Skip to content

Commit

Permalink
Merge pull request #7 from ipfs-shipyard/jj-remove-force
Browse files Browse the repository at this point in the history
Remove forced redirects support
  • Loading branch information
Justin Johnson authored Aug 12, 2022
2 parents 8b4073e + 711f372 commit 37f4710
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 47 deletions.
7 changes: 2 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ Currently this is a subset of Netlify's [redirects format](https://www.netlify.c
The details of the supported functionality are still in flux and will eventually be included in a [spec](https://github.com/ipfs/specs).

## Format
Currently only supports `from`, `to`, `status` and `force`.
Currently only supports `from`, `to` and `status`.

```
from to [status][!]
from to [status]
```

## Example
Expand Down Expand Up @@ -39,9 +39,6 @@ from to [status][!]

# Proxying
/api/* https://api.example.com/:splat 200

# Forced redirect, even if the from path exists
/app/* /app/index.html 200!
```

---
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ go 1.17
require (
github.com/pkg/errors v0.9.1
github.com/tj/assert v0.0.3
github.com/ucarion/urlpath v0.0.0-20200424170820-7ccc79b76bbb
)

require (
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/tj/assert v0.0.3 h1:Df/BlaZ20mq6kuai7f5z2TvPFiwC3xaWJSDQNiIS3Rk=
github.com/tj/assert v0.0.3/go.mod h1:Ne6X72Q+TB1AteidzQncjw9PabbMp4PBMZ1k+vd1Pvk=
github.com/ucarion/urlpath v0.0.0-20200424170820-7ccc79b76bbb h1:Ywfo8sUltxogBpFuMOFRrrSifO788kAFxmvVw31PtQQ=
github.com/ucarion/urlpath v0.0.0-20200424170820-7ccc79b76bbb/go.mod h1:ikPs9bRWicNw3S7XpJ8sK/smGwU9WcSVU3dy9qahYBM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Expand Down
39 changes: 26 additions & 13 deletions redirects.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ package redirects

import (
"bufio"
"fmt"
"io"
"net/url"
"strconv"
"strings"

"github.com/pkg/errors"
"github.com/ucarion/urlpath"
)

// A Rule represents a single redirection or rewrite rule.
Expand All @@ -29,10 +31,6 @@ type Rule struct {
// When proxying this field is ignored.
//
Status int

// Force is used to force a rewrite or redirect even
// when a response (or static file) is present.
Force bool
}

// IsRewrite returns true if the rule represents a rewrite (status 200).
Expand Down Expand Up @@ -81,11 +79,11 @@ func Parse(r io.Reader) (rules []Rule, err error) {

// missing dst
if len(fields) <= 1 {
return nil, errors.Wrapf(err, "missing destination path: %q", line)
return nil, fmt.Errorf("missing destination path: %q", line)
}

if len(fields) > 3 {
return nil, errors.Wrapf(err, "must match format `from to [status][!]`")
return nil, fmt.Errorf("must match format `from to [status][!]`")
}

// src and dst
Expand All @@ -97,13 +95,12 @@ func Parse(r io.Reader) (rules []Rule, err error) {

// status
if len(fields) > 2 {
code, force, err := parseStatus(fields[2])
code, err := parseStatus(fields[2])
if err != nil {
return nil, errors.Wrapf(err, "parsing status %q", fields[2])
}

rule.Status = code
rule.Force = force
}

rules = append(rules, rule)
Expand All @@ -118,13 +115,29 @@ func ParseString(s string) ([]Rule, error) {
return Parse(strings.NewReader(s))
}

// parseStatus returns the status code and force when "!" suffix is present.
func parseStatus(s string) (code int, force bool, err error) {
// parseStatus returns the status code.
func parseStatus(s string) (code int, err error) {
if strings.HasSuffix(s, "!") {
force = true
s = strings.Replace(s, "!", "", -1)
// See https://docs.netlify.com/routing/redirects/rewrites-proxies/#shadowing
return -1, fmt.Errorf("forced redirects (or \"shadowing\") are not supported by IPFS gateways")
}

code, err = strconv.Atoi(s)
return
return code, err
}

// ReplacePlaceholders replaces all placeholders from the match in the provided string.
func ReplacePlaceholders(to string, match urlpath.Match) string {
if len(match.Params) > 0 {
for key, value := range match.Params {
to = strings.ReplaceAll(to, ":"+key, value)
}
}

return to
}

// ReplaceSplat replaces all splats from the match in the provided string.
func ReplaceSplat(to string, match urlpath.Match) string {
return strings.ReplaceAll(to, ":splat", match.Trailing)
}
39 changes: 10 additions & 29 deletions redirects_example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,6 @@ func Example() {
# Proxying
/api/* https://api.example.com/:splat 200
# Forcing
/app/* /app/index.html 200!
`))

enc := json.NewEncoder(os.Stdout)
Expand All @@ -43,68 +40,52 @@ func Example() {
// {
// "From": "/home",
// "To": "/",
// "Status": 301,
// "Force": false
// "Status": 301
// },
// {
// "From": "/blog/my-post.php",
// "To": "/blog/my-post",
// "Status": 301,
// "Force": false
// "Status": 301
// },
// {
// "From": "/news",
// "To": "/blog",
// "Status": 301,
// "Force": false
// "Status": 301
// },
// {
// "From": "/google",
// "To": "https://www.google.com",
// "Status": 301,
// "Force": false
// "Status": 301
// },
// {
// "From": "/home",
// "To": "/",
// "Status": 301,
// "Force": false
// "Status": 301
// },
// {
// "From": "/my-redirect",
// "To": "/",
// "Status": 302,
// "Force": false
// "Status": 302
// },
// {
// "From": "/pass-through",
// "To": "/index.html",
// "Status": 200,
// "Force": false
// "Status": 200
// },
// {
// "From": "/ecommerce",
// "To": "/store-closed",
// "Status": 404,
// "Force": false
// "Status": 404
// },
// {
// "From": "/*",
// "To": "/index.html",
// "Status": 200,
// "Force": false
// "Status": 200
// },
// {
// "From": "/api/*",
// "To": "https://api.example.com/:splat",
// "Status": 200,
// "Force": false
// },
// {
// "From": "/app/*",
// "To": "/app/index.html",
// "Status": 200,
// "Force": true
// "Status": 200
// }
// ]
}
11 changes: 11 additions & 0 deletions redirects_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package redirects

import (
"strings"
"testing"

"github.com/tj/assert"
Expand Down Expand Up @@ -56,3 +57,13 @@ func TestRule_IsRewrite(t *testing.T) {
assert.False(t, r.IsRewrite())
})
}

func TestParse(t *testing.T) {
t.Run("with illegal force", func(t *testing.T) {
_, err := Parse(strings.NewReader(`
/home / 301!
`))

assert.Error(t, err, "forced redirects should return an error")
})
}

0 comments on commit 37f4710

Please sign in to comment.