fix(gw): 404 when a valid DAG is missing link
Marcin Rataj committed
Jul 19, 2022 at 22:04 UTC
7992025254c70cda1b5fd084b7a8a28b1f06958f
4 files changed
+18
-8
core/corehttp/gateway_handler.go
+4
-2
@@ -19,6 +19,7 @@ import (
19
20
cid "github.com/ipfs/go-cid"
21
files "github.com/ipfs/go-ipfs-files"
22
+ ipld "github.com/ipfs/go-ipld-format"
23
dag "github.com/ipfs/go-merkledag"
24
mfs "github.com/ipfs/go-mfs"
25
path "github.com/ipfs/go-path"
@@ -389,8 +390,7 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request
390
logger.Debugw("serve pretty 404 if present")
391
return
392
}
392
-
393
- webError(w, "ipfs resolve -r "+debugStr(contentPath.String()), err, http.StatusNotFound)
393
+ webError(w, "ipfs resolve -r "+debugStr(contentPath.String()), err, http.StatusBadRequest)
394
return
395
}
396
@@ -782,6 +782,8 @@ func webError(w http.ResponseWriter, message string, err error, defaultCode int)
782
webErrorWithCode(w, message, err, http.StatusNotFound)
783
} else if err == routing.ErrNotFound {
784
webErrorWithCode(w, message, err, http.StatusNotFound)
785
+ } else if ipld.IsNotFound(err) {
786
+ webErrorWithCode(w, message, err, http.StatusNotFound)
787
} else if err == context.DeadlineExceeded {
788
webErrorWithCode(w, message, err, http.StatusRequestTimeout)
789
} else {
core/corehttp/gateway_handler_unixfs.go
+1
-1
@@ -22,7 +22,7 @@ func (i *gatewayHandler) serveUnixFS(ctx context.Context, w http.ResponseWriter,
22
// Handling UnixFS
23
dr, err := i.api.Unixfs().Get(ctx, resolvedPath)
24
if err != nil {
25
- webError(w, "ipfs cat "+html.EscapeString(contentPath.String()), err, http.StatusNotFound)
25
+ webError(w, "ipfs cat "+html.EscapeString(contentPath.String()), err, http.StatusBadRequest)
26
return
27
}
28
defer dr.Close()
core/corehttp/gateway_test.go
+4
-4
@@ -235,8 +235,8 @@ func TestGatewayGet(t *testing.T) {
235
{"127.0.0.1:8080", "/", http.StatusNotFound, "404 page not found\n"},
236
{"127.0.0.1:8080", "/" + k.Cid().String(), http.StatusNotFound, "404 page not found\n"},
237
{"127.0.0.1:8080", k.String(), http.StatusOK, "fnord"},
238
- {"127.0.0.1:8080", "/ipns/nxdomain.example.com", http.StatusNotFound, "ipfs resolve -r /ipns/nxdomain.example.com: " + namesys.ErrResolveFailed.Error() + "\n"},
239
- {"127.0.0.1:8080", "/ipns/%0D%0A%0D%0Ahello", http.StatusNotFound, "ipfs resolve -r /ipns/\\r\\n\\r\\nhello: " + namesys.ErrResolveFailed.Error() + "\n"},
238
+ {"127.0.0.1:8080", "/ipns/nxdomain.example.com", http.StatusBadRequest, "ipfs resolve -r /ipns/nxdomain.example.com: " + namesys.ErrResolveFailed.Error() + "\n"},
239
+ {"127.0.0.1:8080", "/ipns/%0D%0A%0D%0Ahello", http.StatusBadRequest, "ipfs resolve -r /ipns/\\r\\n\\r\\nhello: " + namesys.ErrResolveFailed.Error() + "\n"},
240
{"127.0.0.1:8080", "/ipns/example.com", http.StatusOK, "fnord"},
241
{"example.com", "/", http.StatusOK, "fnord"},
242
@@ -244,8 +244,8 @@ func TestGatewayGet(t *testing.T) {
244
{"double.example.com", "/", http.StatusOK, "fnord"},
245
{"triple.example.com", "/", http.StatusOK, "fnord"},
246
{"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"},
247
- {"broken.example.com", "/", http.StatusNotFound, "ipfs resolve -r /ipns/broken.example.com/: " + namesys.ErrResolveFailed.Error() + "\n"},
248
- {"broken.example.com", k.String(), http.StatusNotFound, "ipfs resolve -r /ipns/broken.example.com" + k.String() + ": " + namesys.ErrResolveFailed.Error() + "\n"},
247
+ {"broken.example.com", "/", http.StatusBadRequest, "ipfs resolve -r /ipns/broken.example.com/: " + namesys.ErrResolveFailed.Error() + "\n"},
248
+ {"broken.example.com", k.String(), http.StatusBadRequest, "ipfs resolve -r /ipns/broken.example.com" + k.String() + ": " + namesys.ErrResolveFailed.Error() + "\n"},
249
// This test case ensures we don't treat the TLD as a file extension.
250
{"example.man", "/", http.StatusOK, "fnord"},
251
} {
test/sharness/t0110-gateway.sh
+9
-1
@@ -88,10 +88,14 @@ test_expect_success "GET IPFS directory with index.html and trailing slash retur
88
test_should_contain \"hello i am a webpage\" response_with_slash
89
"
90
91
-test_expect_success "GET IPFS nonexistent file returns code expected (404)" '
91
+test_expect_success "GET IPFS nonexistent file returns 404 (Not Found)" '
92
test_curl_resp_http_code "http://127.0.0.1:$port/ipfs/$HASH2/pleaseDontAddMe" "HTTP/1.1 404 Not Found"
93
'
94
95
+test_expect_success "GET IPFS invalid CID returns 400 (Bad Request)" '
96
+ test_curl_resp_http_code "http://127.0.0.1:$port/ipfs/QmInvalid/pleaseDontAddMe" "HTTP/1.1 400 Bad Request"
97
+'
98
+
99
# https://github.com/ipfs/go-ipfs/issues/8230
100
test_expect_success "GET IPFS inlined zero-length data object returns ok code (200)" '
101
curl -sD - "http://127.0.0.1:$port/ipfs/bafkqaaa" > empty_ok_response &&
@@ -105,6 +109,10 @@ test_expect_success "GET /ipfs/ipfs/{cid} returns redirect to the valid path" '
109
test_should_contain "<link rel=\"canonical\" href=\"/ipfs/bafkqaaa?query=to-remember\" />" response_with_double_ipfs_ns
110
'
111
112
+test_expect_success "GET invalid IPNS root returns 400 (Bad Request)" '
113
+ test_curl_resp_http_code "http://127.0.0.1:$port/ipns/QmInvalid/pleaseDontAddMe" "HTTP/1.1 400 Bad Request"
114
+'
115
+
116
test_expect_failure "GET IPNS path succeeds" '
117
ipfs name publish --allow-offline "$HASH" &&
118
PEERID=$(ipfs config Identity.PeerID) &&