Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions cmd/ipfs/kubo/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -850,8 +850,6 @@ func serveHTTPGateway(req *cmds.Request, cctx *oldcmds.Context) (<-chan error, e
corehttp.GatewayOption("/ipfs", "/ipns"),
corehttp.VersionOption(),
corehttp.CheckVersionOption(),
// TODO[api-on-gw]: remove for 0.28.0: https://github.com/ipfs/kubo/issues/10312
corehttp.CommandsROOption(cmdctx),
}

if cfg.Experimental.P2pHttpProxy {
Expand Down
2 changes: 1 addition & 1 deletion config/gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const (

type GatewaySpec struct {
// Paths is explicit list of path prefixes that should be handled by
// this gateway. Example: `["/ipfs", "/ipns", "/api"]`
// this gateway. Example: `["/ipfs", "/ipns"]`
Paths []string

// UseSubdomains indicates whether or not this gateway uses subdomains
Expand Down
57 changes: 0 additions & 57 deletions core/commands/commands_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,63 +15,6 @@ func collectPaths(prefix string, cmd *cmds.Command, out map[string]struct{}) {
}
}

func TestROCommands(t *testing.T) {
list := []string{
"/block",
"/block/get",
"/block/stat",
"/cat",
"/commands",
"/commands/completion",
"/commands/completion/bash",
"/commands/completion/fish",
"/commands/completion/zsh",
"/dag",
"/dag/get",
"/dag/resolve",
"/dag/stat",
"/dag/export",
"/get",
"/ls",
"/name",
"/name/resolve",
"/object",
"/object/data",
"/object/get",
"/object/links",
"/object/stat",
"/refs",
"/resolve",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💭 if someone needs replacement for /api/v0/resolve we could tell them to use x-ipfs-roots:

$ curl https://ipfs.io/ipns/en.wikipedia-on-ipfs.org/favicon.ico -X HEAD -is | grep -i ipfs-roots
x-ipfs-roots: bafybeiaysi4s6lnjev27ln5icwm6tueaw2vdykrtjkwiphwekaywqhcjze,bafkreicl5473u3g5c2l34n5oh5trtpft56ep6mbqv57affzgkfppcitfl4

"/version",
}

cmdSet := make(map[string]struct{})
collectPaths("", RootRO, cmdSet)

for _, path := range list {
if _, ok := cmdSet[path]; !ok {
t.Errorf("%q not in result", path)
} else {
delete(cmdSet, path)
}
}

for path := range cmdSet {
t.Errorf("%q in result but shouldn't be", path)
}

for _, path := range list {
path = path[1:] // remove leading slash
split := strings.Split(path, "/")
sub, err := RootRO.Get(split)
if err != nil {
t.Errorf("error getting subcommand %q: %v", path, err)
} else if sub == nil {
t.Errorf("subcommand %q is nil even though there was no error", path)
}
}
}

func TestCommands(t *testing.T) {
list := []string{
"/add",
Expand Down
63 changes: 0 additions & 63 deletions core/commands/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,72 +162,9 @@ var rootSubcommands = map[string]*cmds.Command{
"multibase": MbaseCmd,
}

// RootRO is the readonly version of Root
var RootRO = &cmds.Command{}

var CommandsDaemonROCmd = CommandsCmd(RootRO)

// RefsROCmd is `ipfs refs` command
var RefsROCmd = &cmds.Command{}

// VersionROCmd is `ipfs version` command (without deps).
var VersionROCmd = &cmds.Command{}

var rootROSubcommands = map[string]*cmds.Command{
"commands": CommandsDaemonROCmd,
"cat": CatCmd,
"block": {
Subcommands: map[string]*cmds.Command{
"stat": blockStatCmd,
"get": blockGetCmd,
},
},
"get": GetCmd,
"ls": LsCmd,
"name": {
Subcommands: map[string]*cmds.Command{
"resolve": name.IpnsCmd,
},
},
"object": {
Subcommands: map[string]*cmds.Command{
"data": ocmd.ObjectDataCmd,
"links": ocmd.ObjectLinksCmd,
"get": ocmd.ObjectGetCmd,
"stat": ocmd.ObjectStatCmd,
},
},
"dag": {
Subcommands: map[string]*cmds.Command{
"get": dag.DagGetCmd,
"resolve": dag.DagResolveCmd,
"stat": dag.DagStatCmd,
"export": dag.DagExportCmd,
},
},
"resolve": ResolveCmd,
}

func init() {
Root.ProcessHelp()
*RootRO = *Root

// this was in the big map definition above before,
// but if we leave it there lgc.NewCommand will be executed
// before the value is updated (:/sanitize readonly refs command/)

// sanitize readonly refs command
*RefsROCmd = *RefsCmd
RefsROCmd.Subcommands = map[string]*cmds.Command{}
rootROSubcommands["refs"] = RefsROCmd

// sanitize readonly version command (no need to expose precise deps)
*VersionROCmd = *VersionCmd
VersionROCmd.Subcommands = map[string]*cmds.Command{}
rootROSubcommands["version"] = VersionROCmd

Root.Subcommands = rootSubcommands
RootRO.Subcommands = rootROSubcommands
}

type MessageOutput struct {
Expand Down
1 change: 0 additions & 1 deletion core/commands/root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,4 @@ func TestCommandTree(t *testing.T) {
}
}
printErrors(Root.DebugValidate())
printErrors(RootRO.DebugValidate())
}
22 changes: 2 additions & 20 deletions core/corehttp/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"strconv"
"strings"

"github.com/ipfs/boxo/gateway"
cmds "github.com/ipfs/go-ipfs-cmds"
cmdsHttp "github.com/ipfs/go-ipfs-cmds/http"
version "github.com/ipfs/kubo"
Expand Down Expand Up @@ -122,14 +121,10 @@ func patchCORSVars(c *cmdsHttp.ServerConfig, addr net.Addr) {
c.SetAllowedOrigins(newOrigins...)
}

func commandsOption(cctx oldcmds.Context, command *cmds.Command, allowGet bool) ServeOption {
func commandsOption(cctx oldcmds.Context, command *cmds.Command) ServeOption {
return func(n *core.IpfsNode, l net.Listener, mux *http.ServeMux) (*http.ServeMux, error) {
cfg := cmdsHttp.NewServerConfig()
cfg.AllowGet = allowGet
corsAllowedMethods := []string{http.MethodPost}
if allowGet {
corsAllowedMethods = append(corsAllowedMethods, http.MethodGet)
}

cfg.SetAllowedMethods(corsAllowedMethods...)
cfg.APIPath = APIPath
Expand All @@ -150,13 +145,6 @@ func commandsOption(cctx oldcmds.Context, command *cmds.Command, allowGet bool)
cmdHandler = withAuthSecrets(authorizations, cmdHandler)
}

// TODO[api-on-gw]: remove for Kubo 0.28
if command == corecommands.RootRO && allowGet {
cmdHandler = gateway.NewHeaders(map[string][]string{
"Link": {`<https://github.com/ipfs/kubo/issues/10312>; rel="deprecation"; type="text/html"`},
}).Wrap(cmdHandler)
}

cmdHandler = otelhttp.NewHandler(cmdHandler, "corehttp.cmdsHandler")
mux.Handle(APIPath+"/", cmdHandler)
return mux, nil
Expand Down Expand Up @@ -211,13 +199,7 @@ func withAuthSecrets(authorizations map[string]rpcAuthScopeWithUser, next http.H
// CommandsOption constructs a ServerOption for hooking the commands into the
// HTTP server. It will NOT allow GET requests.
func CommandsOption(cctx oldcmds.Context) ServeOption {
return commandsOption(cctx, corecommands.Root, false)
}

// CommandsROOption constructs a ServerOption for hooking the read-only commands
// into the HTTP server. It will allow GET requests.
func CommandsROOption(cctx oldcmds.Context) ServeOption {
return commandsOption(cctx, corecommands.RootRO, true)
return commandsOption(cctx, corecommands.Root)
}

// CheckVersionOption returns a ServeOption that checks whether the client ipfs version matches. Does nothing when the user agent string does not contain `/kubo/` or `/go-ipfs/`
Expand Down
2 changes: 1 addition & 1 deletion core/corehttp/gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ func (o *offlineGatewayErrWrapper) GetDNSLinkRecord(ctx context.Context, s strin

var _ gateway.IPFSBackend = (*offlineGatewayErrWrapper)(nil)

var defaultPaths = []string{"/ipfs/", "/ipns/", "/api/", "/p2p/"}
var defaultPaths = []string{"/ipfs/", "/ipns/", "/p2p/"}

var subdomainGatewaySpec = &gateway.PublicGateway{
Paths: defaultPaths,
Expand Down
9 changes: 7 additions & 2 deletions docs/changelogs/v0.28.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,22 @@
- [Overview](#overview)
- [🔦 Highlights](#-highlights)
- [RPC client: removed deprecated DHT API](#rpc-client-removed-deprecated-dht-api)
- [Gateway: `/api/v0` is removed](#gateway-apiv0-is-removed)
- [📝 Changelog](#-changelog)
- [👨‍👩‍👧‍👦 Contributors](#-contributors)

### Overview

### 🔦 Highlights

#### RPC client: removed deprecated DHT API

The deprecated DHT API commands in the RPC client have been removed. Instead, use the Routing API.

#### Gateway: `/api/v0` is removed

The legacy subset of the Kubo RPC that was available via the Gateway port and was deprecated is now completely removed. You can read more in <https://github.com/ipfs/kubo/issues/10312>.

If you have a legacy software that relies on this behavior, and want to expose parts of `/api/v0` next to `/ipfs`, use reverse-proxy in front of Kubo to mount both Gateway and RPC on the same port. NOTE: exposing RPC to the internet comes with security risk: make sure to specify access control via [API.Authorizations](https://github.com/ipfs/kubo/blob/master/docs/config.md#apiauthorizations).
Comment on lines +20 to +24
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👌


### 📝 Changelog

### 👨‍👩‍👧‍👦 Contributors
9 changes: 0 additions & 9 deletions docs/gateway.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,3 @@ Right now only 'full DAG' implicit selector is implemented.
Support for user-provided IPLD selectors is tracked in https://github.com/ipfs/kubo/issues/8769.

This is a rough equivalent of `ipfs dag export`.

## Deprecated Subset of RPC API

For legacy reasons, some gateways may expose a small subset of RPC API under `/api/v0/`.
While this read-only API exposes a read-only, "safe" subset of the normal API,
it is deprecated and should not be used for greenfield projects.

Where possible, leverage `/ipfs/` and `/ipns/` endpoints.
along with `application/vnd.ipld.*` Content-Types instead.
71 changes: 0 additions & 71 deletions test/cli/gateway_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (

"github.com/ipfs/kubo/config"
"github.com/ipfs/kubo/test/cli/harness"
. "github.com/ipfs/kubo/test/cli/testutils"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/multiformats/go-multiaddr"
manet "github.com/multiformats/go-multiaddr/net"
Expand Down Expand Up @@ -344,76 +343,6 @@ func TestGateway(t *testing.T) {
})
})

t.Run("readonly API", func(t *testing.T) {
t.Parallel()

client := node.GatewayClient()

fileContents := "12345"
h.WriteFile("readonly/dir/test", fileContents)
cids := node.IPFS("add", "-r", "-q", filepath.Join(h.Dir, "readonly/dir")).Stdout.Lines()

rootCID := cids[len(cids)-1]
client.TemplateData = map[string]string{"RootCID": rootCID}

t.Run("Get IPFS directory file through readonly API succeeds", func(t *testing.T) {
t.Parallel()
resp := client.Get("/api/v0/cat?arg={{.RootCID}}/test")
assert.Equal(t, 200, resp.StatusCode)
assert.Equal(t, fileContents, resp.Body)
})

t.Run("refs IPFS directory file through readonly API succeeds", func(t *testing.T) {
t.Parallel()
resp := client.Get("/api/v0/refs?arg={{.RootCID}}/test")
assert.Equal(t, 200, resp.StatusCode)
})

t.Run("test gateway API is sanitized", func(t *testing.T) {
t.Parallel()
for _, cmd := range []string{
"add",
"block/put",
"bootstrap",
"config",
"dag/put",
"dag/import",
"dht",
"diag",
"id",
"mount",
"name/publish",
"object/put",
"object/new",
"object/patch",
"pin",
"ping",
"repo",
"stats",
"swarm",
"file",
"update",
"bitswap",
} {
t.Run(cmd, func(t *testing.T) {
cmd := cmd
t.Parallel()
assert.Equal(t, 404, client.Get("/api/v0/"+cmd).StatusCode)
})
}
})
})

t.Run("refs/local", func(t *testing.T) {
t.Parallel()
gatewayAddr := URLStrToMultiaddr(node.GatewayURL())
res := node.RunIPFS("--api", gatewayAddr.String(), "refs", "local")
assert.Contains(t,
res.Stderr.Trimmed(),
`Error: invalid path "local":`,
)
})

t.Run("raw leaves node", func(t *testing.T) {
t.Parallel()
contents := "This is RAW!"
Expand Down
2 changes: 1 addition & 1 deletion test/sharness/t0002-docker-image.sh
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ test_expect_success "docker image runs" '
'

test_expect_success "docker container gateway is up" '
pollEndpoint -host=/ip4/127.0.0.1/tcp/8080 -http-url http://localhost:8080/api/v0/version -v -tries 30 -tout 1s
Copy link
Member

@lidel lidel Mar 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💭 I suspect /api/v0/version is used as healthcheck by various monitoring tools.
Mind updating waterworks-infra in preparation for this removal?

/api/v0/version seems to be used in a few places, including pingdom:

https://github.com/search?q=repo%3Aipshipyard%2Fwaterworks-infra+api%2Fv0%2Fversion&type=code

Maybe @ns4plabs knows other places.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pollEndpoint -host=/ip4/127.0.0.1/tcp/8080 -http-url http://localhost:8080/ipfs/bafkqaddimvwgy3zao5xxe3debi -v -tries 30 -tout 1s
'

test_expect_success "docker container API is up" '
Expand Down
Loading