Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: remove support for legacy ipfs-404.html #509

Merged
merged 1 commit into from
Nov 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ The following emojis are used to highlight certain changes:
### Changed

### Removed
* 🛠 `boxo/gateway`: removed support for undocumented legacy `ipfs-404.html`. Use [`_redirects`](https://specs.ipfs.tech/http-gateways/web-redirects-file/) instead.

### Fixed

Expand Down
40 changes: 0 additions & 40 deletions gateway/gateway_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,46 +93,6 @@ func TestGatewayGet(t *testing.T) {
}
}

func TestPretty404(t *testing.T) {
ts, backend, root := newTestServerAndNode(t, nil, "pretty-404.car")
t.Logf("test server url: %s", ts.URL)

host := "example.net"
backend.namesys["/ipns/"+host] = newMockNamesysItem(path.FromCid(root), 0)

for _, test := range []struct {
path string
accept string
status int
text string
}{
{"/ipfs-404.html", "text/html", http.StatusOK, "Custom 404"},
{"/nope", "text/html", http.StatusNotFound, "Custom 404"},
{"/nope", "text/*", http.StatusNotFound, "Custom 404"},
{"/nope", "*/*", http.StatusNotFound, "Custom 404"},
{"/nope", "application/json", http.StatusNotFound, fmt.Sprintf("failed to resolve /ipns/example.net/nope: no link named \"nope\" under %s\n", root.String())},
{"/deeper/nope", "text/html", http.StatusNotFound, "Deep custom 404"},
{"/deeper/", "text/html", http.StatusOK, ""},
{"/deeper", "text/html", http.StatusOK, ""},
{"/nope/nope", "text/html", http.StatusNotFound, "Custom 404"},
} {
testName := fmt.Sprintf("%s %s", test.path, test.accept)
t.Run(testName, func(t *testing.T) {
req := mustNewRequest(t, "GET", ts.URL+test.path, nil)
req.Header.Add("Accept", test.accept)
req.Host = host
resp := mustDo(t, req)
defer resp.Body.Close()
require.Equal(t, test.status, resp.StatusCode)
body, err := io.ReadAll(resp.Body)
require.NoError(t, err)
if test.text != "" {
require.Equal(t, test.text, string(body))
}
})
}
}

func TestHeaders(t *testing.T) {
t.Parallel()

Expand Down
10 changes: 0 additions & 10 deletions gateway/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -770,16 +770,6 @@ func (i *handler) handleWebRequestErrors(w http.ResponseWriter, r *http.Request,
}
}

// if Accept is text/html, see if ipfs-404.html is present
// This logic isn't documented and will likely be removed at some point.
// Any 404 logic in _redirects above will have already run by this time, so it's really an extra fall back
// PLEASE do not use this for new websites,
// follow https://docs.ipfs.tech/how-to/websites-on-ipfs/redirects-and-custom-404s/ instead.
if i.serveLegacy404IfPresent(w, r, immutableContentPath, logger) {
logger.Debugw("served legacy 404")
return path.ImmutablePath{}, false
}

err = fmt.Errorf("failed to resolve %s: %w", debugStr(contentPath.String()), err)
i.webError(w, r, err, http.StatusInternalServerError)
return path.ImmutablePath{}, false
Expand Down
70 changes: 0 additions & 70 deletions gateway/handler_unixfs__redirects.go
Original file line number Diff line number Diff line change
Expand Up @@ -240,73 +240,3 @@ func hasOriginIsolation(r *http.Request) bool {

return false
}

// Deprecated: legacy ipfs-404.html files are superseded by _redirects file
// This is provided only for backward-compatibility, until websites migrate
// to 404s managed via _redirects file (https://github.com/ipfs/specs/pull/290)
func (i *handler) serveLegacy404IfPresent(w http.ResponseWriter, r *http.Request, imPath path.ImmutablePath, logger *zap.SugaredLogger) bool {
resolved404File, resolved404FileSize, ctype, err := i.searchUpTreeFor404(r, imPath)
if err != nil {
return false
}
defer resolved404File.Close()

logger.Debugw("using pretty 404 file", "path", imPath)
w.Header().Set("Content-Type", ctype)
w.Header().Set("Content-Length", strconv.FormatInt(resolved404FileSize, 10))
w.WriteHeader(http.StatusNotFound)
_, err = io.CopyN(w, resolved404File, resolved404FileSize)
return err == nil
}

func (i *handler) searchUpTreeFor404(r *http.Request, imPath path.ImmutablePath) (io.ReadCloser, int64, string, error) {
filename404, ctype, err := preferred404Filename(r.Header.Values("Accept"))
if err != nil {
return nil, 0, "", err
}

pathComponents := strings.Split(imPath.String(), "/")

for idx := len(pathComponents); idx >= 3; idx-- {
pretty404 := gopath.Join(append(pathComponents[0:idx], filename404)...)
parsed404Path, err := path.NewPath("/" + pretty404)
if err != nil {
break
}
imparsed404Path, err := path.NewImmutablePath(parsed404Path)
if err != nil {
break
}

_, getResp, err := i.backend.Get(r.Context(), imparsed404Path)
if err != nil {
continue
}
if getResp.bytes == nil {
// Close the response here if not returning bytes, otherwise it's the caller's responsibility to close the io.ReadCloser
getResp.Close()
return nil, 0, "", fmt.Errorf("found a pretty 404 but it was not a file")
}
return getResp.bytes, getResp.bytesSize, ctype, nil
}

return nil, 0, "", fmt.Errorf("no pretty 404 in any parent folder")
}

func preferred404Filename(acceptHeaders []string) (string, string, error) {
// If we ever want to offer a 404 file for a different content type
// then this function will need to parse q weightings, but for now
// the presence of anything matching HTML is enough.
for _, acceptHeader := range acceptHeaders {
accepted := strings.Split(acceptHeader, ",")
for _, spec := range accepted {
contentType := strings.SplitN(spec, ";", 1)[0]
switch contentType {
case "*/*", "text/*", "text/html":
return "ipfs-404.html", "text/html", nil
}
}
}

return "", "", fmt.Errorf("there is no 404 file for the requested content types")
}
Binary file removed gateway/testdata/pretty-404.car
Binary file not shown.
Loading