mirror of
https://github.com/ipfs/kubo.git
synced 2025-06-24 22:38:27 +08:00
Merge pull request #5372 from raulk/dns-resolution-api-endpoint
Run DNS lookup for --api endpoint provided in CLI
This commit is contained in:
72
cmd/ipfs/dnsresolve_test.go
Normal file
72
cmd/ipfs/dnsresolve_test.go
Normal file
@ -0,0 +1,72 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
ma "gx/ipfs/QmYmsdtJ3HsodkePE3eU3TsCaP2YvPZJ4LoXnNkDE5Tpt7/go-multiaddr"
|
||||
madns "gx/ipfs/QmfXU2MhWoegxHoeMd3A2ytL2P6CY4FfqGWc23LTNWBwZt/go-multiaddr-dns"
|
||||
)
|
||||
|
||||
var (
|
||||
ctx = context.Background()
|
||||
testAddr, _ = ma.NewMultiaddr("/dns4/example.com/tcp/5001")
|
||||
)
|
||||
|
||||
func makeResolver(n uint8) *madns.Resolver {
|
||||
results := make([]net.IPAddr, n)
|
||||
for i := uint8(0); i < n; i++ {
|
||||
results[i] = net.IPAddr{IP: net.ParseIP(fmt.Sprintf("192.0.2.%d", i))}
|
||||
}
|
||||
|
||||
backend := &madns.MockBackend{
|
||||
IP: map[string][]net.IPAddr{
|
||||
"example.com": results,
|
||||
}}
|
||||
|
||||
return &madns.Resolver{
|
||||
Backend: backend,
|
||||
}
|
||||
}
|
||||
|
||||
func TestApiEndpointResolveDNSOneResult(t *testing.T) {
|
||||
dnsResolver = makeResolver(1)
|
||||
|
||||
addr, err := resolveAddr(ctx, testAddr)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if ref, _ := ma.NewMultiaddr("/ip4/192.0.2.0/tcp/5001"); !addr.Equal(ref) {
|
||||
t.Errorf("resolved address was different than expected")
|
||||
}
|
||||
}
|
||||
|
||||
func TestApiEndpointResolveDNSMultipleResults(t *testing.T) {
|
||||
dnsResolver = makeResolver(4)
|
||||
|
||||
addr, err := resolveAddr(ctx, testAddr)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if ref, _ := ma.NewMultiaddr("/ip4/192.0.2.0/tcp/5001"); !addr.Equal(ref) {
|
||||
t.Errorf("resolved address was different than expected")
|
||||
}
|
||||
}
|
||||
|
||||
func TestApiEndpointResolveDNSNoResults(t *testing.T) {
|
||||
dnsResolver = makeResolver(0)
|
||||
|
||||
addr, err := resolveAddr(ctx, testAddr)
|
||||
if addr != nil || err == nil {
|
||||
t.Error("expected test address not to resolve, and to throw an error")
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(err.Error(), "non-resolvable API endpoint") {
|
||||
t.Errorf("expected error not thrown; actual: %v", err)
|
||||
}
|
||||
}
|
@ -34,6 +34,7 @@ import (
|
||||
osh "gx/ipfs/QmXuBJ7DR6k3rmUEKtvVMhwjmXDuJgXXPUt4LQXKBMsU93/go-os-helper"
|
||||
ma "gx/ipfs/QmYmsdtJ3HsodkePE3eU3TsCaP2YvPZJ4LoXnNkDE5Tpt7/go-multiaddr"
|
||||
loggables "gx/ipfs/QmZ4zF1mBrt8C2mSCM4ZYE4aAnv78f7GvrzufJC4G5tecK/go-libp2p-loggables"
|
||||
madns "gx/ipfs/QmfXU2MhWoegxHoeMd3A2ytL2P6CY4FfqGWc23LTNWBwZt/go-multiaddr-dns"
|
||||
)
|
||||
|
||||
// log is the command logger
|
||||
@ -41,6 +42,9 @@ var log = logging.Logger("cmd/ipfs")
|
||||
|
||||
var errRequestCanceled = errors.New("request canceled")
|
||||
|
||||
// declared as a var for testing purposes
|
||||
var dnsResolver = madns.DefaultResolver
|
||||
|
||||
const (
|
||||
EnvEnableProfiling = "IPFS_PROF"
|
||||
cpuProfile = "ipfs.cpuprof"
|
||||
@ -235,7 +239,7 @@ func commandShouldRunOnDaemon(details cmdDetails, req *cmds.Request, cctx *oldcm
|
||||
// did user specify an api to use for this command?
|
||||
apiAddrStr, _ := req.Options[corecmds.ApiOption].(string)
|
||||
|
||||
client, err := getApiClient(cctx.ConfigRoot, apiAddrStr)
|
||||
client, err := getAPIClient(req.Context, cctx.ConfigRoot, apiAddrStr)
|
||||
if err == repo.ErrApiNotRunning {
|
||||
if apiAddrStr != "" && req.Command != daemonCmd {
|
||||
// if user SPECIFIED an api, and this cmd is not daemon
|
||||
@ -403,10 +407,10 @@ If you're sure go-ipfs isn't running, you can just delete it.
|
||||
var checkIPFSUnixFmt = "Otherwise check:\n\tps aux | grep ipfs"
|
||||
var checkIPFSWinFmt = "Otherwise check:\n\ttasklist | findstr ipfs"
|
||||
|
||||
// getApiClient checks the repo, and the given options, checking for
|
||||
// getAPIClient checks the repo, and the given options, checking for
|
||||
// a running API service. if there is one, it returns a client.
|
||||
// otherwise, it returns errApiNotRunning, or another error.
|
||||
func getApiClient(repoPath, apiAddrStr string) (http.Client, error) {
|
||||
func getAPIClient(ctx context.Context, repoPath, apiAddrStr string) (http.Client, error) {
|
||||
var apiErrorFmt string
|
||||
switch {
|
||||
case osh.IsUnix():
|
||||
@ -440,10 +444,15 @@ func getApiClient(repoPath, apiAddrStr string) (http.Client, error) {
|
||||
if len(addr.Protocols()) == 0 {
|
||||
return nil, fmt.Errorf(apiErrorFmt, repoPath, "multiaddr doesn't provide any protocols")
|
||||
}
|
||||
return apiClientForAddr(addr)
|
||||
return apiClientForAddr(ctx, addr)
|
||||
}
|
||||
|
||||
func apiClientForAddr(addr ma.Multiaddr) (http.Client, error) {
|
||||
func apiClientForAddr(ctx context.Context, addr ma.Multiaddr) (http.Client, error) {
|
||||
addr, err := resolveAddr(ctx, addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, host, err := manet.DialArgs(addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -451,3 +460,19 @@ func apiClientForAddr(addr ma.Multiaddr) (http.Client, error) {
|
||||
|
||||
return http.NewClient(host, http.ClientWithAPIPrefix(corehttp.APIPath)), nil
|
||||
}
|
||||
|
||||
func resolveAddr(ctx context.Context, addr ma.Multiaddr) (ma.Multiaddr, error) {
|
||||
ctx, cancelFunc := context.WithTimeout(ctx, 10*time.Second)
|
||||
defer cancelFunc()
|
||||
|
||||
addrs, err := dnsResolver.Resolve(ctx, addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(addrs) == 0 {
|
||||
return nil, errors.New("non-resolvable API endpoint")
|
||||
}
|
||||
|
||||
return addrs[0], nil
|
||||
}
|
||||
|
@ -539,6 +539,12 @@
|
||||
"hash": "QmPyxJ2QS7L5FhGkNYkNcXHGjDhvGHueJ4auqAstFHYxy5",
|
||||
"name": "go-cidutil",
|
||||
"version": "0.0.2"
|
||||
},
|
||||
{
|
||||
"author": "lgierth",
|
||||
"hash": "QmfXU2MhWoegxHoeMd3A2ytL2P6CY4FfqGWc23LTNWBwZt",
|
||||
"name": "go-multiaddr-dns",
|
||||
"version": "0.2.4"
|
||||
}
|
||||
],
|
||||
"gxVersion": "0.10.0",
|
||||
|
24
test/sharness/t0236-cli-api-dns-resolve.sh
Executable file
24
test/sharness/t0236-cli-api-dns-resolve.sh
Executable file
@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Copyright (c) 2015 Jeromy Johnson
|
||||
# MIT Licensed; see the LICENSE file in this repository.
|
||||
#
|
||||
|
||||
test_description="test dns resolution of api endpoint by cli"
|
||||
|
||||
. lib/test-lib.sh
|
||||
|
||||
test_init_ipfs
|
||||
|
||||
test_expect_success "can make http request against dns resolved nc server" '
|
||||
nc -ld 5005 > nc_out &
|
||||
NCPID=$!
|
||||
go-sleep 0.5s && kill "$NCPID" &
|
||||
ipfs cat /ipfs/Qmabcdef --api /dns4/localhost/tcp/5005 || true
|
||||
'
|
||||
|
||||
test_expect_success "request was received by local nc server" '
|
||||
grep "POST /api/v0/cat" nc_out
|
||||
'
|
||||
|
||||
test_done
|
Reference in New Issue
Block a user