@@ -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"
@@ -325,6 +327,10 @@ func (i *handler) getOrHeadHandler(w http.ResponseWriter, r *http.Request) {
325327 return
326328 }
327329
330+ if handleIpnsB58mhToCidRedirection (w , r ) {
331+ return
332+ }
333+
328334 contentPath := ipath .New (r .URL .Path )
329335 ctx := context .WithValue (r .Context (), ContentPathKey , contentPath )
330336 r = r .WithContext (ctx )
@@ -844,6 +850,45 @@ func handleServiceWorkerRegistration(r *http.Request) (err *ErrorResponse) {
844850 return nil
845851}
846852
853+ // handleIpnsB58mhToCidRedirection redirects from /ipns/b58mh to /ipns/cid in
854+ // the most cost-effective way.
855+ func handleIpnsB58mhToCidRedirection (w http.ResponseWriter , r * http.Request ) bool {
856+ if w .Header ().Get ("Location" ) != "" {
857+ // Ignore this if there is already a redirection in place. This happens
858+ // if there is a subdomain redirection. In that case, the path is already
859+ // converted to CIDv1.
860+ return false
861+ }
862+
863+ pathParts := strings .Split (r .URL .Path , "/" )
864+ if len (pathParts ) < 3 {
865+ return false
866+ }
867+
868+ if pathParts [1 ] != "ipns" {
869+ return false
870+ }
871+
872+ s := pathParts [2 ]
873+
874+ // Similarly to peer.Decode, check the prefix first as it is less computationally
875+ // expensive. Base58 encoded peer IDs will start with a '1'.
876+ if ! strings .HasPrefix (s , "1" ) {
877+ return false
878+ }
879+
880+ // Decode the base58 encoded sha256 or identity multihash.
881+ m , err := multihash .FromB58String (s )
882+ if err != nil {
883+ return false
884+ }
885+
886+ pathParts [2 ] = peer .ToCid (peer .ID (m )).String ()
887+ r .URL .Path = strings .Join (pathParts , "/" )
888+ http .Redirect (w , r , r .URL .String (), http .StatusFound )
889+ return true
890+ }
891+
847892// Attempt to fix redundant /ipfs/ namespace as long as resulting
848893// 'intended' path is valid. This is in case gremlins were tickled
849894// wrong way and user ended up at /ipfs/ipfs/{cid} or /ipfs/ipns/{id}
0 commit comments