mirror of
https://github.com/kataras/iris.git
synced 2025-01-23 10:41:03 +01:00
rewrite middleware: add a feature which supports users.json to users?format=json local route redirection
This commit is contained in:
parent
02c85c27cc
commit
95c3c2a951
26
HISTORY.md
26
HISTORY.md
|
@ -365,14 +365,30 @@ Other Improvements:
|
||||||
- New [Rewrite Engine Middleware](https://github.com/kataras/iris/tree/master/middleware/rewrite). Set up redirection rules for path patterns using the syntax we all know. [Example Code](https://github.com/kataras/iris/tree/master/_examples/routing/rewrite).
|
- New [Rewrite Engine Middleware](https://github.com/kataras/iris/tree/master/middleware/rewrite). Set up redirection rules for path patterns using the syntax we all know. [Example Code](https://github.com/kataras/iris/tree/master/_examples/routing/rewrite).
|
||||||
|
|
||||||
```yml
|
```yml
|
||||||
# REDIRECT_CODE PATH_PATTERN TARGET_PATH_REPL
|
RedirectMatch: # REDIRECT_CODE_DIGITS | PATTERN_REGEX | TARGET_REPL
|
||||||
RedirectMatch:
|
# Redirects /seo/* to /*
|
||||||
# redirects /seo/* to /*
|
|
||||||
- 301 /seo/(.*) /$1
|
- 301 /seo/(.*) /$1
|
||||||
# redirects /docs/v12* to /docs
|
|
||||||
|
# Redirects /docs/v12* to /docs
|
||||||
- 301 /docs/v12(.*) /docs
|
- 301 /docs/v12(.*) /docs
|
||||||
# redirects /old(.*) to /
|
|
||||||
|
# Redirects /old(.*) to /
|
||||||
- 301 /old(.*) /
|
- 301 /old(.*) /
|
||||||
|
|
||||||
|
# Redirects http or https://test.* to http or https://newtest.*
|
||||||
|
- 301 ^(http|https)://test.(.*) $1://newtest.$2
|
||||||
|
|
||||||
|
# Handles /*.json or .xml as *?format=json or xml,
|
||||||
|
# without redirect. See /users route.
|
||||||
|
# When Code is 0 then it does not redirect the request,
|
||||||
|
# instead it changes the request URL
|
||||||
|
# and leaves a route handle the request.
|
||||||
|
- 0 /(.*).(json|xml) /$1?format=$2
|
||||||
|
|
||||||
|
# Redirects root domain to www.
|
||||||
|
# Creation of a www subdomain inside the Application is unnecessary,
|
||||||
|
# all requests are handled by the root Application itself.
|
||||||
|
PrimarySubdomain: www
|
||||||
```
|
```
|
||||||
|
|
||||||
- New `TraceRoute bool` on [middleware/logger](https://github.com/kataras/iris/tree/master/middleware/logger) middleware. Displays information about the executed route. Also marks the handlers executed. Screenshot:
|
- New `TraceRoute bool` on [middleware/logger](https://github.com/kataras/iris/tree/master/middleware/logger) middleware. Displays information about the executed route. Also marks the handlers executed. Screenshot:
|
||||||
|
|
|
@ -7,9 +7,11 @@ import (
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
app := iris.New()
|
app := iris.New()
|
||||||
|
|
||||||
app.Get("/", index)
|
app.Get("/", index)
|
||||||
app.Get("/about", about)
|
app.Get("/about", about)
|
||||||
app.Get("/docs", docs)
|
app.Get("/docs", docs)
|
||||||
|
app.Get("/users", listUsers)
|
||||||
|
|
||||||
app.Subdomain("test").Get("/", testIndex)
|
app.Subdomain("test").Get("/", testIndex)
|
||||||
|
|
||||||
|
@ -29,6 +31,7 @@ func main() {
|
||||||
// http://localhost:8080/docs/v12some -> http://localhost:8080/docs
|
// http://localhost:8080/docs/v12some -> http://localhost:8080/docs
|
||||||
// http://localhost:8080/oldsome -> http://localhost:8080
|
// http://localhost:8080/oldsome -> http://localhost:8080
|
||||||
// http://localhost:8080/oldindex/random -> http://localhost:8080
|
// http://localhost:8080/oldindex/random -> http://localhost:8080
|
||||||
|
// http://localhost:8080/users.json -> http://localhost:8080/users?format=json
|
||||||
app.Listen(":8080")
|
app.Listen(":8080")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,8 +47,24 @@ func docs(ctx iris.Context) {
|
||||||
ctx.WriteString("Docs")
|
ctx.WriteString("Docs")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func listUsers(ctx iris.Context) {
|
||||||
|
format := ctx.URLParamDefault("format", "text")
|
||||||
|
/*
|
||||||
|
switch format{
|
||||||
|
case "json":
|
||||||
|
ctx.JSON(response)
|
||||||
|
case "xml":
|
||||||
|
ctx.XML(response)
|
||||||
|
// [...]
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
ctx.Writef("Format: %s", format)
|
||||||
|
}
|
||||||
|
|
||||||
func testIndex(ctx iris.Context) {
|
func testIndex(ctx iris.Context) {
|
||||||
ctx.WriteString("Test Subdomain Index (This should never be executed, redirects to newtest subdomain)")
|
ctx.WriteString(`Test Subdomain Index
|
||||||
|
(This should never be executed,
|
||||||
|
redirects to newtest subdomain)`)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTestIndex(ctx iris.Context) {
|
func newTestIndex(ctx iris.Context) {
|
||||||
|
@ -63,6 +82,7 @@ rewriteOptions := rewrite.Options{
|
||||||
"301 /docs/v12(.*) /docs",
|
"301 /docs/v12(.*) /docs",
|
||||||
"301 /old(.*) /",
|
"301 /old(.*) /",
|
||||||
"301 ^(http|https)://test.(.*) $1://newtest.$2",
|
"301 ^(http|https)://test.(.*) $1://newtest.$2",
|
||||||
|
"0 /(.*).(json|xml) /$1?format=$2",
|
||||||
},
|
},
|
||||||
PrimarySubdomain: "www",
|
PrimarySubdomain: "www",
|
||||||
}
|
}
|
||||||
|
@ -77,5 +97,6 @@ app.Use(rewriteEngine.Handler)
|
||||||
//
|
//
|
||||||
// To make the entire application respect the redirect rules
|
// To make the entire application respect the redirect rules
|
||||||
// you have to wrap the Iris Router and pass the `Rewrite` method instead
|
// you have to wrap the Iris Router and pass the `Rewrite` method instead
|
||||||
// as we did at this example.
|
// as we did at this example:
|
||||||
|
// app.WrapRouter(rewriteEngine.Rewrite)
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,12 +1,24 @@
|
||||||
# REDIRECT_CODE PATH_PATTERN TARGET_PATH_REPL
|
RedirectMatch: # REDIRECT_CODE_DIGITS | PATTERN_REGEX | TARGET_REPL
|
||||||
RedirectMatch:
|
# Redirects /seo/* to /*
|
||||||
# redirects /seo/* to /*
|
|
||||||
- 301 /seo/(.*) /$1
|
- 301 /seo/(.*) /$1
|
||||||
# redirects /docs/v12* to /docs
|
|
||||||
|
# Redirects /docs/v12* to /docs
|
||||||
- 301 /docs/v12(.*) /docs
|
- 301 /docs/v12(.*) /docs
|
||||||
# redirects /old(.*) to /
|
|
||||||
|
# Redirects /old(.*) to /
|
||||||
- 301 /old(.*) /
|
- 301 /old(.*) /
|
||||||
# redirects http or https://test.* to http or https://newtest.*
|
|
||||||
|
# Redirects http or https://test.* to http or https://newtest.*
|
||||||
- 301 ^(http|https)://test.(.*) $1://newtest.$2
|
- 301 ^(http|https)://test.(.*) $1://newtest.$2
|
||||||
# redirects root domain to www.
|
|
||||||
PrimarySubdomain: www
|
# Handle /*.json or .xml as *?format=json or xml,
|
||||||
|
# without redirect. See /users route.
|
||||||
|
# When Code is 0 then it does not redirect the request,
|
||||||
|
# instead it changes the request URL
|
||||||
|
# and leaves a route handle the request.
|
||||||
|
- 0 /(.*).(json|xml) /$1?format=$2
|
||||||
|
|
||||||
|
# Redirects root domain to www.
|
||||||
|
# Creation of a www subdomain inside the Application is unnecessary,
|
||||||
|
# all requests are handled by the root Application itself.
|
||||||
|
PrimarySubdomain: www
|
|
@ -1906,14 +1906,14 @@ func (ctx *Context) AbsoluteURI(s string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Redirect sends a redirect response to the client
|
// Redirect sends a redirect response to the client
|
||||||
// to a specific url or relative path.
|
// of an absolute or relative target URL.
|
||||||
// accepts 2 parameters string and an optional int
|
// It accepts 2 input arguments, a string and an optional integer.
|
||||||
// first parameter is the url to redirect
|
// The first parameter is the target url to redirect.
|
||||||
// second parameter is the http status should send,
|
// The second one is the HTTP status code should be sent
|
||||||
// default is 302 (StatusFound),
|
// among redirection response,
|
||||||
// you can set it to 301 (Permant redirect)
|
// If the second parameter is missing, then it defaults to 302 (StatusFound).
|
||||||
// or 303 (StatusSeeOther) if POST method,
|
// It can be set to 301 (Permant redirect), StatusTemporaryRedirect(307)
|
||||||
// or StatusTemporaryRedirect(307) if that's nessecery.
|
// or 303 (StatusSeeOther) if POST method.
|
||||||
func (ctx *Context) Redirect(urlToRedirect string, statusHeader ...int) {
|
func (ctx *Context) Redirect(urlToRedirect string, statusHeader ...int) {
|
||||||
ctx.StopExecution()
|
ctx.StopExecution()
|
||||||
// get the previous status code given by the end-developer.
|
// get the previous status code given by the end-developer.
|
||||||
|
|
|
@ -187,6 +187,18 @@ func (e *Engine) Rewrite(w http.ResponseWriter, r *http.Request, routeHandler ht
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if rd.noRedirect {
|
||||||
|
u, err := r.URL.Parse(target)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusMisdirectedRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
r.URL = u
|
||||||
|
routeHandler(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if !rd.isRelativePattern {
|
if !rd.isRelativePattern {
|
||||||
// this performs better, no need to check query or host,
|
// this performs better, no need to check query or host,
|
||||||
// the uri already built.
|
// the uri already built.
|
||||||
|
@ -208,6 +220,7 @@ type redirectMatch struct {
|
||||||
target string
|
target string
|
||||||
|
|
||||||
isRelativePattern bool
|
isRelativePattern bool
|
||||||
|
noRedirect bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *redirectMatch) matchAndReplace(src string) (string, bool) {
|
func (r *redirectMatch) matchAndReplace(src string) (string, bool) {
|
||||||
|
@ -241,20 +254,16 @@ func parseRedirectMatchLine(s string) (*redirectMatch, error) {
|
||||||
return nil, fmt.Errorf("redirect match: status code digits: %s: %v", codeStr, err)
|
return nil, fmt.Errorf("redirect match: status code digits: %s: %v", codeStr, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if code <= 0 {
|
|
||||||
code = http.StatusMovedPermanently
|
|
||||||
}
|
|
||||||
|
|
||||||
regex := regexp.MustCompile(pattern)
|
regex := regexp.MustCompile(pattern)
|
||||||
if regex.MatchString(target) {
|
if regex.MatchString(target) {
|
||||||
return nil, fmt.Errorf("redirect match: loop detected: pattern: %s vs target: %s", pattern, target)
|
return nil, fmt.Errorf("redirect match: loop detected: pattern: %s vs target: %s", pattern, target)
|
||||||
}
|
}
|
||||||
|
|
||||||
v := &redirectMatch{
|
v := &redirectMatch{
|
||||||
code: code,
|
code: code,
|
||||||
pattern: regex,
|
pattern: regex,
|
||||||
target: target,
|
target: target,
|
||||||
|
noRedirect: code <= 0,
|
||||||
isRelativePattern: pattern[0] == '/', // search by path.
|
isRelativePattern: pattern[0] == '/', // search by path.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user