Repository: libp2p/go-libp2p
Pull request #2600 (2023-10-10 09:53:55)

Fix typos


Patch:
diff --git a/examples/libp2p-host/README.md b/examples/libp2p-host/README.md
index e187f067..966ee0e1 100644
--- a/examples/libp2p-host/README.md
+++ b/examples/libp2p-host/README.md
@@ -84,7 +84,7 @@ defer h2.Close()
 fmt.Printf("Hello World, my second hosts ID is %s\n", h2.ID())
 ```
 
-And thats it, you have a libp2p host and you're ready to start doing some awesome p2p networking!
+And that's it, you have a libp2p host and you're ready to start doing some awesome p2p networking!
 
 In future guides we will go over ways to use hosts, configure them differently (hint: there are a huge number of ways to set these up), and interesting ways to apply this technology to various applications you might want to build.
 
diff --git a/p2p/http/libp2phttp.go b/p2p/http/libp2phttp.go
index d8158153..87f8f9a3 100644
--- a/p2p/http/libp2phttp.go
+++ b/p2p/http/libp2phttp.go
@@ -370,7 +370,9 @@ func (h *Host) SetHTTPHandlerAtPath(p protocol.ID, path string, handler http.Han
 	}
 	h.WellKnownHandler.AddProtocolMeta(p, ProtocolMeta{Path: path})
 	h.serveMuxInit()
-	h.ServeMux.Handle(path, http.StripPrefix(path, handler))
+	// Do not trim the trailing / from path
+	// This allows us to serve `/a/b` when we mount a handler for `/b` at path `/a`
+	h.ServeMux.Handle(path, http.StripPrefix(strings.TrimSuffix(path, "/"), handler))
 }
 
 // PeerMetadataGetter lets RoundTrippers implement a specific way of caching a peer's protocol mapping.


Test patch:
diff --git a/docs/flaky-tests.md b/docs/flaky-tests.md
index e65800ac..667dd77a 100644
--- a/docs/flaky-tests.md
+++ b/docs/flaky-tests.md
@@ -28,7 +28,7 @@ processes are vying for CPU time.
   sudo cgset -r cpu.cfs_quota_us=10000 cpulimit
   sudo cgset -r cpu.cfs_period_us=1000000 cpulimit
 
-  # Run a shell with in our limited environemnt
+  # Run a shell with in our limited environment
   sudo cgexec -g cpu:cpulimit bash
 
   # In the shell, run the test
diff --git a/p2p/host/peerstore/test/peerstore_suite.go b/p2p/host/peerstore/test/peerstore_suite.go
index 576b8fd4..da8f6f4a 100644
--- a/p2p/host/peerstore/test/peerstore_suite.go
+++ b/p2p/host/peerstore/test/peerstore_suite.go
@@ -144,7 +144,7 @@ func testGetStreamBeforePeerAdded(ps pstore.Peerstore) func(t *testing.T) {
 				t.Fatal("channel shouldnt be closed yet")
 			}
 			if a == nil {
-				t.Fatal("got a nil address, thats weird")
+				t.Fatal("got a nil address, that's weird")
 			}
 			count++
 			if received[a.String()] {
@@ -195,7 +195,7 @@ func testAddrStreamDuplicates(ps pstore.Peerstore) func(t *testing.T) {
 		var count int
 		for a := range ach {
 			if a == nil {
-				t.Fatal("got a nil address, thats weird")
+				t.Fatal("got a nil address, that's weird")
 			}
 			count++
 			if received[a.String()] {
diff --git a/p2p/http/libp2phttp_test.go b/p2p/http/libp2phttp_test.go
index 8a95bed6..6e29fbd6 100644
--- a/p2p/http/libp2phttp_test.go
+++ b/p2p/http/libp2phttp_test.go
@@ -10,6 +10,7 @@ import (
 	"crypto/x509"
 	"crypto/x509/pkix"
 	"encoding/json"
+	"fmt"
 	"io"
 	"math/big"
 	"net"
@@ -419,3 +420,68 @@ func TestCustomServeMux(t *testing.T) {
 	require.NoError(t, err)
 	require.Equal(t, 200, resp.StatusCode)
 }
+
+func TestSetHandlerAtPath(t *testing.T) {
+	hf := func(w http.ResponseWriter, r *http.Request) {
+		w.Header().Add("Content-Type", "text/plain")
+		w.Write([]byte("Hello World"))
+	}
+	tests := []struct {
+		prefix, rest string
+		paths200     []string
+		paths404     []string
+	}{
+		{
+			prefix:   "/",
+			rest:     "/",
+			paths200: []string{"/", "/a/", "/b", "/a/b"},
+		},
+		{
+			prefix:   "/a",
+			rest:     "/b/",
+			paths200: []string{"/a/b/", "///a///b/", "/a/b/c"},
+			// Not being able to serve /a/b when handling /a/b/ is a rather annoying limitation
+			// of http.StripPrefix mechanism. This happens because /a/b is redirected to /b/
+			// as the prefix /a is stripped when the redirect happens
+			paths404: []string{"/a/b", "/a", "/b", "/a/a"},
+		},
+		{
+			prefix:   "/",
+			rest:     "/b/",
+			paths200: []string{"/b", "/b/c", "/b/c/"},
+			paths404: []string{"/", "/a/b"},
+		},
+	}
+	for i, tc := range tests {
+		t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
+			nestedMx := http.NewServeMux()
+			nestedMx.HandleFunc(tc.rest, hf)
+			server := libp2phttp.Host{
+				ListenAddrs:       []ma.Multiaddr{ma.StringCast("/ip4/127.0.0.1/tcp/0/http")},
+				InsecureAllowHTTP: true,
+			}
+			server.SetHTTPHandlerAtPath("test", tc.prefix, nestedMx)
+			go func() {
+				server.Serve()
+			}()
+			defer server.Close()
+			addrs := server.Addrs()
+			require.Equal(t, 1, len(addrs))
+			port, err := addrs[0].ValueForProtocol(ma.P_TCP)
+			require.NoError(t, err)
+			httpAddr := fmt.Sprintf("http://127.0.0.1:%s", port)
+			for _, p := range tc.paths200 {
+				resp, err := http.Get(httpAddr + p)
+				require.NoError(t, err)
+				require.Equal(t, 200, resp.StatusCode, "path:%s", p)
+				resp.Body.Close()
+			}
+			for _, p := range tc.paths404 {
+				resp, _ := http.Get(httpAddr + p)
+				require.Equal(t, 404, resp.StatusCode, "path:%s", p)
+				resp.Body.Close()
+			}
+		})
+	}
+
+}