From 65acc04c9b7ffa327135939cc4f7275158546aa8 Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Wed, 22 Feb 2023 14:16:16 +0100 Subject: [PATCH] feat: simplify error handling --- gateway/gateway_test.go | 12 ++-- gateway/handler.go | 84 +++++++++++++++++----------- gateway/handler_block.go | 4 +- gateway/handler_car.go | 2 +- gateway/handler_codec.go | 24 ++++---- gateway/handler_ipns_record.go | 10 ++-- gateway/handler_tar.go | 6 +- gateway/handler_unixfs.go | 6 +- gateway/handler_unixfs__redirects.go | 6 +- gateway/handler_unixfs_dir.go | 15 ++--- 10 files changed, 96 insertions(+), 73 deletions(-) diff --git a/gateway/gateway_test.go b/gateway/gateway_test.go index 9cdf6418a6..e9445c438a 100644 --- a/gateway/gateway_test.go +++ b/gateway/gateway_test.go @@ -349,17 +349,17 @@ func TestGatewayGet(t *testing.T) { {"127.0.0.1:8080", "/", http.StatusNotFound, "404 page not found\n"}, {"127.0.0.1:8080", "/" + k.Cid().String(), http.StatusNotFound, "404 page not found\n"}, {"127.0.0.1:8080", k.String(), http.StatusOK, "fnord"}, - {"127.0.0.1:8080", "/ipns/nxdomain.example.com", http.StatusInternalServerError, "ipfs resolve -r /ipns/nxdomain.example.com: " + namesys.ErrResolveFailed.Error() + "\n"}, - {"127.0.0.1:8080", "/ipns/%0D%0A%0D%0Ahello", http.StatusInternalServerError, "ipfs resolve -r /ipns/\\r\\n\\r\\nhello: " + namesys.ErrResolveFailed.Error() + "\n"}, + {"127.0.0.1:8080", "/ipns/nxdomain.example.com", http.StatusInternalServerError, "failed to resolve /ipns/nxdomain.example.com: " + namesys.ErrResolveFailed.Error() + "\n"}, + {"127.0.0.1:8080", "/ipns/%0D%0A%0D%0Ahello", http.StatusInternalServerError, "failed to resolve /ipns/\\r\\n\\r\\nhello: " + namesys.ErrResolveFailed.Error() + "\n"}, {"127.0.0.1:8080", "/ipns/example.com", http.StatusOK, "fnord"}, {"example.com", "/", http.StatusOK, "fnord"}, {"working.example.com", "/", http.StatusOK, "fnord"}, {"double.example.com", "/", http.StatusOK, "fnord"}, {"triple.example.com", "/", http.StatusOK, "fnord"}, - {"working.example.com", k.String(), http.StatusNotFound, "ipfs resolve -r /ipns/working.example.com" + k.String() + ": no link named \"ipfs\" under " + k.Cid().String() + "\n"}, - {"broken.example.com", "/", http.StatusInternalServerError, "ipfs resolve -r /ipns/broken.example.com/: " + namesys.ErrResolveFailed.Error() + "\n"}, - {"broken.example.com", k.String(), http.StatusInternalServerError, "ipfs resolve -r /ipns/broken.example.com" + k.String() + ": " + namesys.ErrResolveFailed.Error() + "\n"}, + {"working.example.com", k.String(), http.StatusNotFound, "failed to resolve /ipns/working.example.com" + k.String() + ": no link named \"ipfs\" under " + k.Cid().String() + "\n"}, + {"broken.example.com", "/", http.StatusInternalServerError, "failed to resolve /ipns/broken.example.com/: " + namesys.ErrResolveFailed.Error() + "\n"}, + {"broken.example.com", k.String(), http.StatusInternalServerError, "failed to resolve /ipns/broken.example.com" + k.String() + ": " + namesys.ErrResolveFailed.Error() + "\n"}, // This test case ensures we don't treat the TLD as a file extension. {"example.man", "/", http.StatusOK, "fnord"}, } { @@ -686,7 +686,7 @@ func TestPretty404(t *testing.T) { {"/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("ipfs resolve -r /ipns/example.net/nope: no link named \"nope\" under %s\n", k.Cid().String())}, + {"/nope", "application/json", http.StatusNotFound, fmt.Sprintf("failed to resolve /ipns/example.net/nope: no link named \"nope\" under %s\n", k.Cid().String())}, {"/deeper/nope", "text/html", http.StatusNotFound, "Deep custom 404"}, {"/deeper/", "text/html", http.StatusOK, ""}, {"/deeper", "text/html", http.StatusOK, ""}, diff --git a/gateway/handler.go b/gateway/handler.go index 82adbe5c39..20177aea52 100644 --- a/gateway/handler.go +++ b/gateway/handler.go @@ -99,7 +99,6 @@ type statusResponseWriter struct { // Custom type for collecting error details to be handled by `webRequestError` type requestError struct { - Message string StatusCode int Err error } @@ -108,9 +107,8 @@ func (r *requestError) Error() string { return r.Err.Error() } -func newRequestError(message string, err error, statusCode int) *requestError { +func newRequestError(err error, statusCode int) *requestError { return &requestError{ - Message: message, Err: err, StatusCode: statusCode, } @@ -372,7 +370,7 @@ func (i *handler) getOrHeadHandler(w http.ResponseWriter, r *http.Request) { // Detect when explicit Accept header or ?format parameter are present responseFormat, formatParams, err := customResponseFormat(r) if err != nil { - webError(w, "error while processing the Accept header", err, http.StatusBadRequest) + webError(w, fmt.Errorf("error while processing the Accept header: %w", err), http.StatusBadRequest) return } trace.SpanFromContext(r.Context()).SetAttributes(attribute.String("ResponseFormat", responseFormat)) @@ -438,7 +436,7 @@ func (i *handler) getOrHeadHandler(w http.ResponseWriter, r *http.Request) { success = i.serveIpnsRecord(r.Context(), w, r, resolvedPath, contentPath, begin, logger) default: // catch-all for unsuported application/vnd.* err := fmt.Errorf("unsupported format %q", responseFormat) - webError(w, "failed to respond with requested content type", err, http.StatusBadRequest) + webError(w, err, http.StatusBadRequest) return } @@ -558,35 +556,48 @@ func (i *handler) buildIpfsRootsHeader(contentPath string, r *http.Request) (str } func webRequestError(w http.ResponseWriter, err *requestError) { - webError(w, err.Message, err.Err, err.StatusCode) + webError(w, err.Err, err.StatusCode) } -func internalWebError(w http.ResponseWriter, err error) { - webError(w, "internalWebError", err, http.StatusInternalServerError) -} - -func webError(w http.ResponseWriter, message string, err error, defaultCode int) { - if _, ok := err.(resolver.ErrNoLink); ok { - webErrorWithCode(w, message, err, http.StatusNotFound) +func webError(w http.ResponseWriter, err error, defaultCode int) { + if isErrNoLink(err) { + webErrorWithCode(w, err, http.StatusNotFound) } else if errors.Is(err, routing.ErrNotFound) || err == routing.ErrNotFound { - webErrorWithCode(w, message, err, http.StatusNotFound) + webErrorWithCode(w, err, http.StatusNotFound) } else if ipld.IsNotFound(err) { - webErrorWithCode(w, message, err, http.StatusNotFound) + webErrorWithCode(w, err, http.StatusNotFound) } else if errors.Is(err, ErrGatewayTimeout) { - webErrorWithCode(w, message, err, http.StatusGatewayTimeout) + webErrorWithCode(w, err, http.StatusGatewayTimeout) } else if errors.Is(err, ErrBadGateway) { - webErrorWithCode(w, message, err, http.StatusBadGateway) + webErrorWithCode(w, err, http.StatusBadGateway) } else if errors.Is(err, context.DeadlineExceeded) || err == context.DeadlineExceeded { - webErrorWithCode(w, message, err, http.StatusRequestTimeout) + webErrorWithCode(w, err, http.StatusRequestTimeout) } else { - webErrorWithCode(w, message, err, defaultCode) + webErrorWithCode(w, err, defaultCode) + } +} + +// isErrNoLink checks if err is a resolver.ErrNoLink. resolver.ErrNoLink +// does not implement a .Is interface and cannot be directly compared to. +// Therefore, errors.Is always returns false with it. +func isErrNoLink(err error) bool { + for { + _, ok := err.(resolver.ErrNoLink) + if ok { + return true + } + + err = errors.Unwrap(err) + if err == nil { + return false + } } } -func webErrorWithCode(w http.ResponseWriter, message string, err error, code int) { - http.Error(w, fmt.Sprintf("%s: %s", message, err), code) +func webErrorWithCode(w http.ResponseWriter, err error, code int) { + http.Error(w, err.Error(), code) if code >= 500 { - log.Warnf("server error: %s: %s", message, err) + log.Warnf("server error: %s", err) } } @@ -749,11 +760,13 @@ func (i *handler) handlePathResolution(w http.ResponseWriter, r *http.Request, r case nil: return resolvedPath, contentPath, true case coreiface.ErrOffline: - webError(w, "ipfs resolve -r "+debugStr(contentPath.String()), err, http.StatusServiceUnavailable) + err = fmt.Errorf("failed to resolve %s: %w", debugStr(contentPath.String()), err) + webError(w, err, http.StatusServiceUnavailable) return nil, nil, false case namesys.ErrResolveFailed: // Note: webError will replace http.StatusBadRequest with StatusNotFound or StatusRequestTimeout if necessary - webError(w, "ipfs resolve -r "+debugStr(contentPath.String()), err, http.StatusInternalServerError) + err = fmt.Errorf("failed to resolve %s: %w", debugStr(contentPath.String()), err) + webError(w, err, http.StatusInternalServerError) return nil, nil, false default: // The path can't be resolved. @@ -780,7 +793,8 @@ func (i *handler) handlePathResolution(w http.ResponseWriter, r *http.Request, r } // Note: webError will replace http.StatusBadRequest with StatusNotFound or StatusRequestTimeout if necessary - webError(w, "ipfs resolve -r "+debugStr(contentPath.String()), err, http.StatusBadRequest) + err = fmt.Errorf("failed to resolve %s: %w", debugStr(contentPath.String()), err) + webError(w, err, http.StatusBadRequest) return nil, nil, false } } @@ -810,8 +824,8 @@ func handleUnsupportedHeaders(r *http.Request) (err *requestError) { // X-Ipfs-Gateway-Prefix was removed (https://github.com/ipfs/kubo/issues/7702) // TODO: remove this after go-ipfs 0.13 ships if prfx := r.Header.Get("X-Ipfs-Gateway-Prefix"); prfx != "" { - err := fmt.Errorf("X-Ipfs-Gateway-Prefix support was removed: https://github.com/ipfs/kubo/issues/7702") - return newRequestError("unsupported HTTP header", err, http.StatusBadRequest) + err := fmt.Errorf("unsupported HTTP header: X-Ipfs-Gateway-Prefix support was removed: https://github.com/ipfs/kubo/issues/7702") + return newRequestError(err, http.StatusBadRequest) } return nil } @@ -824,11 +838,11 @@ func handleProtocolHandlerRedirect(w http.ResponseWriter, r *http.Request, logge if uriParam := r.URL.Query().Get("uri"); uriParam != "" { u, err := url.Parse(uriParam) if err != nil { - webError(w, "failed to parse uri query parameter", err, http.StatusBadRequest) + webError(w, fmt.Errorf("failed to parse uri query parameter: %w", err), http.StatusBadRequest) return true } if u.Scheme != "ipfs" && u.Scheme != "ipns" { - webError(w, "uri query parameter scheme must be ipfs or ipns", err, http.StatusBadRequest) + webError(w, fmt.Errorf("uri query parameter scheme must be ipfs or ipns: %w", err), http.StatusBadRequest) return true } path := u.Path @@ -852,7 +866,7 @@ func handleServiceWorkerRegistration(r *http.Request) (err *requestError) { matched, _ := regexp.MatchString(`^/ip[fn]s/[^/]+$`, r.URL.Path) if matched { err := fmt.Errorf("registration is not allowed for this scope") - return newRequestError("navigator.serviceWorker", err, http.StatusBadRequest) + return newRequestError(fmt.Errorf("navigator.serviceWorker: %w", err), http.StatusBadRequest) } } @@ -877,7 +891,7 @@ func handleSuperfluousNamespace(w http.ResponseWriter, r *http.Request, contentP // Attempt to fix the superflous namespace intendedPath := ipath.New(strings.TrimPrefix(r.URL.Path, "/ipfs")) if err := intendedPath.IsValid(); err != nil { - webError(w, "invalid ipfs path", err, http.StatusBadRequest) + webError(w, fmt.Errorf("invalid ipfs path: %w", err), http.StatusBadRequest) return true } intendedURL := intendedPath.String() @@ -897,7 +911,7 @@ func handleSuperfluousNamespace(w http.ResponseWriter, r *http.Request, contentP SuggestedPath: intendedPath.String(), ErrorMsg: fmt.Sprintf("invalid path: %q should be %q", r.URL.Path, intendedPath.String()), }); err != nil { - webError(w, "failed to redirect when fixing superfluous namespace", err, http.StatusBadRequest) + webError(w, fmt.Errorf("failed to redirect when fixing superfluous namespace: %w", err), http.StatusBadRequest) } return true @@ -908,7 +922,8 @@ func (i *handler) handleGettingFirstBlock(r *http.Request, begin time.Time, cont // NOTE: for legacy reasons this happens before we go into content-type specific code paths _, err := i.api.GetBlock(r.Context(), resolvedPath.Cid()) if err != nil { - return newRequestError("ipfs block get "+resolvedPath.Cid().String(), err, http.StatusInternalServerError) + err = fmt.Errorf("could not get block %s: %w", resolvedPath.Cid().String(), err) + return newRequestError(err, http.StatusInternalServerError) } ns := contentPath.Namespace() timeToGetFirstContentBlock := time.Since(begin).Seconds() @@ -924,7 +939,8 @@ func (i *handler) setCommonHeaders(w http.ResponseWriter, r *http.Request, conte if rootCids, err := i.buildIpfsRootsHeader(contentPath.String(), r); err == nil { w.Header().Set("X-Ipfs-Roots", rootCids) } else { // this should never happen, as we resolved the contentPath already - return newRequestError("error while resolving X-Ipfs-Roots", err, http.StatusInternalServerError) + err = fmt.Errorf("error while resolving X-Ipfs-Roots: %s", err) + return newRequestError(err, http.StatusInternalServerError) } return nil diff --git a/gateway/handler_block.go b/gateway/handler_block.go index fcb2408bc4..a4f00ff9df 100644 --- a/gateway/handler_block.go +++ b/gateway/handler_block.go @@ -3,6 +3,7 @@ package gateway import ( "bytes" "context" + "fmt" "net/http" "time" @@ -19,7 +20,8 @@ func (i *handler) serveRawBlock(ctx context.Context, w http.ResponseWriter, r *h blockCid := resolvedPath.Cid() block, err := i.api.GetBlock(ctx, blockCid) if err != nil { - webError(w, "ipfs block get "+blockCid.String(), err, http.StatusInternalServerError) + err = fmt.Errorf("error getting block %s: %w", blockCid.String(), err) + webError(w, err, http.StatusInternalServerError) return false } content := bytes.NewReader(block.RawData()) diff --git a/gateway/handler_car.go b/gateway/handler_car.go index b900d699ac..0ce53fe7b2 100644 --- a/gateway/handler_car.go +++ b/gateway/handler_car.go @@ -28,7 +28,7 @@ func (i *handler) serveCAR(ctx context.Context, w http.ResponseWriter, r *http.R case "1": // noop, we support this default: err := fmt.Errorf("only version=1 is supported") - webError(w, "unsupported CAR version", err, http.StatusBadRequest) + webError(w, err, http.StatusBadRequest) return false } rootCid := resolvedPath.Cid() diff --git a/gateway/handler_codec.go b/gateway/handler_codec.go index 9959ddffb9..2341b5a223 100644 --- a/gateway/handler_codec.go +++ b/gateway/handler_codec.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "fmt" - "html" "net/http" "strings" "time" @@ -64,7 +63,7 @@ func (i *handler) serveCodec(ctx context.Context, w http.ResponseWriter, r *http if resolvedPath.Remainder() != "" { path := strings.TrimSuffix(resolvedPath.String(), resolvedPath.Remainder()) err := fmt.Errorf("%q of %q could not be returned: reading IPLD Kinds other than Links (CBOR Tag 42) is not implemented: try reading %q instead", resolvedPath.Remainder(), resolvedPath.String(), path) - webError(w, "unsupported pathing", err, http.StatusNotImplemented) + webError(w, err, http.StatusNotImplemented) return false } @@ -74,7 +73,7 @@ func (i *handler) serveCodec(ctx context.Context, w http.ResponseWriter, r *http if !ok { // Should not happen unless function is called with wrong parameters. err := fmt.Errorf("content type not found for codec: %v", cidCodec) - webError(w, "internal error", err, http.StatusInternalServerError) + webError(w, err, http.StatusInternalServerError) return false } responseContentType = cidContentType @@ -119,7 +118,7 @@ func (i *handler) serveCodec(ctx context.Context, w http.ResponseWriter, r *http if !ok { // This is never supposed to happen unless function is called with wrong parameters. err := fmt.Errorf("unsupported content type: %s", requestedContentType) - webError(w, err.Error(), err, http.StatusInternalServerError) + webError(w, err, http.StatusInternalServerError) return false } @@ -151,7 +150,8 @@ func (i *handler) serveCodecHTML(ctx context.Context, w http.ResponseWriter, r * CodecName: cidCodec.String(), CodecHex: fmt.Sprintf("0x%x", uint64(cidCodec)), }); err != nil { - webError(w, "failed to generate HTML listing for this DAG: try fetching raw block with ?format=raw", err, http.StatusInternalServerError) + err = fmt.Errorf("failed to generate HTML listing for this DAG: try fetching raw block with ?format=raw: %w", err) + webError(w, err, http.StatusInternalServerError) return false } @@ -163,7 +163,8 @@ func (i *handler) serveCodecRaw(ctx context.Context, w http.ResponseWriter, r *h blockCid := resolvedPath.Cid() block, err := i.api.GetBlock(ctx, blockCid) if err != nil { - webError(w, "ipfs block get "+blockCid.String(), err, http.StatusInternalServerError) + err = fmt.Errorf("error getting block %s: %w", blockCid.String(), err) + webError(w, err, http.StatusInternalServerError) return false } content := bytes.NewReader(block.RawData()) @@ -185,27 +186,28 @@ func (i *handler) serveCodecConverted(ctx context.Context, w http.ResponseWriter blockCid := resolvedPath.Cid() block, err := i.api.GetBlock(ctx, blockCid) if err != nil { - webError(w, "ipfs block get "+html.EscapeString(resolvedPath.String()), err, http.StatusInternalServerError) + err = fmt.Errorf("error getting block %s: %w", blockCid.String(), err) + webError(w, err, http.StatusInternalServerError) return false } codec := blockCid.Prefix().Codec decoder, err := multicodec.LookupDecoder(codec) if err != nil { - webError(w, err.Error(), err, http.StatusInternalServerError) + webError(w, err, http.StatusInternalServerError) return false } node := basicnode.Prototype.Any.NewBuilder() err = decoder(node, bytes.NewReader(block.RawData())) if err != nil { - webError(w, err.Error(), err, http.StatusInternalServerError) + webError(w, err, http.StatusInternalServerError) return false } encoder, err := multicodec.LookupEncoder(uint64(toCodec)) if err != nil { - webError(w, err.Error(), err, http.StatusInternalServerError) + webError(w, err, http.StatusInternalServerError) return false } @@ -213,7 +215,7 @@ func (i *handler) serveCodecConverted(ctx context.Context, w http.ResponseWriter var buf bytes.Buffer err = encoder(node.Build(), &buf) if err != nil { - webError(w, err.Error(), err, http.StatusInternalServerError) + webError(w, err, http.StatusInternalServerError) return false } diff --git a/gateway/handler_ipns_record.go b/gateway/handler_ipns_record.go index e2f658579f..e9548f7775 100644 --- a/gateway/handler_ipns_record.go +++ b/gateway/handler_ipns_record.go @@ -23,7 +23,7 @@ func (i *handler) serveIpnsRecord(ctx context.Context, w http.ResponseWriter, r if contentPath.Namespace() != "ipns" { err := fmt.Errorf("%s is not an IPNS link", contentPath.String()) - webError(w, err.Error(), err, http.StatusBadRequest) + webError(w, err, http.StatusBadRequest) return false } @@ -32,26 +32,26 @@ func (i *handler) serveIpnsRecord(ctx context.Context, w http.ResponseWriter, r key = strings.TrimPrefix(key, "/ipns/") if strings.Count(key, "/") != 0 { err := errors.New("cannot find ipns key for subpath") - webError(w, err.Error(), err, http.StatusBadRequest) + webError(w, err, http.StatusBadRequest) return false } c, err := cid.Decode(key) if err != nil { - webError(w, err.Error(), err, http.StatusBadRequest) + webError(w, err, http.StatusBadRequest) return false } rawRecord, err := i.api.GetIPNSRecord(ctx, c) if err != nil { - webError(w, err.Error(), err, http.StatusInternalServerError) + webError(w, err, http.StatusInternalServerError) return false } var record ipns_pb.IpnsEntry err = proto.Unmarshal(rawRecord, &record) if err != nil { - webError(w, err.Error(), err, http.StatusInternalServerError) + webError(w, err, http.StatusInternalServerError) return false } diff --git a/gateway/handler_tar.go b/gateway/handler_tar.go index 9c7026d33e..b4a06b4ef3 100644 --- a/gateway/handler_tar.go +++ b/gateway/handler_tar.go @@ -2,6 +2,7 @@ package gateway import ( "context" + "fmt" "html" "net/http" "time" @@ -25,7 +26,8 @@ func (i *handler) serveTAR(ctx context.Context, w http.ResponseWriter, r *http.R // Get Unixfs file file, err := i.api.GetUnixFsNode(ctx, resolvedPath) if err != nil { - webError(w, "ipfs cat "+html.EscapeString(contentPath.String()), err, http.StatusBadRequest) + err = fmt.Errorf("error getting unixfs node for %s: %w", html.EscapeString(contentPath.String()), err) + webError(w, err, http.StatusBadRequest) return false } defer file.Close() @@ -61,7 +63,7 @@ func (i *handler) serveTAR(ctx context.Context, w http.ResponseWriter, r *http.R // Construct the TAR writer tarw, err := files.NewTarWriter(w) if err != nil { - webError(w, "could not build tar writer", err, http.StatusInternalServerError) + webError(w, fmt.Errorf("could not build tar writer: %w", err), http.StatusInternalServerError) return false } defer tarw.Close() diff --git a/gateway/handler_unixfs.go b/gateway/handler_unixfs.go index 75da6c6003..deefa9cb85 100644 --- a/gateway/handler_unixfs.go +++ b/gateway/handler_unixfs.go @@ -3,7 +3,6 @@ package gateway import ( "context" "fmt" - "html" "net/http" "time" @@ -21,7 +20,8 @@ func (i *handler) serveUnixFS(ctx context.Context, w http.ResponseWriter, r *htt // Handling UnixFS dr, err := i.api.GetUnixFsNode(ctx, resolvedPath) if err != nil { - webError(w, "ipfs cat "+html.EscapeString(contentPath.String()), err, http.StatusBadRequest) + err = fmt.Errorf("error while getting unixfs node: %w", err) + webError(w, err, http.StatusBadRequest) return false } defer dr.Close() @@ -35,7 +35,7 @@ func (i *handler) serveUnixFS(ctx context.Context, w http.ResponseWriter, r *htt // Handling Unixfs directory dir, ok := dr.(files.Directory) if !ok { - internalWebError(w, fmt.Errorf("unsupported UnixFS type")) + webError(w, fmt.Errorf("unsupported UnixFS type"), http.StatusInternalServerError) return false } diff --git a/gateway/handler_unixfs__redirects.go b/gateway/handler_unixfs__redirects.go index 97d3ec5a55..b9658e4e52 100644 --- a/gateway/handler_unixfs__redirects.go +++ b/gateway/handler_unixfs__redirects.go @@ -41,14 +41,14 @@ func (i *handler) serveRedirectsIfPresent(w http.ResponseWriter, r *http.Request if redirectsFile != nil { redirectRules, err := i.getRedirectRules(r, redirectsFile) if err != nil { - internalWebError(w, err) + webError(w, err, http.StatusInternalServerError) return nil, nil, false, true } redirected, newPath, err := i.handleRedirectsFileRules(w, r, contentPath, redirectRules) if err != nil { err = fmt.Errorf("trouble processing _redirects file at %q: %w", redirectsFile.String(), err) - internalWebError(w, err) + webError(w, err, http.StatusInternalServerError) return nil, nil, false, true } @@ -62,7 +62,7 @@ func (i *handler) serveRedirectsIfPresent(w http.ResponseWriter, r *http.Request contentPath = ipath.New(newPath) resolvedPath, err = i.api.ResolvePath(r.Context(), contentPath) if err != nil { - internalWebError(w, err) + webError(w, err, http.StatusInternalServerError) return nil, nil, false, true } diff --git a/gateway/handler_unixfs_dir.go b/gateway/handler_unixfs_dir.go index 6caa3f1714..c03a4b81b3 100644 --- a/gateway/handler_unixfs_dir.go +++ b/gateway/handler_unixfs_dir.go @@ -2,6 +2,7 @@ package gateway import ( "context" + "fmt" "net/http" "net/url" gopath "path" @@ -34,7 +35,7 @@ func (i *handler) serveDirectory(ctx context.Context, w http.ResponseWriter, r * // the redirects and links would end up as http://example.net/ipns/example.net requestURI, err := url.ParseRequestURI(r.RequestURI) if err != nil { - webError(w, "failed to parse request path", err, http.StatusInternalServerError) + webError(w, fmt.Errorf("failed to parse request path: %w", err), http.StatusInternalServerError) return false } originalURLPath := requestURI.Path @@ -65,13 +66,13 @@ func (i *handler) serveDirectory(ctx context.Context, w http.ResponseWriter, r * case nil: idx, err := i.api.GetUnixFsNode(ctx, idxResolvedPath) if err != nil { - internalWebError(w, err) + webError(w, err, http.StatusInternalServerError) return false } f, ok := idx.(files.File) if !ok { - internalWebError(w, files.ErrNotReader) + webError(w, files.ErrNotReader, http.StatusInternalServerError) return false } @@ -85,7 +86,7 @@ func (i *handler) serveDirectory(ctx context.Context, w http.ResponseWriter, r * case resolver.ErrNoLink: logger.Debugw("no index.html; noop", "path", idxPath) default: - internalWebError(w, err) + webError(w, err, http.StatusInternalServerError) return false } @@ -114,14 +115,14 @@ func (i *handler) serveDirectory(ctx context.Context, w http.ResponseWriter, r * results, err := i.api.LsUnixFsDir(ctx, resolvedPath) if err != nil { - internalWebError(w, err) + webError(w, err, http.StatusInternalServerError) return false } dirListing := make([]assets.DirectoryItem, 0, len(results)) for link := range results { if link.Err != nil { - internalWebError(w, link.Err) + webError(w, link.Err, http.StatusInternalServerError) return false } @@ -197,7 +198,7 @@ func (i *handler) serveDirectory(ctx context.Context, w http.ResponseWriter, r * logger.Debugw("request processed", "tplDataDNSLink", dnslink, "tplDataSize", size, "tplDataBackLink", backLink, "tplDataHash", hash) if err := assets.DirectoryTemplate.Execute(w, tplData); err != nil { - internalWebError(w, err) + webError(w, err, http.StatusInternalServerError) return false }