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? #<'</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? #<'</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