@cryptotaxi247 / kubo / commits / ed4d6b7d4

test: remove gateway tests migrated to go-libipfs

Henrique Dias committed Feb 7, 2023 at 12:40 UTC ed4d6b7d4187512ede4aeb19188a383d9aa55d45
1 file changed -478
core/corehttp/gateway_test.go
-478
@@ -6,7 +6,6 @@ import (
6 "io"
7 "net/http"
8 "net/http/httptest"
9 - "regexp"
9 "strings"
10 "testing"
11
@@ -18,19 +17,14 @@ import (
17
18 datastore "github.com/ipfs/go-datastore"
19 syncds "github.com/ipfs/go-datastore/sync"
21 - "github.com/ipfs/go-libipfs/files"
20 path "github.com/ipfs/go-path"
21 iface "github.com/ipfs/interface-go-ipfs-core"
22 nsopts "github.com/ipfs/interface-go-ipfs-core/options/namesys"
25 - ipath "github.com/ipfs/interface-go-ipfs-core/path"
23 config "github.com/ipfs/kubo/config"
24 ci "github.com/libp2p/go-libp2p/core/crypto"
25 id "github.com/libp2p/go-libp2p/p2p/protocol/identify"
26 )
27
31 -// `ipfs object new unixfs-dir`
32 -var emptyDir = "/ipfs/QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn"
33 -
28 type mockNamesys map[string]path.Path
29
30 func (m mockNamesys) Resolve(ctx context.Context, name string, opts ...nsopts.ResolveOpt) (value path.Path, err error) {
@@ -145,478 +139,6 @@ func newTestServerAndNode(t *testing.T, ns mockNamesys) (*httptest.Server, iface
139 return ts, api, n.Context()
140 }
141
148 -func matchPathOrBreadcrumbs(s string, expected string) bool {
149 - matched, _ := regexp.MatchString("Index of\n[\t ]*"+regexp.QuoteMeta(expected), s)
150 - return matched
151 -}
152 -
153 -func TestUriQueryRedirect(t *testing.T) {
154 - ts, _, _ := newTestServerAndNode(t, mockNamesys{})
155 -
156 - cid := "QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR"
157 - for i, test := range []struct {
158 - path string
159 - status int
160 - location string
161 - }{
162 - // - Browsers will send original URI in URL-escaped form
163 - // - We expect query parameters to be persisted
164 - // - We drop fragments, as those should not be sent by a browser
165 - {"/ipfs/?uri=ipfs%3A%2F%2FQmXoypizjW3WknFiJnKLwHCnL72vedxjQkDDP1mXWo6uco%2Fwiki%2FFoo_%C4%85%C4%99.html%3Ffilename%3Dtest-%C4%99.html%23header-%C4%85", http.StatusMovedPermanently, "/ipfs/QmXoypizjW3WknFiJnKLwHCnL72vedxjQkDDP1mXWo6uco/wiki/Foo_%c4%85%c4%99.html?filename=test-%c4%99.html"},
166 - {"/ipfs/?uri=ipns%3A%2F%2Fexample.com%2Fwiki%2FFoo_%C4%85%C4%99.html%3Ffilename%3Dtest-%C4%99.html", http.StatusMovedPermanently, "/ipns/example.com/wiki/Foo_%c4%85%c4%99.html?filename=test-%c4%99.html"},
167 - {"/ipfs/?uri=ipfs://" + cid, http.StatusMovedPermanently, "/ipfs/" + cid},
168 - {"/ipfs?uri=ipfs://" + cid, http.StatusMovedPermanently, "/ipfs/?uri=ipfs://" + cid},
169 - {"/ipfs/?uri=ipns://" + cid, http.StatusMovedPermanently, "/ipns/" + cid},
170 - {"/ipns/?uri=ipfs%3A%2F%2FQmXoypizjW3WknFiJnKLwHCnL72vedxjQkDDP1mXWo6uco%2Fwiki%2FFoo_%C4%85%C4%99.html%3Ffilename%3Dtest-%C4%99.html%23header-%C4%85", http.StatusMovedPermanently, "/ipfs/QmXoypizjW3WknFiJnKLwHCnL72vedxjQkDDP1mXWo6uco/wiki/Foo_%c4%85%c4%99.html?filename=test-%c4%99.html"},
171 - {"/ipns/?uri=ipns%3A%2F%2Fexample.com%2Fwiki%2FFoo_%C4%85%C4%99.html%3Ffilename%3Dtest-%C4%99.html", http.StatusMovedPermanently, "/ipns/example.com/wiki/Foo_%c4%85%c4%99.html?filename=test-%c4%99.html"},
172 - {"/ipns?uri=ipns://" + cid, http.StatusMovedPermanently, "/ipns/?uri=ipns://" + cid},
173 - {"/ipns/?uri=ipns://" + cid, http.StatusMovedPermanently, "/ipns/" + cid},
174 - {"/ipns/?uri=ipfs://" + cid, http.StatusMovedPermanently, "/ipfs/" + cid},
175 - {"/ipfs/?uri=unsupported://" + cid, http.StatusBadRequest, ""},
176 - {"/ipfs/?uri=invaliduri", http.StatusBadRequest, ""},
177 - {"/ipfs/?uri=" + cid, http.StatusBadRequest, ""},
178 - } {
179 -
180 - r, err := http.NewRequest(http.MethodGet, ts.URL+test.path, nil)
181 - if err != nil {
182 - t.Fatal(err)
183 - }
184 - resp, err := doWithoutRedirect(r)
185 - if err != nil {
186 - t.Fatal(err)
187 - }
188 - defer resp.Body.Close()
189 -
190 - if resp.StatusCode != test.status {
191 - t.Errorf("(%d) got %d, expected %d from %s", i, resp.StatusCode, test.status, ts.URL+test.path)
192 - }
193 -
194 - locHdr := resp.Header.Get("Location")
195 - if locHdr != test.location {
196 - t.Errorf("(%d) location header got %s, expected %s from %s", i, locHdr, test.location, ts.URL+test.path)
197 - }
198 - }
199 -}
200 -
201 -func TestGatewayGet(t *testing.T) {
202 - ns := mockNamesys{}
203 - ts, api, ctx := newTestServerAndNode(t, ns)
204 -
205 - k, err := api.Unixfs().Add(ctx, files.NewBytesFile([]byte("fnord")))
206 - if err != nil {
207 - t.Fatal(err)
208 - }
209 - ns["/ipns/example.com"] = path.FromString(k.String())
210 - ns["/ipns/working.example.com"] = path.FromString(k.String())
211 - ns["/ipns/double.example.com"] = path.FromString("/ipns/working.example.com")
212 - ns["/ipns/triple.example.com"] = path.FromString("/ipns/double.example.com")
213 - ns["/ipns/broken.example.com"] = path.FromString("/ipns/" + k.Cid().String())
214 - // We picked .man because:
215 - // 1. It's a valid TLD.
216 - // 2. Go treats it as the file extension for "man" files (even though
217 - // nobody actually *uses* this extension, AFAIK).
218 - //
219 - // Unfortunately, this may not work on all platforms as file type
220 - // detection is platform dependent.
221 - ns["/ipns/example.man"] = path.FromString(k.String())
222 -
223 - t.Log(ts.URL)
224 - for i, test := range []struct {
225 - host string
226 - path string
227 - status int
228 - text string
229 - }{
230 - {"127.0.0.1:8080", "/", http.StatusNotFound, "404 page not found\n"},
231 - {"127.0.0.1:8080", "/" + k.Cid().String(), http.StatusNotFound, "404 page not found\n"},
232 - {"127.0.0.1:8080", k.String(), http.StatusOK, "fnord"},
233 - {"127.0.0.1:8080", "/ipns/nxdomain.example.com", http.StatusBadRequest, "ipfs resolve -r /ipns/nxdomain.example.com: " + namesys.ErrResolveFailed.Error() + "\n"},
234 - {"127.0.0.1:8080", "/ipns/%0D%0A%0D%0Ahello", http.StatusBadRequest, "ipfs resolve -r /ipns/\\r\\n\\r\\nhello: " + namesys.ErrResolveFailed.Error() + "\n"},
235 - {"127.0.0.1:8080", "/ipns/example.com", http.StatusOK, "fnord"},
236 - {"example.com", "/", http.StatusOK, "fnord"},
237 -
238 - {"working.example.com", "/", http.StatusOK, "fnord"},
239 - {"double.example.com", "/", http.StatusOK, "fnord"},
240 - {"triple.example.com", "/", http.StatusOK, "fnord"},
241 - {"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"},
242 - {"broken.example.com", "/", http.StatusBadRequest, "ipfs resolve -r /ipns/broken.example.com/: " + namesys.ErrResolveFailed.Error() + "\n"},
243 - {"broken.example.com", k.String(), http.StatusBadRequest, "ipfs resolve -r /ipns/broken.example.com" + k.String() + ": " + namesys.ErrResolveFailed.Error() + "\n"},
244 - // This test case ensures we don't treat the TLD as a file extension.
245 - {"example.man", "/", http.StatusOK, "fnord"},
246 - } {
247 - var c http.Client
248 - r, err := http.NewRequest(http.MethodGet, ts.URL+test.path, nil)
249 - if err != nil {
250 - t.Fatal(err)
251 - }
252 - r.Host = test.host
253 - resp, err := c.Do(r)
254 -
255 - urlstr := "http://" + test.host + test.path
256 - if err != nil {
257 - t.Errorf("error requesting %s: %s", urlstr, err)
258 - continue
259 - }
260 - defer resp.Body.Close()
261 - contentType := resp.Header.Get("Content-Type")
262 - if contentType != "text/plain; charset=utf-8" {
263 - t.Errorf("expected content type to be text/plain, got %s", contentType)
264 - }
265 - body, err := io.ReadAll(resp.Body)
266 - if resp.StatusCode != test.status {
267 - t.Errorf("(%d) got %d, expected %d from %s", i, resp.StatusCode, test.status, urlstr)
268 - t.Errorf("Body: %s", body)
269 - continue
270 - }
271 - if err != nil {
272 - t.Fatalf("error reading response from %s: %s", urlstr, err)
273 - }
274 - if string(body) != test.text {
275 - t.Errorf("unexpected response body from %s: expected %q; got %q", urlstr, test.text, body)
276 - continue
277 - }
278 - }
279 -}
280 -
281 -func TestPretty404(t *testing.T) {
282 - ns := mockNamesys{}
283 - ts, api, ctx := newTestServerAndNode(t, ns)
284 -
285 - f1 := files.NewMapDirectory(map[string]files.Node{
286 - "ipfs-404.html": files.NewBytesFile([]byte("Custom 404")),
287 - "deeper": files.NewMapDirectory(map[string]files.Node{
288 - "ipfs-404.html": files.NewBytesFile([]byte("Deep custom 404")),
289 - }),
290 - })
291 -
292 - k, err := api.Unixfs().Add(ctx, f1)
293 - if err != nil {
294 - t.Fatal(err)
295 - }
296 -
297 - host := "example.net"
298 - ns["/ipns/"+host] = path.FromString(k.String())
299 -
300 - for _, test := range []struct {
301 - path string
302 - accept string
303 - status int
304 - text string
305 - }{
306 - {"/ipfs-404.html", "text/html", http.StatusOK, "Custom 404"},
307 - {"/nope", "text/html", http.StatusNotFound, "Custom 404"},
308 - {"/nope", "text/*", http.StatusNotFound, "Custom 404"},
309 - {"/nope", "*/*", http.StatusNotFound, "Custom 404"},
310 - {"/nope", "application/json", http.StatusNotFound, "ipfs resolve -r /ipns/example.net/nope: no link named \"nope\" under QmcmnF7XG5G34RdqYErYDwCKNFQ6jb8oKVR21WAJgubiaj\n"},
311 - {"/deeper/nope", "text/html", http.StatusNotFound, "Deep custom 404"},
312 - {"/deeper/", "text/html", http.StatusOK, ""},
313 - {"/deeper", "text/html", http.StatusOK, ""},
314 - {"/nope/nope", "text/html", http.StatusNotFound, "Custom 404"},
315 - } {
316 - var c http.Client
317 - req, err := http.NewRequest("GET", ts.URL+test.path, nil)
318 - if err != nil {
319 - t.Fatal(err)
320 - }
321 - req.Header.Add("Accept", test.accept)
322 - req.Host = host
323 - resp, err := c.Do(req)
324 -
325 - if err != nil {
326 - t.Fatalf("error requesting %s: %s", test.path, err)
327 - }
328 -
329 - defer resp.Body.Close()
330 - if resp.StatusCode != test.status {
331 - t.Fatalf("got %d, expected %d, from %s", resp.StatusCode, test.status, test.path)
332 - }
333 - body, err := io.ReadAll(resp.Body)
334 - if err != nil {
335 - t.Fatalf("error reading response from %s: %s", test.path, err)
336 - }
337 -
338 - if test.text != "" && string(body) != test.text {
339 - t.Fatalf("unexpected response body from %s: got %q, expected %q", test.path, body, test.text)
340 - }
341 - }
342 -}
343 -
344 -func TestIPNSHostnameRedirect(t *testing.T) {
345 - ns := mockNamesys{}
346 - ts, api, ctx := newTestServerAndNode(t, ns)
347 - t.Logf("test server url: %s", ts.URL)
348 -
349 - // create /ipns/example.net/foo/index.html
350 -
351 - f1 := files.NewMapDirectory(map[string]files.Node{
352 - "_": files.NewBytesFile([]byte("_")),
353 - "foo": files.NewMapDirectory(map[string]files.Node{
354 - "index.html": files.NewBytesFile([]byte("_")),
355 - }),
356 - })
357 -
358 - k, err := api.Unixfs().Add(ctx, f1)
359 - if err != nil {
360 - t.Fatal(err)
361 - }
362 -
363 - t.Logf("k: %s\n", k)
364 - ns["/ipns/example.net"] = path.FromString(k.String())
365 -
366 - // make request to directory containing index.html
367 - req, err := http.NewRequest(http.MethodGet, ts.URL+"/foo", nil)
368 - if err != nil {
369 - t.Fatal(err)
370 - }
371 - req.Host = "example.net"
372 -
373 - res, err := doWithoutRedirect(req)
374 - if err != nil {
375 - t.Fatal(err)
376 - }
377 -
378 - // expect 301 redirect to same path, but with trailing slash
379 - if res.StatusCode != 301 {
380 - t.Errorf("status is %d, expected 301", res.StatusCode)
381 - }
382 - hdr := res.Header["Location"]
383 - if len(hdr) < 1 {
384 - t.Errorf("location header not present")
385 - } else if hdr[0] != "/foo/" {
386 - t.Errorf("location header is %v, expected /foo/", hdr[0])
387 - }
388 -
389 - // make request with prefix to directory containing index.html
390 - req, err = http.NewRequest(http.MethodGet, ts.URL+"/foo", nil)
391 - if err != nil {
392 - t.Fatal(err)
393 - }
394 - req.Host = "example.net"
395 -
396 - res, err = doWithoutRedirect(req)
397 - if err != nil {
398 - t.Fatal(err)
399 - }
400 -
401 - // expect 301 redirect to same path, but with prefix and trailing slash
402 - if res.StatusCode != 301 {
403 - t.Errorf("status is %d, expected 301", res.StatusCode)
404 - }
405 - hdr = res.Header["Location"]
406 - if len(hdr) < 1 {
407 - t.Errorf("location header not present")
408 - } else if hdr[0] != "/foo/" {
409 - t.Errorf("location header is %v, expected /foo/", hdr[0])
410 - }
411 -
412 - // make sure /version isn't exposed
413 - req, err = http.NewRequest(http.MethodGet, ts.URL+"/version", nil)
414 - if err != nil {
415 - t.Fatal(err)
416 - }
417 - req.Host = "example.net"
418 -
419 - res, err = doWithoutRedirect(req)
420 - if err != nil {
421 - t.Fatal(err)
422 - }
423 -
424 - if res.StatusCode != 404 {
425 - t.Fatalf("expected a 404 error, got: %s", res.Status)
426 - }
427 -}
428 -
429 -// Test directory listing on DNSLink website
430 -// (scenario when Host header is the same as URL hostname)
431 -// This is basic regression test: additional end-to-end tests
432 -// can be found in test/sharness/t0115-gateway-dir-listing.sh
433 -func TestIPNSHostnameBacklinks(t *testing.T) {
434 - ns := mockNamesys{}
435 - ts, api, ctx := newTestServerAndNode(t, ns)
436 - t.Logf("test server url: %s", ts.URL)
437 -
438 - f1 := files.NewMapDirectory(map[string]files.Node{
439 - "file.txt": files.NewBytesFile([]byte("1")),
440 - "foo? #<'": files.NewMapDirectory(map[string]files.Node{
441 - "file.txt": files.NewBytesFile([]byte("2")),
442 - "bar": files.NewMapDirectory(map[string]files.Node{
443 - "file.txt": files.NewBytesFile([]byte("3")),
444 - }),
445 - }),
446 - })
447 -
448 - // create /ipns/example.net/foo/
449 - k, err := api.Unixfs().Add(ctx, f1)
450 - if err != nil {
451 - t.Fatal(err)
452 - }
453 -
454 - k2, err := api.ResolvePath(ctx, ipath.Join(k, "foo? #<'"))
455 - if err != nil {
456 - t.Fatal(err)
457 - }
458 -
459 - k3, err := api.ResolvePath(ctx, ipath.Join(k, "foo? #<'/bar"))
460 - if err != nil {
461 - t.Fatal(err)
462 - }
463 -
464 - t.Logf("k: %s\n", k)
465 - ns["/ipns/example.net"] = path.FromString(k.String())
466 -
467 - // make request to directory listing
468 - req, err := http.NewRequest(http.MethodGet, ts.URL+"/foo%3F%20%23%3C%27/", nil)
469 - if err != nil {
470 - t.Fatal(err)
471 - }
472 - req.Host = "example.net"
473 -
474 - res, err := doWithoutRedirect(req)
475 - if err != nil {
476 - t.Fatal(err)
477 - }
478 -
479 - // expect correct links
480 - body, err := io.ReadAll(res.Body)
481 - if err != nil {
482 - t.Fatalf("error reading response: %s", err)
483 - }
484 - s := string(body)
485 - t.Logf("body: %s\n", string(body))
486 -
487 - if !matchPathOrBreadcrumbs(s, "/ipns/<a href=\"//example.net/\">example.net</a>/<a href=\"//example.net/foo%3F%20%23%3C%27\">foo? #&lt;&#39;</a>") {
488 - t.Fatalf("expected a path in directory listing")
489 - }
490 - if !strings.Contains(s, "<a href=\"/foo%3F%20%23%3C%27/..\">") {
491 - t.Fatalf("expected backlink in directory listing")
492 - }
493 - if !strings.Contains(s, "<a href=\"/foo%3F%20%23%3C%27/file.txt\">") {
494 - t.Fatalf("expected file in directory listing")
495 - }
496 - if !strings.Contains(s, "<a class=\"ipfs-hash\" translate=\"no\" href=\"https://cid.ipfs.tech/#") {
497 - // https://github.com/ipfs/dir-index-html/issues/42
498 - t.Fatalf("expected links to cid.ipfs.tech in CID column when on DNSLink website")
499 - }
500 - if !strings.Contains(s, k2.Cid().String()) {
501 - t.Fatalf("expected hash in directory listing")
502 - }
503 -
504 - // make request to directory listing at root
505 - req, err = http.NewRequest(http.MethodGet, ts.URL, nil)
506 - if err != nil {
507 - t.Fatal(err)
508 - }
509 - req.Host = "example.net"
510 -
511 - res, err = doWithoutRedirect(req)
512 - if err != nil {
513 - t.Fatal(err)
514 - }
515 -
516 - // expect correct backlinks at root
517 - body, err = io.ReadAll(res.Body)
518 - if err != nil {
519 - t.Fatalf("error reading response: %s", err)
520 - }
521 - s = string(body)
522 - t.Logf("body: %s\n", string(body))
523 -
524 - if !matchPathOrBreadcrumbs(s, "/") {
525 - t.Fatalf("expected a path in directory listing")
526 - }
527 - if strings.Contains(s, "<a href=\"/\">") {
528 - t.Fatalf("expected no backlink in directory listing of the root CID")
529 - }
530 - if !strings.Contains(s, "<a href=\"/file.txt\">") {
531 - t.Fatalf("expected file in directory listing")
532 - }
533 - if !strings.Contains(s, "<a class=\"ipfs-hash\" translate=\"no\" href=\"https://cid.ipfs.tech/#") {
534 - // https://github.com/ipfs/dir-index-html/issues/42
535 - t.Fatalf("expected links to cid.ipfs.tech in CID column when on DNSLink website")
536 - }
537 - if !strings.Contains(s, k.Cid().String()) {
538 - t.Fatalf("expected hash in directory listing")
539 - }
540 -
541 - // make request to directory listing
542 - req, err = http.NewRequest(http.MethodGet, ts.URL+"/foo%3F%20%23%3C%27/bar/", nil)
543 - if err != nil {
544 - t.Fatal(err)
545 - }
546 - req.Host = "example.net"
547 -
548 - res, err = doWithoutRedirect(req)
549 - if err != nil {
550 - t.Fatal(err)
551 - }
552 -
553 - // expect correct backlinks
554 - body, err = io.ReadAll(res.Body)
555 - if err != nil {
556 - t.Fatalf("error reading response: %s", err)
557 - }
558 - s = string(body)
559 - t.Logf("body: %s\n", string(body))
560 -
561 - if !matchPathOrBreadcrumbs(s, "/ipns/<a href=\"//example.net/\">example.net</a>/<a href=\"//example.net/foo%3F%20%23%3C%27\">foo? #&lt;&#39;</a>/<a href=\"//example.net/foo%3F%20%23%3C%27/bar\">bar</a>") {
562 - t.Fatalf("expected a path in directory listing")
563 - }
564 - if !strings.Contains(s, "<a href=\"/foo%3F%20%23%3C%27/bar/..\">") {
565 - t.Fatalf("expected backlink in directory listing")
566 - }
567 - if !strings.Contains(s, "<a href=\"/foo%3F%20%23%3C%27/bar/file.txt\">") {
568 - t.Fatalf("expected file in directory listing")
569 - }
570 - if !strings.Contains(s, k3.Cid().String()) {
571 - t.Fatalf("expected hash in directory listing")
572 - }
573 -}
574 -
575 -func TestCacheControlImmutable(t *testing.T) {
576 - ts, _, _ := newTestServerAndNode(t, nil)
577 - t.Logf("test server url: %s", ts.URL)
578 -
579 - req, err := http.NewRequest(http.MethodGet, ts.URL+emptyDir+"/", nil)
580 - if err != nil {
581 - t.Fatal(err)
582 - }
583 -
584 - res, err := doWithoutRedirect(req)
585 - if err != nil {
586 - t.Fatal(err)
587 - }
588 -
589 - // check the immutable tag isn't set
590 - hdrs, ok := res.Header["Cache-Control"]
591 - if ok {
592 - for _, hdr := range hdrs {
593 - if strings.Contains(hdr, "immutable") {
594 - t.Fatalf("unexpected Cache-Control: immutable on directory listing: %s", hdr)
595 - }
596 - }
597 - }
598 -}
599 -
600 -func TestGoGetSupport(t *testing.T) {
601 - ts, _, _ := newTestServerAndNode(t, nil)
602 - t.Logf("test server url: %s", ts.URL)
603 -
604 - // mimic go-get
605 - req, err := http.NewRequest(http.MethodGet, ts.URL+emptyDir+"?go-get=1", nil)
606 - if err != nil {
607 - t.Fatal(err)
608 - }
609 -
610 - res, err := doWithoutRedirect(req)
611 - if err != nil {
612 - t.Fatal(err)
613 - }
614 -
615 - if res.StatusCode != 200 {
616 - t.Errorf("status is %d, expected 200", res.StatusCode)
617 - }
618 -}
619 -
142 func TestVersion(t *testing.T) {
143 version.CurrentCommit = "theshortcommithash"
144