Repository: swaggest/rest
Pull request #22 (2021-01-30 20:59:22)

Fix Route function to avoid middleware duplication

github-actions[bot]: ### Unit Test Coverage
total:	(statements)	81.1%
<details><summary>Coverage diff with base branch</summary>

```diff

```
</details>
<!-- Sticky Pull Request Commentunit-test -->
codecov[bot]: # [Codecov](https://codecov.io/gh/swaggest/rest/pull/22?src=pr&el=h1) Report
> Merging [#22](https://codecov.io/gh/swaggest/rest/pull/22?src=pr&el=desc) (9dca65e) into [master](https://codecov.io/gh/swaggest/rest/commit/b7e7c076f27ec5016e15cfff9a020eae8ade32c5?el=desc) (b7e7c07) will **increase** coverage by `0.01%`.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/swaggest/rest/pull/22/graphs/tree.svg?width=650&height=150&src=pr&token=OpLHxxPdmn)](https://codecov.io/gh/swaggest/rest/pull/22?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master      #22      +/-   ##
==========================================
+ Coverage   73.29%   73.31%   +0.01%     
==========================================
  Files          26       26              
  Lines        1483     1484       +1     
==========================================
+ Hits         1087     1088       +1     
  Misses        250      250              
  Partials      146      146              
```

| Flag | Coverage Δ | |
|---|---|---|
| unittests | `73.31% <100.00%> (+0.01%)` | :arrow_up: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags#carryforward-flags-in-the-pull-request-comment) to find out more.

| [Impacted Files](https://codecov.io/gh/swaggest/rest/pull/22?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [chirouter/wrapper.go](https://codecov.io/gh/swaggest/rest/pull/22/diff?src=pr&el=tree#diff-Y2hpcm91dGVyL3dyYXBwZXIuZ28=) | `100.00% <100.00%> (ø)` | |
| [nethttp/wrap.go](https://codecov.io/gh/swaggest/rest/pull/22/diff?src=pr&el=tree#diff-bmV0aHR0cC93cmFwLmdv) | `59.25% <100.00%> (+1.56%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/swaggest/rest/pull/22?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/swaggest/rest/pull/22?src=pr&el=footer). Last update [b7e7c07...9dca65e](https://codecov.io/gh/swaggest/rest/pull/22?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

github-actions[bot]: ### Benchmark Result
<details><summary>Benchmark diff with base branch</summary>

```
Using vendor
name                                    old time/op    new time/op    delta
pkg:github.com/swaggest/rest/jsonschema goos:linux goarch:amd64
RequestValidator_ValidateRequestData-2    1.68µs ± 2%    1.31µs ± 1%  -21.86%  (p=0.016 n=5+4)
pkg:github.com/swaggest/rest/request goos:linux goarch:amd64
Decoder_Decode-2                           940ns ± 3%     699ns ± 2%  -25.60%  (p=0.008 n=5+5)
DecoderFunc_Decode-2                      2.65µs ± 3%    2.03µs ± 3%  -23.59%  (p=0.008 n=5+5)
Decoder_Decode_json-2                     30.9µs ± 1%    23.7µs ± 2%  -23.36%  (p=0.008 n=5+5)
Decoder_Decode_queryObject-2              6.67µs ± 1%    5.00µs ± 2%  -25.00%  (p=0.008 n=5+5)
Decoder_Decode_jsonParam-2                2.43µs ± 6%    1.84µs ± 2%  -24.30%  (p=0.008 n=5+5)
DecoderFactory_SetDecoderFunc-2           2.15µs ± 2%    1.64µs ± 1%  -24.10%  (p=0.008 n=5+5)
pkg:github.com/swaggest/rest/response/gzip goos:linux goarch:amd64
Middleware-2                              14.9µs ± 1%    10.9µs ± 2%  -26.93%  (p=0.008 n=5+5)
Middleware_control-2                      4.39µs ± 3%    3.44µs ± 9%  -21.49%  (p=0.008 n=5+5)

name                                    old alloc/op   new alloc/op   delta
pkg:github.com/swaggest/rest/jsonschema goos:linux goarch:amd64
RequestValidator_ValidateRequestData-2    2.50kB ± 0%    2.50kB ± 0%     ~     (all equal)
pkg:github.com/swaggest/rest/request goos:linux goarch:amd64
Decoder_Decode-2                            448B ± 0%      448B ± 0%     ~     (all equal)
DecoderFunc_Decode-2                      1.51kB ± 0%    1.51kB ± 0%     ~     (all equal)
Decoder_Decode_json-2                     12.4kB ± 0%    12.4kB ± 0%     ~     (all equal)
Decoder_Decode_queryObject-2              2.00kB ± 0%    2.00kB ± 0%     ~     (all equal)
Decoder_Decode_jsonParam-2                  752B ± 0%      752B ± 0%     ~     (all equal)
DecoderFactory_SetDecoderFunc-2           1.02kB ± 0%    1.02kB ± 0%     ~     (all equal)
pkg:github.com/swaggest/rest/response/gzip goos:linux goarch:amd64
Middleware-2                              1.14kB ± 3%    1.14kB ± 5%     ~     (p=0.690 n=5+5)
Middleware_control-2                      11.2kB ± 0%    11.2kB ± 0%     ~     (all equal)

name                                    old allocs/op  new allocs/op  delta
pkg:github.com/swaggest/rest/jsonschema goos:linux goarch:amd64
RequestValidator_ValidateRequestData-2      8.00 ± 0%      8.00 ± 0%     ~     (all equal)
pkg:github.com/swaggest/rest/request goos:linux goarch:amd64
Decoder_Decode-2                            4.00 ± 0%      4.00 ± 0%     ~     (all equal)
DecoderFunc_Decode-2                        12.0 ± 0%      12.0 ± 0%     ~     (all equal)
Decoder_Decode_json-2                        169 ± 0%       169 ± 0%     ~     (all equal)
Decoder_Decode_queryObject-2                36.0 ± 0%      36.0 ± 0%     ~     (all equal)
Decoder_Decode_jsonParam-2                  12.0 ± 0%      12.0 ± 0%     ~     (all equal)
DecoderFactory_SetDecoderFunc-2             16.0 ± 0%      16.0 ± 0%     ~     (all equal)
pkg:github.com/swaggest/rest/response/gzip goos:linux goarch:amd64
Middleware-2                                11.0 ± 0%      11.0 ± 0%     ~     (all equal)
Middleware_control-2                        9.00 ± 0%      9.00 ± 0%     ~     (all equal)
```
</details>

### Examples Benchmark Result
<details><summary>Benchmark diff with base branch</summary>

```
Using vendor
name                    old time/op    new time/op    delta
pkg:github.com/swaggest/rest/_examples/advanced goos:linux goarch:amd64
_directGzip-2             36.9µs ± 1%    29.6µs ± 3%  -19.97%  (p=0.008 n=5+5)
_directGzipHead-2         36.6µs ± 3%    29.1µs ± 2%  -20.58%  (p=0.008 n=5+5)
_noDirectGzip-2            168µs ± 4%     128µs ± 2%  -23.91%  (p=0.008 n=5+5)
_directGzip_decode-2       600µs ± 2%     475µs ± 4%  -20.90%  (p=0.008 n=5+5)
_noDirectGzip_decode-2     166µs ± 1%     133µs ± 5%  -19.74%  (p=0.008 n=5+5)
_jsonBody-2               45.5µs ± 1%    35.7µs ± 4%  -21.41%  (p=0.008 n=5+5)
_jsonBodyValidation-2     69.8µs ± 1%    55.4µs ± 3%  -20.68%  (p=0.008 n=5+5)
_outputHeaders-2          36.4µs ± 3%    28.2µs ± 3%  -22.45%  (p=0.008 n=5+5)
_validation-2             66.4µs ± 1%    52.5µs ± 5%  -20.97%  (p=0.008 n=5+5)
pkg:github.com/swaggest/rest/_examples/task-api/internal/infra/nethttp goos:linux goarch:amd64
_notFoundSrv-2            43.7µs ± 3%    33.3µs ± 2%  -23.71%  (p=0.008 n=5+5)
_ok-2                     48.2µs ± 2%    35.1µs ± 3%  -27.17%  (p=0.008 n=5+5)
_invalidBody-2            64.1µs ± 3%    48.4µs ± 3%  -24.41%  (p=0.008 n=5+5)

name                    old B:rcvd/op  new B:rcvd/op  delta
pkg:github.com/swaggest/rest/_examples/advanced goos:linux goarch:amd64
_directGzip-2                639 ± 0%       639 ± 0%     ~     (all equal)
_directGzipHead-2            183 ± 0%       183 ± 0%     ~     (all equal)
_noDirectGzip-2            1.04k ± 0%     1.04k ± 0%     ~     (all equal)
_directGzip_decode-2         639 ± 0%       639 ± 0%     ~     (all equal)
_noDirectGzip_decode-2     1.04k ± 0%     1.04k ± 0%     ~     (all equal)
_jsonBody-2                  194 ± 0%       194 ± 0%     ~     (all equal)
_jsonBodyValidation-2        194 ± 0%       194 ± 0%     ~     (all equal)
_outputHeaders-2             155 ± 0%       155 ± 0%     ~     (all equal)
_validation-2                177 ± 0%       177 ± 0%     ~     (all equal)
pkg:github.com/swaggest/rest/_examples/task-api/internal/infra/nethttp goos:linux goarch:amd64
_notFoundSrv-2               337 ± 0%       337 ± 0%     ~     (all equal)
_ok-2                        359 ± 0%       359 ± 0%     ~     (all equal)
_invalidBody-2               435 ± 0%       435 ± 0%     ~     (all equal)

name                    old B:sent/op  new B:sent/op  delta
pkg:github.com/swaggest/rest/_examples/advanced goos:linux goarch:amd64
_directGzip-2                103 ± 0%       103 ± 0%     ~     (all equal)
_directGzipHead-2            104 ± 0%       104 ± 0%     ~     (all equal)
_noDirectGzip-2              117 ± 0%       117 ± 0%     ~     (all equal)
_directGzip_decode-2         116 ± 0%       116 ± 0%     ~     (all equal)
_noDirectGzip_decode-2       130 ± 0%       130 ± 0%     ~     (all equal)
_jsonBody-2                  181 ± 0%       181 ± 0%     ~     (all equal)
_jsonBodyValidation-2        192 ± 0%       192 ± 0%     ~     (all equal)
_outputHeaders-2            77.0 ± 0%      77.0 ± 0%     ~     (all equal)
_validation-2                170 ± 0%       170 ± 0%     ~     (all equal)
pkg:github.com/swaggest/rest/_examples/task-api/internal/infra/nethttp goos:linux goarch:amd64
_notFoundSrv-2              74.0 ± 0%      74.0 ± 0%     ~     (all equal)
_ok-2                       74.0 ± 0%      74.0 ± 0%     ~     (all equal)
_invalidBody-2               137 ± 0%       137 ± 0%     ~     (all equal)

name                    old rps        new rps        delta
pkg:github.com/swaggest/rest/_examples/advanced goos:linux goarch:amd64
_directGzip-2              27.1k ± 1%     33.8k ± 3%  +24.96%  (p=0.008 n=5+5)
_directGzipHead-2          27.3k ± 3%     34.4k ± 2%  +25.88%  (p=0.008 n=5+5)
_noDirectGzip-2            5.96k ± 4%     7.83k ± 2%  +31.39%  (p=0.008 n=5+5)
_directGzip_decode-2       1.67k ± 2%     2.11k ± 5%  +26.52%  (p=0.008 n=5+5)
_noDirectGzip_decode-2     6.01k ± 1%     7.50k ± 4%  +24.73%  (p=0.008 n=5+5)
_jsonBody-2                22.0k ± 1%     28.0k ± 4%  +27.32%  (p=0.008 n=5+5)
_jsonBodyValidation-2      14.3k ± 1%     18.1k ± 3%  +26.09%  (p=0.008 n=5+5)
_outputHeaders-2           27.5k ± 3%     35.5k ± 3%  +28.95%  (p=0.008 n=5+5)
_validation-2              15.1k ± 1%     19.1k ± 5%  +26.68%  (p=0.008 n=5+5)
pkg:github.com/swaggest/rest/_examples/task-api/internal/infra/nethttp goos:linux goarch:amd64
_notFoundSrv-2             22.9k ± 3%     30.0k ± 2%  +31.08%  (p=0.008 n=5+5)
_ok-2                      20.7k ± 2%     28.5k ± 3%  +37.33%  (p=0.008 n=5+5)
_invalidBody-2             15.6k ± 3%     20.7k ± 3%  +32.26%  (p=0.008 n=5+5)

name                    old alloc/op   new alloc/op   delta
pkg:github.com/swaggest/rest/_examples/advanced goos:linux goarch:amd64
_directGzip-2             3.82kB ± 0%    3.81kB ± 0%   -0.20%  (p=0.008 n=5+5)
_directGzipHead-2         3.82kB ± 0%    3.81kB ± 0%   -0.15%  (p=0.008 n=5+5)
_noDirectGzip-2           5.90kB ±16%    5.84kB ±21%     ~     (p=1.000 n=5+5)
_directGzip_decode-2       403kB ± 0%     402kB ± 0%   -0.03%  (p=0.032 n=5+5)
_noDirectGzip_decode-2    5.14kB ± 7%    5.21kB ± 8%     ~     (p=0.690 n=5+5)
_jsonBody-2               5.94kB ± 0%    5.93kB ± 0%   -0.15%  (p=0.008 n=5+5)
_jsonBodyValidation-2     18.2kB ± 0%    18.2kB ± 0%   -0.04%  (p=0.016 n=4+5)
_outputHeaders-2          3.60kB ± 0%    3.59kB ± 0%   -0.21%  (p=0.008 n=5+5)
_validation-2             16.1kB ± 0%    16.1kB ± 0%     ~     (p=0.063 n=5+5)
pkg:github.com/swaggest/rest/_examples/task-api/internal/infra/nethttp goos:linux goarch:amd64
_notFoundSrv-2            5.60kB ± 0%    4.77kB ± 0%  -14.92%  (p=0.008 n=5+5)
_ok-2                     5.51kB ± 0%    4.68kB ± 0%  -15.22%  (p=0.029 n=4+4)
_invalidBody-2            9.53kB ± 3%    8.59kB ± 0%   -9.89%  (p=0.016 n=5+4)

name                    old allocs/op  new allocs/op  delta
pkg:github.com/swaggest/rest/_examples/advanced goos:linux goarch:amd64
_directGzip-2               39.0 ± 0%      39.0 ± 0%     ~     (all equal)
_directGzipHead-2           39.0 ± 0%      39.0 ± 0%     ~     (all equal)
_noDirectGzip-2             46.8 ± 4%      46.4 ± 3%     ~     (p=1.000 n=5+5)
_directGzip_decode-2         496 ± 0%       496 ± 0%     ~     (p=0.444 n=5+5)
_noDirectGzip_decode-2      47.0 ± 0%      47.0 ± 0%     ~     (all equal)
_jsonBody-2                 56.0 ± 0%      56.0 ± 0%     ~     (all equal)
_jsonBodyValidation-2        143 ± 0%       143 ± 0%     ~     (all equal)
_outputHeaders-2            34.0 ± 0%      34.0 ± 0%     ~     (all equal)
_validation-2                130 ± 0%       130 ± 0%     ~     (all equal)
pkg:github.com/swaggest/rest/_examples/task-api/internal/infra/nethttp goos:linux goarch:amd64
_notFoundSrv-2              62.0 ± 0%      51.0 ± 0%  -17.74%  (p=0.008 n=5+5)
_ok-2                       58.0 ± 0%      47.0 ± 0%  -18.97%  (p=0.029 n=4+4)
_invalidBody-2               108 ± 0%        97 ± 0%  -10.19%  (p=0.029 n=4+4)
```
</details>
<!-- Sticky Pull Request Commentbench -->

Patch:
diff --git a/chirouter/wrapper.go b/chirouter/wrapper.go
index b0d7b81..bb73eb9 100644
--- a/chirouter/wrapper.go
+++ b/chirouter/wrapper.go
@@ -69,7 +69,7 @@ func (r *Wrapper) Route(pattern string, fn func(r chi.Router)) chi.Router {
 		fn(subRouter)
 	}
 
-	r.Mount(pattern, subRouter)
+	r.Router.Mount(pattern, subRouter)
 
 	return subRouter
 }
diff --git a/nethttp/wrap.go b/nethttp/wrap.go
index 1dc86de..a0133d0 100644
--- a/nethttp/wrap.go
+++ b/nethttp/wrap.go
@@ -21,6 +21,7 @@ func WrapHandler(h http.Handler, mw ...func(http.Handler) http.Handler) http.Han
 		h = &wrappedHandler{
 			Handler: w,
 			wrapped: h,
+			mwName:  runtime.FuncForPC(reflect.ValueOf(mw[i]).Pointer()).Name(),
 		}
 	}
 
@@ -81,4 +82,5 @@ var handlerType = reflect.TypeOf((*http.Handler)(nil)).Elem()
 type wrappedHandler struct {
 	http.Handler
 	wrapped http.Handler
+	mwName  string
 }


Test patch:
diff --git a/chirouter/wrapper_test.go b/chirouter/wrapper_test.go
index d4a1cbc..1f55b3b 100644
--- a/chirouter/wrapper_test.go
+++ b/chirouter/wrapper_test.go
@@ -42,14 +42,15 @@ func TestNewWrapper(t *testing.T) {
 		return http.HandlerFunc(handler.ServeHTTP)
 	})
 
-	r.Use(func(handler http.Handler) http.Handler {
-		var foo interface{ Foo() }
-		if nethttp.HandlerAs(handler, &foo) {
-			return HandlerWithBar{Handler: handler}
-		}
+	mw := func(handler http.Handler) http.Handler {
+		var bar interface{ Bar() }
 
-		return handler
-	})
+		assert.False(t, nethttp.HandlerAs(handler, &bar))
+
+		return HandlerWithBar{Handler: handler}
+	}
+
+	r.Use(mw)
 
 	r.Group(func(r chi.Router) {
 		r.Method(http.MethodPost,
@@ -62,6 +63,8 @@ func TestNewWrapper(t *testing.T) {
 		)
 	})
 
+	r.Mount("/mount", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {}))
+
 	r.Route("/deeper/", func(r chi.Router) {
 		r.Use(func(handler http.Handler) http.Handler {
 			return handler
@@ -82,11 +85,13 @@ func TestNewWrapper(t *testing.T) {
 		r.Handle("/bar", http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {}))
 	})
 
-	req, err := http.NewRequest(http.MethodPost, "/baz/123/", nil)
-	require.NoError(t, err)
+	for _, u := range []string{"/baz/123/", "/deeper/foo", "/mount/abc"} {
+		req, err := http.NewRequest(http.MethodPost, u, nil)
+		require.NoError(t, err)
 
-	rw := httptest.NewRecorder()
-	r.ServeHTTP(rw, req)
+		rw := httptest.NewRecorder()
+		r.ServeHTTP(rw, req)
 
-	assert.Equal(t, "bar", rw.Body.String())
+		assert.Equal(t, "bar", rw.Body.String(), u)
+	}
 }