diff --git a/_examples/routing/rewrite/hosts b/_examples/routing/rewrite/hosts index f135219c..d31e56d9 100644 --- a/_examples/routing/rewrite/hosts +++ b/_examples/routing/rewrite/hosts @@ -1,3 +1,4 @@ 127.0.0.1 mydomain.com 127.0.0.1 www.mydomain.com -127.0.0.1 test.mydomain.com \ No newline at end of file +127.0.0.1 test.mydomain.com +127.0.0.1 newtest.mydomain.com diff --git a/_examples/routing/rewrite/main.go b/_examples/routing/rewrite/main.go index 448043e9..9c8bd2c2 100644 --- a/_examples/routing/rewrite/main.go +++ b/_examples/routing/rewrite/main.go @@ -13,17 +13,22 @@ func main() { app.Subdomain("test").Get("/", testIndex) + newtest := app.Subdomain("newtest") + newtest.Get("/", newTestIndex) + newtest.Get("/", newTestAbout) + redirects := rewrite.Load("redirects.yml") app.WrapRouter(redirects) - // http://mydomain.com:8080/seo/about -> http://www.mydomain.com:8080/about - // http://test.mydomain.com:8080 - // http://localhost:8080/seo -> http://localhost:8080 + // http://mydomain.com:8080/seo/about -> http://www.mydomain.com:8080/about + // http://test.mydomain.com:8080 -> http://newtest.mydomain.com:8080 + // http://test.mydomain.com:8080/seo/about -> http://newtest.mydomain.com:8080/about + // http://localhost:8080/seo -> http://localhost:8080 // http://localhost:8080/about - // http://localhost:8080/docs/v12/hello -> http://localhost:8080/docs - // http://localhost:8080/docs/v12some -> http://localhost:8080/docs - // http://localhost:8080/oldsome -> http://localhost:8080 - // http://localhost:8080/oldindex/random -> http://localhost:8080 + // http://localhost:8080/docs/v12/hello -> http://localhost:8080/docs + // http://localhost:8080/docs/v12some -> http://localhost:8080/docs + // http://localhost:8080/oldsome -> http://localhost:8080 + // http://localhost:8080/oldindex/random -> http://localhost:8080 app.Listen(":8080") } @@ -40,7 +45,15 @@ func docs(ctx iris.Context) { } func testIndex(ctx iris.Context) { - ctx.WriteString("Test Subdomain Index") + ctx.WriteString("Test Subdomain Index (This should never be executed, redirects to newtest subdomain)") +} + +func newTestIndex(ctx iris.Context) { + ctx.WriteString("New Test Subdomain Index") +} + +func newTestAbout(ctx iris.Context) { + ctx.WriteString("New Test Subdomain About") } /* More... @@ -49,6 +62,7 @@ rewriteOptions := rewrite.Options{ "301 /seo/(.*) /$1", "301 /docs/v12(.*) /docs", "301 /old(.*) /", + "301 ^(http|https)://test.(.*) $1://newtest.$2", }, PrimarySubdomain: "www", } diff --git a/_examples/routing/rewrite/redirects.yml b/_examples/routing/rewrite/redirects.yml index 86a8ec90..76764b4b 100644 --- a/_examples/routing/rewrite/redirects.yml +++ b/_examples/routing/rewrite/redirects.yml @@ -6,5 +6,7 @@ RedirectMatch: - 301 /docs/v12(.*) /docs # redirects /old(.*) to / - 301 /old(.*) / + # redirects http or https://test.* to http or https://newtest.* + - 301 ^(http|https)://test.(.*) $1://newtest.$2 # redirects root domain to www. PrimarySubdomain: www diff --git a/middleware/rewrite/rewrite.go b/middleware/rewrite/rewrite.go index 3cde921e..9c690888 100644 --- a/middleware/rewrite/rewrite.go +++ b/middleware/rewrite/rewrite.go @@ -8,6 +8,7 @@ import ( "regexp" "strconv" "strings" + "text/template" "github.com/kataras/iris/v12/context" "github.com/kataras/iris/v12/core/router" @@ -176,7 +177,8 @@ func (e *Engine) Rewrite(w http.ResponseWriter, r *http.Request, routeHandler ht for _, rd := range e.redirects { src := r.URL.Path if !rd.isRelativePattern { - src = r.URL.String() + // don't change the request, use a full redirect. + src = context.GetScheme(r) + context.GetHost(r) + r.URL.RequestURI() } if target, ok := rd.matchAndReplace(src); ok { @@ -185,7 +187,14 @@ func (e *Engine) Rewrite(w http.ResponseWriter, r *http.Request, routeHandler ht return } - http.Redirect(w, r, target, rd.code) + if !rd.isRelativePattern { + // this performs better, no need to check query or host, + // the uri already built. + redirectAbs(w, r, target, rd.code) + } else { + http.Redirect(w, r, target, rd.code) + } + return } } @@ -263,3 +272,22 @@ func getPort(hostport string) string { // returns :port, note that this is only return "" } + +func redirectAbs(w http.ResponseWriter, r *http.Request, url string, code int) { + // part of net/http std library. + h := w.Header() + + _, hadCT := h[context.ContentTypeHeaderKey] + + h.Set("Location", url) + if !hadCT && (r.Method == http.MethodGet || r.Method == http.MethodHead) { + h.Set(context.ContentTypeHeaderKey, "text/html; charset=utf-8") + } + w.WriteHeader(code) + + // Shouldn't send the body for POST or HEAD; that leaves GET. + if !hadCT && r.Method == "GET" { + body := "" + http.StatusText(code) + ".\n" + fmt.Fprintln(w, body) + } +}