# Rewrite Middleware

When the Application's requirements suggests that the redirect rules should be registered in one place then use the [Rewrite Middleware](https://github.com/kataras/iris/tree/main/middleware/rewrite). 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](https://pkg.go.dev/regexp/#example_Regexp_ReplaceAllString).

**Usage**

First of all, you should import the builtin middleware as follows:

```go
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.

```go
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 before `Application.Listen/Run`.

The `"redirects.yml"` file looks like that:

```yaml
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.

```go
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:

| SOURCE                                     | TARGET                                           |
| ------------------------------------------ | ------------------------------------------------ |
| <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://mydomain.com:8080/seo>             | <http://www.mydomain.com:8080>                   |
| <http://mydomain.com:8080/about>           | <http://www.mydomain.com:8080/about>             |
| <http://mydomain.com:8080/docs/v12/hello>  | <http://www.mydomain.com:8080/docs>              |
| <http://mydomain.com:8080/docs/v12some>    | <http://www.mydomain.com:8080/docs>              |
| <http://mydomain.com:8080/oldsome>         | <http://www.mydomain.com:8080>                   |
| <http://mydomain.com:8080/oldindex/random> | <http://www.mydomain.com:8080>                   |
| <http://mydomain.com:8080/users.json>      | <http://www.mydomain.com:8080/users?format=json> |

```go
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](https://support.rackspace.com/how-to/modify-your-hosts-file/) if you don't know how to modify the system's hosts file.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://iris-go.gitbook.io/iris/redirect/rewrite-middleware.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
