feat(config): Add gateway-over-libp2p experiment
Adin Schmahmann committed
Aug 31, 2023 at 05:22 UTC
f2c43d5bbfb4efec8e32573eff929feed472e734
5 files changed
+64
-5
.github/workflows/gateway-conformance.yml
+1
@@ -60,6 +60,7 @@ jobs:
60
run: |
61
./ipfs init --profile=test
62
./ipfs config --json Gateway.PublicGateways "$GATEWAY_PUBLIC_GATEWAYS"
63
+ ./ipfs config --json Experimental.GatewayOverLibp2p true
64
./ipfs config Addresses.Gateway "/ip4/127.0.0.1/tcp/8080"
65
./ipfs config Addresses.API "/ip4/127.0.0.1/tcp/5001"
66
working-directory: kubo-gateway/cmd/ipfs
cmd/ipfs/daemon.go
+15
-5
@@ -909,17 +909,27 @@ func serveHTTPGateway(req *cmds.Request, cctx *oldcmds.Context) (<-chan error, e
909
const gatewayProtocolID protocol.ID = "/ipfs/gateway" // FIXME: specify https://github.com/ipfs/specs/issues/433
910
911
func serveTrustlessGatewayOverLibp2p(cctx *oldcmds.Context) (<-chan error, error) {
912
+ node, err := cctx.ConstructNode()
913
+ if err != nil {
914
+ return nil, fmt.Errorf("serveHTTPGatewayOverLibp2p: ConstructNode() failed: %s", err)
915
+ }
916
+ cfg, err := node.Repo.Config()
917
+ if err != nil {
918
+ return nil, fmt.Errorf("could not read config: %w", err)
919
+ }
920
+
921
+ if !cfg.Experimental.GatewayOverLibp2p {
922
+ errCh := make(chan error)
923
+ close(errCh)
924
+ return errCh, nil
925
+ }
926
+
927
opts := []corehttp.ServeOption{
928
corehttp.MetricsCollectionOption("libp2p-gateway"),
929
corehttp.Libp2pGatewayOption(),
930
corehttp.VersionOption(),
931
}
932
918
- node, err := cctx.ConstructNode()
919
- if err != nil {
920
- return nil, fmt.Errorf("serveHTTPGateway: ConstructNode() failed: %s", err)
921
- }
922
-
933
handler, err := corehttp.MakeHandler(node, nil, opts...)
934
if err != nil {
935
return nil, err
config/experiments.go
+1
@@ -11,4 +11,5 @@ type Experiments struct {
11
AcceleratedDHTClient experimentalAcceleratedDHTClient `json:",omitempty"`
12
OptimisticProvide bool
13
OptimisticProvideJobsPoolSize int
14
+ GatewayOverLibp2p bool `json:",omitempty"`
15
}
docs/experimental-features.md
+37
@@ -27,6 +27,7 @@ the above issue.
27
- [Graphsync](#graphsync)
28
- [Noise](#noise)
29
- [Optimistic Provide](#optimistic-provide)
30
+- [HTTP Gateway over Libp2p](#http-gateway-over-libp2p)
31
32
---
33
@@ -617,3 +618,39 @@ ipfs config --json Experimental.OptimisticProvideJobsPoolSize 120
618
619
- [ ] Needs more people to use and report on how well it works
620
- [ ] Should prove at least equivalent availability of provider records as the classic approach
621
+
622
+## HTTP Gateway over Libp2p
623
+
624
+### In Version
625
+
626
+0.23.0
627
+
628
+### State
629
+
630
+Experimental, disabled by default.
631
+
632
+Enables serving the [IPFS HTTP Gateway](https://specs.ipfs.tech/http-gateways/) protocol over libp2p transports and
633
+as described in the [specification](https://github.com/ipfs/specs/pull/434).
634
+
635
+Notes:
636
+- This feature currently is only about serving the gateway requests over libp2p, not about fetching data this way using
637
+[Trustless Gateway Specification](https://specs.ipfs.tech/http-gateways/trustless-gateway/).
638
+- While kubo currently mounts the gateway API at the root (i.e. `/`) of the libp2p `/http/1.1` protocol that is subject to
639
+change. The way to reliably discover where a given HTTP protocol is mounted on a libp2p endpoint is via the `.well-known/libp2p`
640
+resource specified in the [http+libp2p specification](https://github.com/libp2p/specs/pull/508)
641
+- Kubo currently hard codes the gateway-over-libp2p behavior to:
642
+ - Only operate on `/ipfs` resources
643
+ - Only satisfy the Trustless Gateway API
644
+ - Only serve data that is already local to the node (i.e. similar to a `NoFetch` gateway)
645
+
646
+### How to enable
647
+
648
+Modify your ipfs config:
649
+
650
+```
651
+ipfs config --json Experimental.GatewayOverLibp2p true
652
+```
653
+
654
+### Road to being a real feature
655
+
656
+- [ ] Needs more people to use and report on how well it works
\ No newline at end of file
test/cli/http_gateway_over_libp2p_test.go
+10
@@ -57,6 +57,16 @@ func TestGatewayOverLibp2p(t *testing.T) {
57
p2pProxyNodeHTTPListenAddr, err := manet.ToNetAddr(p2pProxyNodeHTTPListenMA)
58
require.NoError(t, err)
59
60
+ t.Run("DoesNotWorkWithoutExperimentalConfig", func(t *testing.T) {
61
+ _, err := http.Get(fmt.Sprintf("http://%s/ipfs/%s?format=raw", p2pProxyNodeHTTPListenAddr, cidDataOnGatewayNode))
62
+ require.Error(t, err)
63
+ })
64
+
65
+ // Enable the experimental feature and reconnect the nodes
66
+ gwNode.IPFS("config", "--json", "Experimental.GatewayOverLibp2p", "true")
67
+ gwNode.StopDaemon().StartDaemon()
68
+ nodes.Connect()
69
+
70
// Note: the bare HTTP requests here assume that the gateway is mounted at `/`
71
t.Run("WillNotServeRemoteContent", func(t *testing.T) {
72
resp, err := http.Get(fmt.Sprintf("http://%s/ipfs/%s?format=raw", p2pProxyNodeHTTPListenAddr, cidDataNotOnGatewayNode))