ronantakizawa/codereview-bench huggingface dataset:
Repository: labstack/echo
File: middleware/rewrite.go (Go)

Code before:
// Rewrite returns a Rewrite middleware.
//
// Rewrite middleware rewrites the URL path based on the provided rules.
func Rewrite(rules map[string]string) echo.MiddlewareFunc {
	c := DefaultRewriteConfig
	c.Rules = rules
	return RewriteWithConfig(c)
}

// RewriteWithConfig returns a Rewrite middleware with config.
// See: `Rewrite()`.
func RewriteWithConfig(config RewriteConfig) echo.MiddlewareFunc {
	// Defaults
	if config.Rules == nil {
		panic("echo: rewrite middleware requires url path rewrite rules")
	}
	if config.Skipper == nil {
		config.Skipper = DefaultBodyDumpConfig.Skipper
	}
	config.rulesRegex = map[*regexp.Regexp]string{}

	// Initialize
	for k, v := range config.Rules {
		k = regexp.QuoteMeta(k)
		k = strings.Replace(k, `\*`, "(.*)", -1)
		k = strings.Replace(k, `\^`, "^", -1)
		k = k + "$"
		if strings.HasPrefix(k, "/") {
			k = "^" + k
		}
		config.rulesRegex[regexp.MustCompile(k)] = v
	}

	return func(next echo.HandlerFunc) echo.HandlerFunc {
		return func(c echo.Context) (err error) {
			if config.Skipper(c) {
				return next(c)
			}

			req := c.Request()

			// Rewrite
			for k, v := range config.rulesRegex {
				replacer := captureTokens(k, req.URL.Path)
				if replacer != nil {
					req.URL.Path = replacer.Replace(v)
					break
				}
			}
			return next(c)
		}

Review comment (suggestion):
The caret (^) does only make sense at the beginning of the string. Better to use hasPrefix here to detect a leading caret.

Code after:
// Rewrite returns a Rewrite middleware.
//
// Rewrite middleware rewrites the URL path based on the provided rules.
func Rewrite(rules map[string]string) echo.MiddlewareFunc {
	c := DefaultRewriteConfig
	c.Rules = rules
	return RewriteWithConfig(c)
}

// RewriteWithConfig returns a Rewrite middleware with config.
// See: `Rewrite()`.
func RewriteWithConfig(config RewriteConfig) echo.MiddlewareFunc {
	// Defaults
	if config.Rules == nil {
		panic("echo: rewrite middleware requires url path rewrite rules")
	}
	if config.Skipper == nil {
		config.Skipper = DefaultBodyDumpConfig.Skipper
	}
	config.rulesRegex = map[*regexp.Regexp]string{}

	// Initialize
	for k, v := range config.Rules {
		k = regexp.QuoteMeta(k)
		k = strings.Replace(k, `\*`, "(.*)", -1)
		if strings.HasPrefix(k, `\^`) {
			k = strings.Replace(k, `\^`, "^", -1)
		}
		k = k + "$"
		config.rulesRegex[regexp.MustCompile(k)] = v
	}

	return func(next echo.HandlerFunc) echo.HandlerFunc {
		return func(c echo.Context) (err error) {
			if config.Skipper(c) {
				return next(c)
			}

			req := c.Request()

			// Rewrite
			for k, v := range config.rulesRegex {
				replacer := captureTokens(k, req.URL.Path)
				if replacer != nil {
					req.URL.Path = replacer.Replace(v)
					break
				}
			}
			return next(c)
		}
	}
Repository: labstack/echo
File: middleware/rewrite.go (Go)

Code before:
// Rewrite middleware rewrites the URL path based on the provided rules.
func Rewrite(rules map[string]string) echo.MiddlewareFunc {
	c := DefaultRewriteConfig
	c.Rules = rules
	return RewriteWithConfig(c)
}

// RewriteWithConfig returns a Rewrite middleware with config.
// See: `Rewrite()`.
func RewriteWithConfig(config RewriteConfig) echo.MiddlewareFunc {
	// Defaults
	if config.Rules == nil {
		panic("echo: rewrite middleware requires url path rewrite rules")
	}
	if config.Skipper == nil {
		config.Skipper = DefaultBodyDumpConfig.Skipper
	}
	config.rulesRegex = map[*regexp.Regexp]string{}

	// Initialize
	for k, v := range config.Rules {
		k = regexp.QuoteMeta(k)
		k = strings.Replace(k, `\*`, "(.*)", -1)
		k = strings.Replace(k, `\^`, "^", -1)
		k = k + "$"
		if strings.HasPrefix(k, "/") {
			k = "^" + k
		}
		config.rulesRegex[regexp.MustCompile(k)] = v
	}

	return func(next echo.HandlerFunc) echo.HandlerFunc {
		return func(c echo.Context) (err error) {
			if config.Skipper(c) {
				return next(c)
			}

			req := c.Request()

			// Rewrite
			for k, v := range config.rulesRegex {
				replacer := captureTokens(k, req.URL.Path)
				if replacer != nil {
					req.URL.Path = replacer.Replace(v)
					break
				}
			}
			return next(c)
		}
	}
}

Review comment (suggestion):
That may change current behaviour, as we did not prefix with caret before and might break existing code if Iäm not mistaken. That would require a v5 label then.

Is this really needed, if we allow the caret now.

Code after:
// Rewrite middleware rewrites the URL path based on the provided rules.
func Rewrite(rules map[string]string) echo.MiddlewareFunc {
	c := DefaultRewriteConfig
	c.Rules = rules
	return RewriteWithConfig(c)
}

// RewriteWithConfig returns a Rewrite middleware with config.
// See: `Rewrite()`.
func RewriteWithConfig(config RewriteConfig) echo.MiddlewareFunc {
	// Defaults
	if config.Rules == nil {
		panic("echo: rewrite middleware requires url path rewrite rules")
	}
	if config.Skipper == nil {
		config.Skipper = DefaultBodyDumpConfig.Skipper
	}
	config.rulesRegex = map[*regexp.Regexp]string{}

	// Initialize
	for k, v := range config.Rules {
		k = regexp.QuoteMeta(k)
		k = strings.Replace(k, `\*`, "(.*)", -1)
		if strings.HasPrefix(k, `\^`) {
			k = strings.Replace(k, `\^`, "^", -1)
		}
		k = k + "$"
		config.rulesRegex[regexp.MustCompile(k)] = v
	}

	return func(next echo.HandlerFunc) echo.HandlerFunc {
		return func(c echo.Context) (err error) {
			if config.Skipper(c) {
				return next(c)
			}

			req := c.Request()

			// Rewrite
			for k, v := range config.rulesRegex {
				replacer := captureTokens(k, req.URL.Path)
				if replacer != nil {
					req.URL.Path = replacer.Replace(v)
					break
				}
			}
			return next(c)
		}
	}
}
Repository: labstack/echo
File: echo.go (Go)

Code before:
		h = applyMiddleware(h, e.middleware...)
	} else {
		h = func(c Context) error {
			e.findRouter(r.Host).Find(r.Method, r.URL.EscapedPath(), c)
			h := c.Handler()
			h = applyMiddleware(h, e.middleware...)
			return h(c)
		}
		h = applyMiddleware(h, e.premiddleware...)
	}

	// Execute chain
	if err := h(c); err != nil {
		e.HTTPErrorHandler(err, c)
	}

	// Release context
	e.pool.Put(c)
}

// Start starts an HTTP server.
func (e *Echo) Start(address string) error {
	e.startupMu.Lock()
	e.Server.Addr = address
	if err := e.configureServer(e.Server); err != nil {
		e.startupMu.Unlock()
		return err
	}
	e.startupMu.Unlock()
	return e.serve()
}

// StartTLS starts an HTTPS server.
// If `certFile` or `keyFile` is `string` the values are treated as file paths.
// If `certFile` or `keyFile` is `[]byte` the values are treated as the certificate or key as-is.
func (e *Echo) StartTLS(address string, certFile, keyFile interface{}) (err error) {
	e.startupMu.Lock()
	var cert []byte
	if cert, err = filepathOrContent(certFile); err != nil {
		e.startupMu.Unlock()
		return
	}

	var key []byte
	if key, err = filepathOrContent(keyFile); err != nil {
		e.startupMu.Unlock()
		return
	}

	s := e.TLSServer
	s.TLSConfig = new(tls.Config)

Review comment (suggestion):
As these function are not called very often we can use `defer` to improve readability.

Code after:
		h = applyMiddleware(h, e.middleware...)
	} else {
		h = func(c Context) error {
			e.findRouter(r.Host).Find(r.Method, r.URL.EscapedPath(), c)
			h := c.Handler()
			h = applyMiddleware(h, e.middleware...)
			return h(c)
		}
		h = applyMiddleware(h, e.premiddleware...)
	}

	// Execute chain
	if err := h(c); err != nil {
		e.HTTPErrorHandler(err, c)
	}

	// Release context
	e.pool.Put(c)
}

// Start starts an HTTP server.
func (e *Echo) Start(address string) error {
	e.startupMutex.Lock()
	e.Server.Addr = address
	if err := e.configureServer(e.Server); err != nil {
		e.startupMutex.Unlock()
		return err
	}
	e.startupMutex.Unlock()
	return e.serve()
}

// StartTLS starts an HTTPS server.
// If `certFile` or `keyFile` is `string` the values are treated as file paths.
// If `certFile` or `keyFile` is `[]byte` the values are treated as the certificate or key as-is.
func (e *Echo) StartTLS(address string, certFile, keyFile interface{}) (err error) {
	e.startupMutex.Lock()
	var cert []byte
	if cert, err = filepathOrContent(certFile); err != nil {
		e.startupMutex.Unlock()
		return
	}

	var key []byte
	if key, err = filepathOrContent(keyFile); err != nil {
		e.startupMutex.Unlock()
		return
	}

	s := e.TLSServer
	s.TLSConfig = new(tls.Config)
Repository: labstack/echo
File: middleware/timeout.go (Go)

Code before:
func TimeoutWithConfig(config TimeoutConfig) echo.MiddlewareFunc {
	// Defaults
	if config.Skipper == nil {
		config.Skipper = DefaultTimeoutConfig.Skipper
	}

	return func(next echo.HandlerFunc) echo.HandlerFunc {
		return func(c echo.Context) error {
			if config.Skipper(c) || config.Timeout == 0 {
				return next(c)
			}

			ctx, cancel := context.WithTimeout(c.Request().Context(), config.Timeout)
			defer cancel()

			// this does a deep clone of the context, wondering if there is a better way to do this?
			c.SetRequest(c.Request().Clone(ctx))

			done := make(chan error, 1)
			go func() {
				done <- next(c)
			}()

			select {
			case <-ctx.Done():
				return c.JSON(http.StatusGatewayTimeout, ctx.Err())
			case err := <-done:
				return err
			}
		}
	}
}


Review comment (suggestion):
This is assuming that user of this middleware is returning JSON responses, which couldn't be true. Please add a function to TimeoutConfig that will be called here as an error handler. 

Code after:
// and handles the control to the centralized HTTPErrorHandler.
func Timeout() echo.MiddlewareFunc {
	return TimeoutWithConfig(DefaultTimeoutConfig)
}

// TimeoutWithConfig returns a Timeout middleware with config.
// See: `Timeout()`.
func TimeoutWithConfig(config TimeoutConfig) echo.MiddlewareFunc {
	// Defaults
	if config.Skipper == nil {
		config.Skipper = DefaultTimeoutConfig.Skipper
	}

	return func(next echo.HandlerFunc) echo.HandlerFunc {
		return func(c echo.Context) error {
			if config.Skipper(c) || config.Timeout == 0 {
				return next(c)
			}

			ctx, cancel := context.WithTimeout(c.Request().Context(), config.Timeout)
			defer cancel()

			// this does a deep clone of the context, wondering if there is a better way to do this?
			c.SetRequest(c.Request().Clone(ctx))

			done := make(chan error, 1)
			go func() {
				// This goroutine will keep running even if this middleware times out and
				// will be stopped when ctx.Done() is called down the next(c) call chain
				done <- next(c)
			}()

			select {
			case <-ctx.Done():
				if config.ErrorHandler != nil {
					return config.ErrorHandler(ctx.Err(), c)
				}
				return ctx.Err()
			case err := <-done:
				return err
			}
		}
	}
}
Repository: labstack/echo
File: middleware/timeout.go (Go)

Code before:
	}

	return func(next echo.HandlerFunc) echo.HandlerFunc {
		return func(c echo.Context) error {
			if config.Skipper(c) || config.Timeout == 0 {
				return next(c)
			}

			ctx, cancel := context.WithTimeout(c.Request().Context(), config.Timeout)
			defer cancel()

			// this does a deep clone of the context, wondering if there is a better way to do this?
			c.SetRequest(c.Request().Clone(ctx))

			done := make(chan error, 1)
			go func() {
				done <- next(c)
			}()

			select {
			case <-ctx.Done():
				return c.JSON(http.StatusGatewayTimeout, ctx.Err())
			case err := <-done:
				return err
			}
		}
	}
}


Review comment (suggestion):
Maybe you can add a comment like the one below here to help new Gophers that starts their journeys with Echo and are not still used to the use of contexts:
```
			// This goroutine will not stop even this middleware timeouts,
			// unless someone in the next(c) call chain handle ctx.Done() properly
```

Code after:

// TimeoutWithConfig returns a Timeout middleware with config.
// See: `Timeout()`.
func TimeoutWithConfig(config TimeoutConfig) echo.MiddlewareFunc {
	// Defaults
	if config.Skipper == nil {
		config.Skipper = DefaultTimeoutConfig.Skipper
	}

	return func(next echo.HandlerFunc) echo.HandlerFunc {
		return func(c echo.Context) error {
			if config.Skipper(c) || config.Timeout == 0 {
				return next(c)
			}

			ctx, cancel := context.WithTimeout(c.Request().Context(), config.Timeout)
			defer cancel()

			// this does a deep clone of the context, wondering if there is a better way to do this?
			c.SetRequest(c.Request().Clone(ctx))

			done := make(chan error, 1)
			go func() {
				// This goroutine will keep running even if this middleware times out and
				// will be stopped when ctx.Done() is called down the next(c) call chain
				done <- next(c)
			}()

			select {
			case <-ctx.Done():
				if config.ErrorHandler != nil {
					return config.ErrorHandler(ctx.Err(), c)
				}
				return ctx.Err()
			case err := <-done:
				return err
			}
		}
	}
}
Repository: labstack/echo
File: middleware/timeout_test.go (Go)

Code before:
// +build go1.13

package middleware

import (
	"errors"
	"github.com/labstack/echo/v4"
	"github.com/stretchr/testify/assert"
	"net/http"
	"net/http/httptest"
	"reflect"
	"testing"
	"time"
)

func TestTimeout(t *testing.T) {
	e := echo.New()

	t.Run("Skipper", func(t *testing.T) {
		t.Parallel()
		m := TimeoutWithConfig(TimeoutConfig{
			Skipper: func(context echo.Context) bool {
				return true
			},
		})

		req := httptest.NewRequest(http.MethodGet, "/", nil)
		rec := httptest.NewRecorder()
		c := e.NewContext(req, rec)

		err := m(func(c echo.Context) error {
			assert.NotEqual(t, "*context.timerCtx", reflect.TypeOf(c.Request().Context()).String())
			return nil
		})(c)

		assert.NoError(t, err)
	})

	t.Run("Is cancelable", func(t *testing.T) {
		t.Parallel()
		m := TimeoutWithConfig(TimeoutConfig{
			Timeout: time.Minute,
		})


Review comment (suggestion):
Maybe this is just a matter of taste, but I prefer a separate test function for every test. Also it is more aligned with the other test implementations on Echo.

Code after:
// +build go1.13

package middleware

import (
	"context"
	"errors"
	"github.com/labstack/echo/v4"
	"github.com/stretchr/testify/assert"
	"net/http"
	"net/http/httptest"
	"net/url"
	"reflect"
	"strings"
	"testing"
	"time"
)

func TestTimeoutSkipper(t *testing.T) {
	t.Parallel()
	m := TimeoutWithConfig(TimeoutConfig{
		Skipper: func(context echo.Context) bool {
			return true
		},
	})

	req := httptest.NewRequest(http.MethodGet, "/", nil)
	rec := httptest.NewRecorder()

	e := echo.New()
	c := e.NewContext(req, rec)

	err := m(func(c echo.Context) error {
		assert.NotEqual(t, "*context.timerCtx", reflect.TypeOf(c.Request().Context()).String())
		return nil
	})(c)

	assert.NoError(t, err)
}

func TestTimeoutWithTimeout0(t *testing.T) {
	t.Parallel()
	m := TimeoutWithConfig(TimeoutConfig{
		Timeout: 0,
Repository: labstack/echo
File: middleware/timeout_test.go (Go)

Code before:
// +build go1.13

package middleware

import (
	"errors"
	"github.com/labstack/echo/v4"
	"github.com/stretchr/testify/assert"
	"net/http"
	"net/http/httptest"
	"reflect"
	"testing"
	"time"
)

func TestTimeout(t *testing.T) {
	e := echo.New()

	t.Run("Skipper", func(t *testing.T) {
		t.Parallel()
		m := TimeoutWithConfig(TimeoutConfig{
			Skipper: func(context echo.Context) bool {
				return true
			},
		})

		req := httptest.NewRequest(http.MethodGet, "/", nil)
		rec := httptest.NewRecorder()
		c := e.NewContext(req, rec)

		err := m(func(c echo.Context) error {
			assert.NotEqual(t, "*context.timerCtx", reflect.TypeOf(c.Request().Context()).String())
			return nil
		})(c)

		assert.NoError(t, err)
	})

	t.Run("Is cancelable", func(t *testing.T) {
		t.Parallel()
		m := TimeoutWithConfig(TimeoutConfig{

Review comment (suggestion):
Please add a test that checks that the request is properly cloned.
Maybe you can use this Context methods that relies on the inner http.Request
* QueryString()
* FormValue(name)
* Cookie(name)

Code after:
// +build go1.13

package middleware

import (
	"context"
	"errors"
	"github.com/labstack/echo/v4"
	"github.com/stretchr/testify/assert"
	"net/http"
	"net/http/httptest"
	"net/url"
	"reflect"
	"strings"
	"testing"
	"time"
)

func TestTimeoutSkipper(t *testing.T) {
	t.Parallel()
	m := TimeoutWithConfig(TimeoutConfig{
		Skipper: func(context echo.Context) bool {
			return true
		},
	})

	req := httptest.NewRequest(http.MethodGet, "/", nil)
	rec := httptest.NewRecorder()

	e := echo.New()
	c := e.NewContext(req, rec)

	err := m(func(c echo.Context) error {
		assert.NotEqual(t, "*context.timerCtx", reflect.TypeOf(c.Request().Context()).String())
		return nil
	})(c)

	assert.NoError(t, err)
}

func TestTimeoutWithTimeout0(t *testing.T) {
Repository: labstack/echo
File: middleware/timeout_test.go (Go)

Code before:
	})

	req := httptest.NewRequest(http.MethodGet, "/", nil)
	rec := httptest.NewRecorder()

	e := echo.New()
	c := e.NewContext(req, rec)

	err := m(func(c echo.Context) error {
		time.Sleep(time.Minute)
		return nil
	})(c)

	assert.EqualError(t, err, context.DeadlineExceeded.Error())
}

func TestTimeoutTestRequestClone(t *testing.T) {
	t.Parallel()
	req := httptest.NewRequest(http.MethodPost, "/uri?query=value", strings.NewReader(url.Values{"form": {"value"}}.Encode()))
	req.AddCookie(&http.Cookie{Name: "cookie", Value: "value"})
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	rec := httptest.NewRecorder()

	m := TimeoutWithConfig(TimeoutConfig{
		Timeout: time.Second,
		ErrorHandler: func(err error, c echo.Context) error {
			assert.EqualError(t, err, context.DeadlineExceeded.Error())
			
			// Cookie test
			cookie, err := c.Request().Cookie("cookie")
			if assert.NoError(t, err) {
				assert.EqualValues(t, "cookie", cookie.Name)
				assert.EqualValues(t, "value", cookie.Value)
			}

			// Form values
			if assert.NoError(t, c.Request().ParseForm()) {
				assert.EqualValues(t, "value", c.Request().FormValue("form"))
			}

			// Query string
			assert.EqualValues(t, "value", c.Request().URL.Query()["query"][0])
			return errors.New("err")
		},
	})

	e := echo.New()
	c := e.NewContext(req, rec)

	err := m(func(c echo.Context) error {
		time.Sleep(time.Minute)

Review comment (suggestion):
Instead of checking if the Context was cloned properly on the ErrorHandler function, do it directly on the HandlerFunc that you pass to the Timeout middleware. It'll be more straightforward and probably the test will run faster because is not needed to wait for the timeout

Code after:
	})

	req := httptest.NewRequest(http.MethodGet, "/", nil)
	rec := httptest.NewRecorder()

	e := echo.New()
	c := e.NewContext(req, rec)

	err := m(func(c echo.Context) error {
		time.Sleep(time.Minute)
		return nil
	})(c)

	assert.EqualError(t, err, context.DeadlineExceeded.Error())
}

func TestTimeoutTestRequestClone(t *testing.T) {
	t.Parallel()
	req := httptest.NewRequest(http.MethodPost, "/uri?query=value", strings.NewReader(url.Values{"form": {"value"}}.Encode()))
	req.AddCookie(&http.Cookie{Name: "cookie", Value: "value"})
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	rec := httptest.NewRecorder()

	m := TimeoutWithConfig(TimeoutConfig{
		// Timeout has to be defined or the whole flow for timeout middleware will be skipped
		Timeout: time.Second,
	})

	e := echo.New()
	c := e.NewContext(req, rec)

	err := m(func(c echo.Context) error {
		// Cookie test
		cookie, err := c.Request().Cookie("cookie")
		if assert.NoError(t, err) {
			assert.EqualValues(t, "cookie", cookie.Name)
			assert.EqualValues(t, "value", cookie.Value)
		}

		// Form values
		if assert.NoError(t, c.Request().ParseForm()) {
			assert.EqualValues(t, "value", c.Request().FormValue("form"))
		}

		// Query string
		assert.EqualValues(t, "value", c.Request().URL.Query()["query"][0])
		return nil
	})(c)

	assert.NoError(t, err)
Repository: labstack/echo
File: middleware/proxy_test.go (Go)

Code before:
			"^/a/*":     "/v1/$1",
			"^/b/*/c/*": "/v2/$2/$1",
			"^/c/*/*":   "/v3/$2",
		},
		RegexRewrite: map[*regexp.Regexp]string{
			regexp.MustCompile("^/x/.+?/(.*)"):   "/v4/$1",
			regexp.MustCompile("^/y/(.+?)/(.*)"): "/v5/$2/$1",
		},
	}))

	testCases := []struct {
		requestPath string
		statusCode  int
		expectPath  string
	}{
		{"/unmatched", http.StatusOK, "/unmatched"},
		{"/a/test", http.StatusOK, "/v1/test"},
		{"/b/foo/c/bar/baz", http.StatusOK, "/v2/bar/baz/foo"},
		{"/c/ignore/test", http.StatusOK, "/v3/test"},
		{"/c/ignore1/test/this", http.StatusOK, "/v3/test/this"},
		{"/x/ignore/test", http.StatusOK, "/v4/test"},
		{"/y/foo/bar", http.StatusOK, "/v5/bar/foo"},
	}

	for _, tc := range testCases {
		req.URL, _ = url.Parse(tc.requestPath)
		rec = httptest.NewRecorder()
		e.ServeHTTP(rec, req)
		assert.Equal(t, tc.expectPath, req.URL.EscapedPath())
		assert.Equal(t, tc.statusCode, rec.Code)
	}
}


Review comment (bug):
Just a sidenote here.  I'm JetBrains GoLand user and it has a feature that allows you to execute single testcase from table driven testcases when test is written as

```go
	for _, tc := range testCases {
		t.Run(tc.requestPath, func(t *testing.T) {
```

![idea_debug_test](https://user-images.githubusercontent.com/2320301/107216471-7c779000-6a15-11eb-916c-c539818426e1.png)


Code after:
			"^/a/*":     "/v1/$1",
			"^/b/*/c/*": "/v2/$2/$1",
			"^/c/*/*":   "/v3/$2",
		},
		RegexRewrite: map[*regexp.Regexp]string{
			regexp.MustCompile("^/x/.+?/(.*)"):   "/v4/$1",
			regexp.MustCompile("^/y/(.+?)/(.*)"): "/v5/$2/$1",
		},
	}))

	testCases := []struct {
		requestPath string
		statusCode  int
		expectPath  string
	}{
		{"/unmatched", http.StatusOK, "/unmatched"},
		{"/a/test", http.StatusOK, "/v1/test"},
		{"/b/foo/c/bar/baz", http.StatusOK, "/v2/bar/baz/foo"},
		{"/c/ignore/test", http.StatusOK, "/v3/test"},
		{"/c/ignore1/test/this", http.StatusOK, "/v3/test/this"},
		{"/x/ignore/test", http.StatusOK, "/v4/test"},
		{"/y/foo/bar", http.StatusOK, "/v5/bar/foo"},
	}


	for _, tc := range testCases {
		t.Run(tc.requestPath, func(t *testing.T) {
			req.URL, _ = url.Parse(tc.requestPath)
			rec = httptest.NewRecorder()
			e.ServeHTTP(rec, req)
			assert.Equal(t, tc.expectPath, req.URL.EscapedPath())
			assert.Equal(t, tc.statusCode, rec.Code)
		})
	}
}