Monorepo for Tangled

appview/{xrpcclient,repo}: show 404 for missing files and paths instead of 503 #1

open opened by murex.tngl.sh targeting master from fix/404-instead-of-503

Add ErrXrpcNotFound and treat 404s with resource-not-found tags (FileNotFound, PathNotFound, RefNotFound, etc.) as ErrXrpcNotFound. Treat other 404s as ErrXrpcUnsupported. In blob, tree, and log handlers, return the 404 page for ErrXrpcNotFound instead of the 503 page.

Signed-off-by: Nupur Agrawal nupur202000@gmail.com

Labels

None yet.

assignee

None yet.

Participants 1
AT URI
at://did:plc:owyua2lvxbs55wyhs22dqu2s/sh.tangled.repo.pull/3mgijogdlkz22
+61 -6
Diff #0
+7 -1
appview/repo/blob.go
··· 2 3 import ( 4 "encoding/base64" 5 "fmt" 6 "io" 7 "net/http" ··· 62 resp, err := tangled.RepoBlob(r.Context(), xrpcc, filePath, false, ref, repo) 63 if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil { 64 l.Error("failed to call XRPC repo.blob", "err", xrpcerr) 65 - rp.pages.Error503(w) 66 return 67 } 68
··· 2 3 import ( 4 "encoding/base64" 5 + "errors" 6 "fmt" 7 "io" 8 "net/http" ··· 63 resp, err := tangled.RepoBlob(r.Context(), xrpcc, filePath, false, ref, repo) 64 if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil { 65 l.Error("failed to call XRPC repo.blob", "err", xrpcerr) 66 + if errors.Is(xrpcerr, xrpcclient.ErrXrpcNotFound) { 67 + w.WriteHeader(http.StatusNotFound) 68 + rp.pages.Error404(w) 69 + } else { 70 + rp.pages.Error503(w) 71 + } 72 return 73 } 74
+25 -4
appview/repo/log.go
··· 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "net/http" 7 "net/url" ··· 61 xrpcBytes, err := tangled.RepoLog(r.Context(), xrpcc, cursor, limit, "", ref, repo) 62 if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil { 63 l.Error("failed to call XRPC repo.log", "err", xrpcerr) 64 - rp.pages.Error503(w) 65 return 66 } 67 ··· 75 tagBytes, err := tangled.RepoTags(r.Context(), xrpcc, "", 0, repo) 76 if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil { 77 l.Error("failed to call XRPC repo.tags", "err", xrpcerr) 78 - rp.pages.Error503(w) 79 return 80 } 81 ··· 96 branchBytes, err := tangled.RepoBranches(r.Context(), xrpcc, "", 0, repo) 97 if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil { 98 l.Error("failed to call XRPC repo.branches", "err", xrpcerr) 99 - rp.pages.Error503(w) 100 return 101 } 102 ··· 176 xrpcBytes, err := tangled.RepoDiff(r.Context(), xrpcc, ref, repo) 177 if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil { 178 l.Error("failed to call XRPC repo.diff", "err", xrpcerr) 179 - rp.pages.Error503(w) 180 return 181 } 182
··· 2 3 import ( 4 "encoding/json" 5 + "errors" 6 "fmt" 7 "net/http" 8 "net/url" ··· 62 xrpcBytes, err := tangled.RepoLog(r.Context(), xrpcc, cursor, limit, "", ref, repo) 63 if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil { 64 l.Error("failed to call XRPC repo.log", "err", xrpcerr) 65 + if errors.Is(xrpcerr, xrpcclient.ErrXrpcNotFound) { 66 + w.WriteHeader(http.StatusNotFound) 67 + rp.pages.Error404(w) 68 + } else { 69 + rp.pages.Error503(w) 70 + } 71 return 72 } 73 ··· 81 tagBytes, err := tangled.RepoTags(r.Context(), xrpcc, "", 0, repo) 82 if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil { 83 l.Error("failed to call XRPC repo.tags", "err", xrpcerr) 84 + if errors.Is(xrpcerr, xrpcclient.ErrXrpcNotFound) { 85 + w.WriteHeader(http.StatusNotFound) 86 + rp.pages.Error404(w) 87 + } else { 88 + rp.pages.Error503(w) 89 + } 90 return 91 } 92 ··· 107 branchBytes, err := tangled.RepoBranches(r.Context(), xrpcc, "", 0, repo) 108 if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil { 109 l.Error("failed to call XRPC repo.branches", "err", xrpcerr) 110 + if errors.Is(xrpcerr, xrpcclient.ErrXrpcNotFound) { 111 + w.WriteHeader(http.StatusNotFound) 112 + rp.pages.Error404(w) 113 + } else { 114 + rp.pages.Error503(w) 115 + } 116 return 117 } 118 ··· 192 xrpcBytes, err := tangled.RepoDiff(r.Context(), xrpcc, ref, repo) 193 if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil { 194 l.Error("failed to call XRPC repo.diff", "err", xrpcerr) 195 + if errors.Is(xrpcerr, xrpcclient.ErrXrpcNotFound) { 196 + w.WriteHeader(http.StatusNotFound) 197 + rp.pages.Error404(w) 198 + } else { 199 + rp.pages.Error503(w) 200 + } 201 return 202 } 203
+7 -1
appview/repo/tree.go
··· 1 package repo 2 3 import ( 4 "fmt" 5 "net/http" 6 "net/url" ··· 45 xrpcResp, err := tangled.RepoTree(r.Context(), xrpcc, treePath, ref, repo) 46 if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil { 47 l.Error("failed to call XRPC repo.tree", "err", xrpcerr) 48 - rp.pages.Error503(w) 49 return 50 } 51 // Convert XRPC response to internal types.RepoTreeResponse
··· 1 package repo 2 3 import ( 4 + "errors" 5 "fmt" 6 "net/http" 7 "net/url" ··· 46 xrpcResp, err := tangled.RepoTree(r.Context(), xrpcc, treePath, ref, repo) 47 if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil { 48 l.Error("failed to call XRPC repo.tree", "err", xrpcerr) 49 + if errors.Is(xrpcerr, xrpcclient.ErrXrpcNotFound) { 50 + w.WriteHeader(http.StatusNotFound) 51 + rp.pages.Error404(w) 52 + } else { 53 + rp.pages.Error503(w) 54 + } 55 return 56 } 57 // Convert XRPC response to internal types.RepoTreeResponse
+22
appview/xrpcclient/xrpc.go
··· 3 import ( 4 "errors" 5 "net/http" 6 7 indigoxrpc "github.com/bluesky-social/indigo/xrpc" 8 ) 9 10 var ( 11 ErrXrpcUnsupported = errors.New("xrpc not supported on this knot") 12 ErrXrpcUnauthorized = errors.New("unauthorized xrpc request") 13 ErrXrpcFailed = errors.New("xrpc request failed") 14 ErrXrpcInvalid = errors.New("invalid xrpc request") 15 ) 16 17 // produces a more manageable error 18 func HandleXrpcErr(err error) error { 19 if err == nil { ··· 27 28 switch xrpcerr.StatusCode { 29 case http.StatusNotFound: 30 return ErrXrpcUnsupported 31 case http.StatusUnauthorized: 32 return ErrXrpcUnauthorized ··· 34 return ErrXrpcFailed 35 } 36 }
··· 3 import ( 4 "errors" 5 "net/http" 6 + "strings" 7 8 indigoxrpc "github.com/bluesky-social/indigo/xrpc" 9 ) 10 11 var ( 12 ErrXrpcUnsupported = errors.New("xrpc not supported on this knot") 13 + ErrXrpcNotFound = errors.New("resource not found") 14 ErrXrpcUnauthorized = errors.New("unauthorized xrpc request") 15 ErrXrpcFailed = errors.New("xrpc request failed") 16 ErrXrpcInvalid = errors.New("invalid xrpc request") 17 ) 18 19 + // resourceNotFoundTags are XRPC error tags that indicate a missing resource 20 + // (file, path, ref, etc.), as opposed to an unsupported feature (spindle, knot, etc.) 21 + var resourceNotFoundTags = []string{ 22 + "FileNotFound", "PathNotFound", "RefNotFound", 23 + "BranchNotFound", "TagNotFound", "RevisionNotFound", "RepoNotFound", 24 + } 25 + 26 // produces a more manageable error 27 func HandleXrpcErr(err error) error { 28 if err == nil { ··· 36 37 switch xrpcerr.StatusCode { 38 case http.StatusNotFound: 39 + if isResourceNotFound(xrpcerr) { 40 + return ErrXrpcNotFound 41 + } 42 return ErrXrpcUnsupported 43 case http.StatusUnauthorized: 44 return ErrXrpcUnauthorized ··· 46 return ErrXrpcFailed 47 } 48 } 49 + 50 + func isResourceNotFound(xrpcerr *indigoxrpc.Error) bool { 51 + errStr := xrpcerr.Error() 52 + for _, tag := range resourceNotFoundTags { 53 + if strings.Contains(errStr, tag) { 54 + return true 55 + } 56 + } 57 + return false 58 + }

History

1 round 0 comments
sign up or login to add to the discussion
murex.tngl.sh submitted #0
1 commit
expand
appview/{xrpcclient,repo}: show 404 for missing files and paths instead of 503
no conflicts, ready to merge
expand 0 comments