Skip to content

Commit 7b6903f

Browse files
authored
Merge pull request #246 from multiformats/marco/http-path
Add support for http-path
2 parents 5d767c5 + d31f376 commit 7b6903f

File tree

3 files changed

+88
-0
lines changed

3 files changed

+88
-0
lines changed

multiaddr_test.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,11 @@ var good = []string{
192192
"/ip4/127.0.0.1/tcp/127/wss",
193193
"/ip4/127.0.0.1/tcp/127/webrtc-direct",
194194
"/ip4/127.0.0.1/tcp/127/webrtc",
195+
"/http-path/tmp%2Fbar",
196+
"/http-path/tmp%2Fbar%2Fbaz",
197+
"/http-path/foo",
198+
"/ip4/127.0.0.1/tcp/0/p2p/12D3KooWCryG7Mon9orvQxcS1rYZjotPgpwoJNHHKcLLfE4Hf5mV/http-path/foo",
199+
"/ip4/127.0.0.1/tcp/443/tls/sni/example.com/http/http-path/foo",
195200
}
196201

197202
func TestConstructSucceeds(t *testing.T) {
@@ -627,6 +632,7 @@ func TestRoundTrip(t *testing.T) {
627632
"/ip4/127.0.0.1/udp/1234/quic-v1/webtransport/certhash/uEiDDq4_xNyDorZBH3TlGazyJdOWSwvo4PUo5YHFMrvDE8g",
628633
"/p2p/QmbHVEEepCi7rn7VL7Exxpd2Ci9NNB6ifvqwhsrbRMgQFP",
629634
"/p2p/QmbHVEEepCi7rn7VL7Exxpd2Ci9NNB6ifvqwhsrbRMgQFP/unix/a/b/c",
635+
"/http-path/tmp%2Fbar",
630636
} {
631637
ma, err := NewMultiaddr(s)
632638
if err != nil {
@@ -923,3 +929,48 @@ func TestDNS(t *testing.T) {
923929
t.Fatal("expected equality")
924930
}
925931
}
932+
933+
func TestHTTPPath(t *testing.T) {
934+
t.Run("bad addr", func(t *testing.T) {
935+
badAddr := "/http-path/thisIsMissingAfullByte%f"
936+
_, err := NewMultiaddr(badAddr)
937+
require.Error(t, err)
938+
})
939+
940+
t.Run("only reads the http-path part", func(t *testing.T) {
941+
addr := "/http-path/tmp%2Fbar/p2p-circuit" // The http-path only reference the part immediately after it. It does not include the rest of the multiaddr (like the /path component sometimes does)
942+
m, err := NewMultiaddr(addr)
943+
require.NoError(t, err)
944+
m.ValueForProtocol(P_HTTP_PATH)
945+
v, err := m.ValueForProtocol(P_HTTP_PATH)
946+
require.NoError(t, err)
947+
require.Equal(t, "tmp%2Fbar", v)
948+
})
949+
950+
t.Run("round trip", func(t *testing.T) {
951+
cases := []string{
952+
"/http-path/tmp%2Fbar",
953+
"/http-path/tmp%2Fbar%2Fbaz",
954+
"/http-path/foo",
955+
"/ip4/127.0.0.1/tcp/0/p2p/12D3KooWCryG7Mon9orvQxcS1rYZjotPgpwoJNHHKcLLfE4Hf5mV/http-path/foo",
956+
"/ip4/127.0.0.1/tcp/443/tls/sni/example.com/http/http-path/foo",
957+
}
958+
for _, c := range cases {
959+
m, err := NewMultiaddr(c)
960+
require.NoError(t, err)
961+
require.Equal(t, c, m.String())
962+
}
963+
})
964+
965+
t.Run("value for protocol", func(t *testing.T) {
966+
m := StringCast("/http-path/tmp%2Fbar")
967+
v, err := m.ValueForProtocol(P_HTTP_PATH)
968+
require.NoError(t, err)
969+
// This gives us the url escaped version
970+
require.Equal(t, "tmp%2Fbar", v)
971+
972+
// If we want the raw unescaped version, we can use the component and read it
973+
_, component := SplitLast(m)
974+
require.Equal(t, "tmp/bar", string(component.RawValue()))
975+
})
976+
}

protocols.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ const (
2626
P_P2P = 421
2727
P_IPFS = P_P2P // alias for backwards compatibility
2828
P_HTTP = 480
29+
P_HTTP_PATH = 481
2930
P_HTTPS = 443 // deprecated alias for /tls/http
3031
P_ONION = 444 // also for backwards compatibility
3132
P_ONION3 = 445
@@ -206,6 +207,13 @@ var (
206207
Code: P_HTTP,
207208
VCode: CodeToVarint(P_HTTP),
208209
}
210+
protoHTTPPath = Protocol{
211+
Name: "http-path",
212+
Code: P_HTTP_PATH,
213+
VCode: CodeToVarint(P_HTTP_PATH),
214+
Size: LengthPrefixedVarSize,
215+
Transcoder: TranscoderHTTPPath,
216+
}
209217
protoHTTPS = Protocol{
210218
Name: "https",
211219
Code: P_HTTPS,
@@ -301,6 +309,7 @@ func init() {
301309
protoWEBTRANSPORT,
302310
protoCERTHASH,
303311
protoHTTP,
312+
protoHTTPPath,
304313
protoHTTPS,
305314
protoP2P,
306315
protoUNIX,

transcoders.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"errors"
99
"fmt"
1010
"net"
11+
"net/url"
1112
"strconv"
1213
"strings"
1314

@@ -454,3 +455,30 @@ func validateCertHash(b []byte) error {
454455
_, err := mh.Decode(b)
455456
return err
456457
}
458+
459+
var TranscoderHTTPPath = NewTranscoderFromFunctions(httpPathStB, httpPathBtS, validateHTTPPath)
460+
461+
func httpPathStB(s string) ([]byte, error) {
462+
unescaped, err := url.QueryUnescape(s)
463+
if err != nil {
464+
return nil, err
465+
}
466+
if len(unescaped) == 0 {
467+
return nil, fmt.Errorf("empty http path is not allowed")
468+
}
469+
return []byte(unescaped), err
470+
}
471+
472+
func httpPathBtS(b []byte) (string, error) {
473+
if len(b) == 0 {
474+
return "", fmt.Errorf("empty http path is not allowed")
475+
}
476+
return url.QueryEscape(string(b)), nil
477+
}
478+
479+
func validateHTTPPath(b []byte) error {
480+
if len(b) == 0 {
481+
return fmt.Errorf("empty http path is not allowed")
482+
}
483+
return nil // We can represent any byte slice when we escape it.
484+
}

0 commit comments

Comments
 (0)