@@ -19,6 +19,8 @@ import (
1919 ipath "github.com/ipfs/boxo/coreiface/path"
2020 cid "github.com/ipfs/go-cid"
2121 logging "github.com/ipfs/go-log"
22+ "github.com/libp2p/go-libp2p/core/peer"
23+ "github.com/multiformats/go-multihash"
2224 prometheus "github.com/prometheus/client_golang/prometheus"
2325 "go.opentelemetry.io/otel"
2426 "go.opentelemetry.io/otel/attribute"
@@ -305,6 +307,34 @@ func (i *handler) optionsHandler(w http.ResponseWriter, r *http.Request) {
305307 i .addUserHeaders (w ) // return all custom headers (including CORS ones, if set)
306308}
307309
310+ // handleIpnsPeerIdToCidRedirection redirects from /ipns/b58mh to /ipns/cid in
311+ // the most cost-effective way.
312+ func handleIpnsPeerIdToCidRedirection (w http.ResponseWriter , r * http.Request ) bool {
313+ pathParts := strings .Split (r .URL .Path , "/" )
314+ if len (pathParts ) < 3 {
315+ return false
316+ }
317+
318+ s := pathParts [2 ]
319+
320+ // Similarly to peer.Decode, check the prefix first as it is
321+ // less computationally expensive.
322+ if ! strings .HasPrefix (s , "1" ) {
323+ return false
324+ }
325+
326+ // Decode the base58 encoded sha256 or identity multihash.
327+ m , err := multihash .FromB58String (s )
328+ if err != nil {
329+ return false
330+ }
331+
332+ pathParts [2 ] = peer .ToCid (peer .ID (m )).String ()
333+ r .URL .Path = strings .Join (pathParts , "/" )
334+ http .Redirect (w , r , r .URL .String (), http .StatusFound )
335+ return true
336+ }
337+
308338func (i * handler ) getOrHeadHandler (w http.ResponseWriter , r * http.Request ) {
309339 begin := time .Now ()
310340
@@ -325,6 +355,10 @@ func (i *handler) getOrHeadHandler(w http.ResponseWriter, r *http.Request) {
325355 return
326356 }
327357
358+ if handleIpnsPeerIdToCidRedirection (w , r ) {
359+ return
360+ }
361+
328362 contentPath := ipath .New (r .URL .Path )
329363 ctx := context .WithValue (r .Context (), ContentPathKey , contentPath )
330364 r = r .WithContext (ctx )
0 commit comments