Greetings gophers,
Today we'll take a quick look to a rewrite middleware that I've created 2 months ago for the Iris Web Framework.
We all remember the old good times, I assume, most of us used apache mod_rewrite in the past to map pattern with URL paths.
Rewrite is useful for Search engine optimization (SEO). It lets you convert an "ugly" path to a more human-readable one.
Without spending most of your time, let's start, the code speaks for itself.
First of all, install Iris version 12, if you haven't already(!):
go get github.com/kataras/iris/v12@master
The rewrite middleware is a builtin package, so you don't need to install anything else.
The Rewrite Middleware supports rewrite URL path, subdomain or host based on a regular expression search and replace.
The syntax is familiar to the majority of the backend developers out there and it looks like that:
| REDIRECT_CODE_DIGITS | PATTERN_REGEX | TARGET_REPL |
|----------------------|---------------|-------------|
| 301 | /seo/(.*) | /$1 |
The above will redirect all requests from relative path /seo/*
to /*
using the 301 (Moved Permanently)
HTTP Status Code. Learn more about regex.
Usage
First of all, you should import the builtin middleware as follows:
import "github.com/kataras/iris/v12/middleware/rewrite"
There are two ways to load rewrite options in order to parse and register the redirect rules:
1. Through a yaml
or json
file using the Load
function. It is the most common scenario and the simplest one. It panics on parse errors.
func main() {
app := iris.New()
// [...routes]
redirects := rewrite.Load("redirects.yml")
app.WrapRouter(redirects)
app.Listen(":80")
}
It is highly recommended that you should register the Rewrite Middleware as a Router Wrapper through
Application.WrapRouter
right beforeApplication.Listen/Run
.
The "redirects.yml"
file looks like that:
RedirectMatch:
# Redirects /seo/* to /*
- 301 /seo/(.*) /$1
# Redirects /docs/v12* to /docs
- 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
# 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
2. Through code using the New
function. Parse errors can be handled and rules can be programmatically stored.
opts := rewrite.Options{
RedirectMatch: []string{
"301 /seo/(.*) /$1",
"301 /docs/v12(.*) /docs",
"301 /old(.*) /",
"301 ^(http|https)://test.(.*) $1://newtest.$2",
"0 /(.*).(json|xml) /$1?format=$2",
},
PrimarySubdomain: "www",
}
rw, err := rewrite.New(opts)
if err != nil { panic(err) }
app.WrapRouter(rw.Rewrite)
Example
Let's write a simple application which follows the redirect rules of:
package main
import (
"github.com/kataras/iris/v12"
"github.com/kataras/iris/v12/middleware/rewrite"
)
func main() {
app := iris.New()
app.Get("/", index)
app.Get("/about", about)
app.Get("/docs", docs)
app.Get("/users", listUsers)
app.Subdomain("test").Get("/", testIndex)
newtest := app.Subdomain("newtest")
newtest.Get("/", newTestIndex)
newtest.Get("/", newTestAbout)
//
redirects := rewrite.Load("redirects.yml")
app.WrapRouter(redirects)
//
app.Listen(":8080")
}
func index(ctx iris.Context) {
ctx.WriteString("Index")
}
func about(ctx iris.Context) {
ctx.WriteString("About")
}
func docs(ctx iris.Context) {
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) {
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")
}
Hosts File
127.0.0.1 mydomain.com
127.0.0.1 www.mydomain.com
127.0.0.1 test.mydomain.com
127.0.0.1 newtest.mydomain.com
Navigate here if you don't know how to modify the system's hosts file.
Thanks for the reading! Please upvote the Post if you liked it. Feel free to follow my Twitter and GitHub. Have fun and be safe 🦾