# Redirect requests with rules

> Send visitors from one path or hostname to another address with redirect rules on a web proxy.

Source: https://docs.coritan.com/proxies/web-proxies/redirect-rules/

In the dashboard:

- /dashboard/proxies/web/…/redirects: https://www.coritan.com/dashboard/proxies/web

A web proxy's **Redirects** tab holds two kinds of redirect. *Redirect rules* send the paths they match to another address, and every other request still reaches the origin. A *whole-domain redirect* answers every request for the name, and the edge never contacts the origin.

## Before you begin

- The web proxy is on your [Edge Proxy](https://www.coritan.com/dashboard/proxies/web) list ([Create a web proxy](/proxies/web-proxies/create-a-web-proxy/)).
- Decide where each redirect goes: a full URL, such as `https://www.example.com/new-page`, or a path on the same name, such as `/new-page`.

## Add a redirect rule

1. In the dashboard, go to [Edge Proxy](https://www.coritan.com/dashboard/proxies/web), select the web proxy and select the **Redirects** tab.
2. On the **Path redirects** card, select **New rule…**.
3. Choose the **Match**: **Exact path**, **Path prefix** or **Regular expression** ([How rules match](#how-rules-match)).
4. Enter the **Source path**, such as `/old-page`.
5. Enter the **Destination**: a full URL, or a path on this name that starts with a slash.
6. Choose the **Status code**. **301 Moved permanently** and **308 Permanent redirect** tell browsers and search engines that the move is permanent. **302 Found** and **307 Temporary redirect** say it is temporary.
7. Set the **Priority**. The edge checks rules with a higher priority first.
8. Leave **Keep the query string** on to add the visitor's query string to the destination.
9. Select **Create rule**.

### How rules match

The edge checks the enabled rules from the highest priority down, and the first rule that matches answers. Give rules that can match the same path different priorities, because the edge can check two rules with the same priority in either order.

A rule tests the request's path only. The query string takes no part in the match, and the edge reads the path as the visitor sent it, so a space is `%20`.

**Exact path**
: The path must equal the source path, letter case included. `/old-page` matches neither `/old-page/` nor `/Old-Page`.

**Path prefix**
: Every path that starts with the source path matches. `/old-blog` matches `/old-blog/post-1` and also `/old-blogroll`, so end the source path with a slash, such as `/old-blog/`, to match one folder only. Every matching path goes to the same destination, and the edge does not add the rest of the path to it.

**Regular expression**
: The edge tests the pattern against the start of the path, with Python's regular expression syntax. End the pattern with `$` to match the whole path. The destination can use the pattern's groups as `\1` or `\g<1>`: with `^/blog/(\d+)/?$` and the destination `/posts/\1`, a request for `/blog/42` goes to `/posts/42`.

A destination that is a path stays on the same name over HTTPS, so `/new-page` sends a visitor on `www.example.com` to `https://www.example.com/new-page`. With **Keep the query string** on, the edge adds the visitor's query string after a `?`, or after a `&` when the destination has a query string already.

Rules answer before the WAF checks a request and before the edge contacts the origin. With **Force HTTPS** on, a plain HTTP request goes to HTTPS first, and the rule then answers the HTTPS request. While the web proxy has a whole-domain redirect, the edge does not check its rules.

## Change or delete a rule

The **Path redirects** table lists the rules from the highest priority down, with the **Source** and its match, the **Destination**, the **Code**, the **Priority** and whether the rule is **Enabled**.

- To turn a rule off or on, use its switch in the **Enabled** column. A disabled rule stays in the list but never matches.
- To change a rule, open its menu, select **Edit rule…**, make the changes and select **Save rule**.
- To delete a rule, open its menu, select **Delete rule…**, then select **Delete rule**. Requests for its path reach the origin again.

> [!CAUTION]
> You cannot undo deleting a rule. To stop a rule for a while, turn it off instead.

## Redirect the whole domain

A whole-domain redirect sends every request for the name to another address, such as `example.com` to `https://www.example.com`. The name that receives the traffic needs its own web proxy or site.

1. On the **Redirects** tab, find the **Whole-domain redirect** card and select **Set redirect**.
2. Enter the **Destination**, a full URL such as `https://www.example.com`.
3. Choose the **Status code**.
4. Leave **Keep the request path** ticked to send each path to the same path at the destination. Untick it to send every request to the destination's home page.
5. Leave **Keep the query string** ticked to keep the visitor's query string.
6. Select **Save redirect**.

The redirect answers before **Force HTTPS** and before any redirect rule. The card then describes the redirect. **Edit** changes it, and **Remove** stops it, so requests reach the origin again.

## Result

- The dashboard confirms `Redirect rule created.`, `Redirect rule updated.` or `Redirect rule deleted.` for a rule, and `Whole-domain redirect saved.` or `Whole-domain redirect removed.` for the whole-domain redirect.
- A matching request gets the status code you chose, with the destination in its `Location` header.

## Troubleshooting

`Enter a source path.` or `Enter a destination.`
: The field is empty. Fill it in.

`Source paths start with a slash, such as /old-page.`
: Exact and prefix rules take a path, such as `/old-page`, and never a full URL. To redirect a whole name, use [Redirect the whole domain](#redirect-the-whole-domain).

`The regular expression does not compile.`
: The pattern has a syntax error, such as a bracket that is never closed. Correct it.

`The destination is a full URL (https://…) or a path on this domain (/…).`
: Start the destination with `https://`, `http://` or `/`.

`The destination is a full URL, such as https://www.example.com.`
: A whole-domain redirect needs a full URL that starts with `https://` or `http://`.

A rule never matches
: Check that the rule is enabled, and that the path matches letter for letter. A rule with a higher priority can answer first, and no rule answers while a whole-domain redirect is set. A regular expression that uses syntax Python does not read, such as the named group `(?<id>…)`, never matches: write `(?P<id>…)` instead.

Visitors go round in a loop
: The destination matches the rule's own source, such as a prefix rule for `/docs` that sends visitors to `/docs/new`. Use an exact rule, end a regular expression with `$`, or choose a destination outside the source path.

Visitors still get a redirect you changed or deleted
: Browsers keep `301` and `308` redirects and follow them without asking again. Clear the browser's cache to test, and use `302` or `307` while you try a rule out.

## Related

- [How web proxies work](/proxies/web-proxies/)
- [Change a web proxy's origin](/proxies/web-proxies/change-the-origin/)
- [Change a web proxy's settings](/proxies/web-proxies/settings/)

## With the API

List a web proxy's rules with `GET /api/v1/proxy/routes/{route_id}/redirect-rules`. The answer is a list, from the highest priority down:

```bash
curl https://api.coritan.com/api/v1/proxy/routes/31/redirect-rules \
  -H "Authorization: Bearer $CORITAN_TOKEN"
```

```json
[
  {
    "id": 7,
    "source_pattern": "/old-page",
    "match_type": "exact",
    "target_url": "/new-page",
    "status_code": 301,
    "preserve_query": true,
    "priority": 10,
    "enabled": true,
    "created_at": "2026-09-02 08:15:40"
  }
]
```

Add a rule with `POST /api/v1/proxy/routes/{route_id}/redirect-rules`. `source_pattern` and `target_url` are required. `match_type` is `exact`, `prefix` or `regex`, `exact` by default. `status_code` is `301`, `302`, `307` or `308`, `301` by default. `preserve_query` and `enabled` are `true` by default, and `priority` is `0`.

```bash
curl -X POST https://api.coritan.com/api/v1/proxy/routes/31/redirect-rules \
  -H "Authorization: Bearer $CORITAN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"source_pattern": "^/blog/(\\d+)/?$", "match_type": "regex", "target_url": "/posts/\\1", "status_code": 308, "priority": 20}'
```

```json
{"id": 8, "message": "Redirect rule created"}
```

The API does not check the source path or the destination the way the dashboard does. Start an exact or prefix source path with a slash, make sure the edge can read a regular expression, and send a destination that is a full URL or a path.

Change a rule with `PATCH /api/v1/proxy/routes/{route_id}/redirect-rules/{rule_id}`, with only the fields you change. It answers `{"message": "Redirect rule updated"}`, and `No fields to update` when the body holds none. Delete a rule with `DELETE` on the same path, which answers `{"message": "Redirect rule deleted"}`:

```bash
curl -X DELETE https://api.coritan.com/api/v1/proxy/routes/31/redirect-rules/8 \
  -H "Authorization: Bearer $CORITAN_TOKEN"
```

A `match_type` or `status_code` outside the lists answers `400` with `match_type must be exact, prefix, or regex` or `status_code must be 301, 302, 307, or 308`. A web proxy that is not on your account answers `404` with `Route not found`.

The whole-domain redirect is part of the web proxy itself. Set it with `PATCH /api/v1/proxy/routes/{route_id}` and the `redirect_to`, `redirect_status_code`, `redirect_preserve_path` and `redirect_preserve_query` fields, and remove it with an empty `redirect_to` ([Change a web proxy's origin](/proxies/web-proxies/change-the-origin/#with-the-api)):

```bash
curl -X PATCH https://api.coritan.com/api/v1/proxy/routes/31 \
  -H "Authorization: Bearer $CORITAN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"redirect_to": "https://www.example.com", "redirect_status_code": 301, "redirect_preserve_path": true}'
```

A web proxy that only redirects needs no origin. Create it with `redirect_to` in place of `upstream_host` ([Create a web proxy](/proxies/web-proxies/create-a-web-proxy/#with-the-api)).

## API

- `GET /api/v1/proxy/routes/{route_id}/redirect-rules`: List redirect rules for a route you own (https://docs.coritan.com/api/reference/client/reverse-proxy/#op-get-api-v1-proxy-routes-route-id-redirect-rules)
- `POST /api/v1/proxy/routes/{route_id}/redirect-rules`: Create a redirect rule for a route you own (https://docs.coritan.com/api/reference/client/reverse-proxy/#op-post-api-v1-proxy-routes-route-id-redirect-rules)
- `PATCH /api/v1/proxy/routes/{route_id}/redirect-rules/{rule_id}`: Update a redirect rule for a route you own (https://docs.coritan.com/api/reference/client/reverse-proxy/#op-patch-api-v1-proxy-routes-route-id-redirect-rules-rule-id)
- `DELETE /api/v1/proxy/routes/{route_id}/redirect-rules/{rule_id}`: Delete a redirect rule for a route you own (https://docs.coritan.com/api/reference/client/reverse-proxy/#op-delete-api-v1-proxy-routes-route-id-redirect-rules-rule-id)
