@cryptotaxi247 / kubo / commits / b81b7549d

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 +}