refactor: addressing review
- moved to separate utility function - return Bad Request error - improved escaping of values passed via URL path
Marcin Rataj committed
Mar 18, 2021 at 21:15 UTC
b81b7549d34e0b549c0035286bdd02b2be50030c
1 file changed
+38
-22
core/corehttp/gateway_handler.go
+38
-22
@@ -39,7 +39,17 @@ var onlyAscii = regexp.MustCompile("[[:^ascii:]]")
39
40
// HTML-based redirect for errors which can be recovered from, but we want
41
// to provide hint to people that they should fix things on their end.
42
-var redirectTemplate = template.Must(template.New("redirect").Parse(`<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><meta http-equiv="refresh" content="10;url={{.RedirectURL}}" /><link rel="canonical" href="{{.RedirectURL}}" /></head><body><pre>{{.ErrorMsg}}</pre><pre>(if a redirect does not happen in 10 seconds, use "{{.SuggestedPath}}" instead)</pre></body></html>`))
42
+var redirectTemplate = template.Must(template.New("redirect").Parse(`<!DOCTYPE html>
43
+<html>
44
+ <head>
45
+ <meta charset="utf-8">
46
+ <meta http-equiv="refresh" content="10;url={{.RedirectURL}}" />
47
+ <link rel="canonical" href="{{.RedirectURL}}" />
48
+ </head>
49
+ <body>
50
+ <pre>{{.ErrorMsg}}</pre><pre>(if a redirect does not happen in 10 seconds, use "{{.SuggestedPath}}" instead)</pre>
51
+ </body>
52
+</html>`))
53
54
type redirectTemplateData struct {
55
RedirectURL string
@@ -228,27 +238,9 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request
238
239
parsedPath := ipath.New(urlPath)
240
if pathErr := parsedPath.IsValid(); pathErr != nil {
231
- // Attempt to fix redundant /ipfs/ namespace as long as resulting
232
- // 'intended' path is valid. This is in case gremlins were tickled
233
- // wrong way and user ended up at /ipfs/ipfs/{cid} or /ipfs/ipns/{id}
234
- // like in bafybeien3m7mdn6imm425vc2s22erzyhbvk5n3ofzgikkhmdkh5cuqbpbq
235
- // :^))
236
- intendedPath := ipath.New(strings.TrimPrefix(urlPath, "/ipfs"))
237
- if err := intendedPath.IsValid(); err == nil {
238
- intendedURL := strings.Replace(r.URL.String(), urlPath, intendedPath.String(), 1)
239
- // return HTML that
240
- // - points at correct canonical path via <link> header
241
- // - displays error
242
- // - redirects to intendedURL after a delay
243
- err = redirectTemplate.Execute(w, redirectTemplateData{
244
- RedirectURL: intendedURL,
245
- SuggestedPath: intendedPath.String(),
246
- ErrorMsg: pathErr.Error(),
247
- })
248
- if err != nil {
249
- internalWebError(w, err)
250
- return
251
- }
241
+ if fixErr := fixupSuperfluousNamespace(w, r, pathErr, urlPath); fixErr == nil {
242
+ // the error was due to redundant namespace, which we were able to fix
243
+ // by returning error/redirect page, nothing left to do here
244
return
245
}
246
// unable to fix path, returning error
@@ -816,3 +808,27 @@ func preferred404Filename(acceptHeaders []string) (string, string, error) {
808
809
return "", "", fmt.Errorf("there is no 404 file for the requested content types")
810
}
811
+
812
+// Attempt to fix redundant /ipfs/ namespace as long as resulting
813
+// 'intended' path is valid. This is in case gremlins were tickled
814
+// wrong way and user ended up at /ipfs/ipfs/{cid} or /ipfs/ipns/{id}
815
+// like in bafybeien3m7mdn6imm425vc2s22erzyhbvk5n3ofzgikkhmdkh5cuqbpbq :^))
816
+func fixupSuperfluousNamespace(w http.ResponseWriter, r *http.Request, pathErr error, urlPath string) error {
817
+ intendedPath := ipath.New(strings.TrimPrefix(urlPath, "/ipfs"))
818
+ err := intendedPath.IsValid()
819
+ if err != nil {
820
+ // not a superfluous namespace
821
+ return err
822
+ }
823
+ intendedURL := strings.Replace(r.URL.String(), urlPath, intendedPath.String(), 1)
824
+ // return HTTP 400 (Bad Request) with HTML error page that:
825
+ // - points at correct canonical path via <link> header
826
+ // - displays human-readable error
827
+ // - redirects to intendedURL after a short delay
828
+ w.WriteHeader(http.StatusBadRequest)
829
+ return redirectTemplate.Execute(w, redirectTemplateData{
830
+ RedirectURL: intendedURL,
831
+ SuggestedPath: intendedPath.String(),
832
+ ErrorMsg: fmt.Sprintf("invalid path: %q should be %q", urlPath, intendedPath.String()),
833
+ })
834
+}