diff --git a/.github/workflows/gateway-conformance.yml b/.github/workflows/gateway-conformance.yml index a6c1b6c6e..60a2cfc18 100644 --- a/.github/workflows/gateway-conformance.yml +++ b/.github/workflows/gateway-conformance.yml @@ -22,7 +22,7 @@ jobs: steps: # 1. Download the gateway-conformance fixtures - name: Download gateway-conformance fixtures - uses: ipfs/gateway-conformance/.github/actions/extract-fixtures@v0.6 + uses: ipfs/gateway-conformance/.github/actions/extract-fixtures@v0.7 with: output: fixtures merged: true @@ -47,7 +47,7 @@ jobs: # 4. Run the gateway-conformance tests - name: Run gateway-conformance tests - uses: ipfs/gateway-conformance/.github/actions/test@v0.6 + uses: ipfs/gateway-conformance/.github/actions/test@v0.7 with: gateway-url: http://127.0.0.1:8040 subdomain-url: http://example.net:8040 @@ -84,7 +84,7 @@ jobs: steps: # 1. Download the gateway-conformance fixtures - name: Download gateway-conformance fixtures - uses: ipfs/gateway-conformance/.github/actions/extract-fixtures@v0.6 + uses: ipfs/gateway-conformance/.github/actions/extract-fixtures@v0.7 with: output: fixtures merged: true @@ -114,7 +114,7 @@ jobs: # 4. Run the gateway-conformance tests - name: Run gateway-conformance tests - uses: ipfs/gateway-conformance/.github/actions/test@v0.6 + uses: ipfs/gateway-conformance/.github/actions/test@v0.7 with: gateway-url: http://127.0.0.1:8040 # we test gateway that is backed by a remote block gateway subdomain-url: http://example.net:8040 @@ -152,7 +152,7 @@ jobs: steps: # 1. Download the gateway-conformance fixtures - name: Download gateway-conformance fixtures - uses: ipfs/gateway-conformance/.github/actions/extract-fixtures@v0.6 + uses: ipfs/gateway-conformance/.github/actions/extract-fixtures@v0.7 with: output: fixtures merged: true @@ -182,7 +182,7 @@ jobs: # 4. Run the gateway-conformance tests - name: Run gateway-conformance tests - uses: ipfs/gateway-conformance/.github/actions/test@v0.6 + uses: ipfs/gateway-conformance/.github/actions/test@v0.7 with: gateway-url: http://127.0.0.1:8040 # we test gateway that is backed by a remote car gateway subdomain-url: http://example.net:8040 diff --git a/CHANGELOG.md b/CHANGELOG.md index a7987fa45..149986ff1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,30 +16,48 @@ The following emojis are used to highlight certain changes: ### Added +- `gateway` Support for custom DNSLink / DoH resolvers on `localhost` to simplify integration with non-ICANN DNS systems [#645](https://github.com/ipfs/boxo/pull/645) + +### Changed + +- `gateway` The default DNSLink resolver for `.eth` TLD changed to `https://dns.eth.limo/dns-query` [#781](https://github.com/ipfs/boxo/pull/781) +- `gateway` The default DNSLink resolver for `.crypto` TLD changed to `https://resolver.unstoppable.io/dns-query` [#782](https://github.com/ipfs/boxo/pull/782) + +### Removed + +### Fixed + +- `gateway` Fix redirect URLs for subdirectories with characters that need escaping. [#779](https://github.com/ipfs/boxo/pull/779) + +### Security + + +## [v0.26.0] + +### Added + - `bitswap/client`: Improved timeout configuration for block requests - Exposed `DontHaveTimeoutConfig` to hold configuration values for `dontHaveTimeoutMgr` which controls how long to wait for requested block before emitting a synthetic DontHave response - Added `DefaultDontHaveTimeoutConfig()` to return a `DontHaveTimeoutConfig` populated with default values - Added optional `WithDontHaveTimeoutConfig` to allow passing a custom `DontHaveTimeoutConfig` - Setting `SetSendDontHaves(false)` works the same as before. Behind the scenes, it will disable `dontHaveTimeoutMgr` by passing a `nil` `onDontHaveTimeout` to `newDontHaveTimeoutMgr`. - ### Changed - 🛠 `blockstore` and `blockservice`'s `WriteThrough()` option now takes an "enabled" parameter: `WriteThrough(enabled bool)`. - Replaced unmaintained mock time implementation uses in tests: [from](github.com/benbjohnson/clock) => [to](github.com/filecoin-project/go-clock) -- upgrade to go-libp2p [v0.38.1](https://github.com/libp2p/go-libp2p/releases/tag/v0.38.1) - `bitswap/client`: if a libp2p connection has a context, use `context.AfterFunc` to cleanup the connection. - upgrade to `go-libp2p-kad-dht` [v0.28.1](https://github.com/libp2p/go-libp2p-kad-dht/releases/tag/v0.28.1) - - -### Removed - +- upgrade to `go-libp2p` [v0.38.1](https://github.com/libp2p/go-libp2p/releases/tag/v0.38.1) +- blockstore/blockservice: change option to `WriteThrough(enabled bool)` [#749](https://github.com/ipfs/boxo/pull/749) +- `mfs`: improve mfs republisher [#754](https://github.com/ipfs/boxo/pull/754) ### Fixed -* `mfs`: directory cache is now cleared on Flush(), liberating the memory used by the otherwise ever-growing cache. References to directories and sub-directories should be renewed after flushing. +- `mfs`: directory cache is now cleared on Flush(), liberating the memory used by the otherwise ever-growing cache. References to directories and sub-directories should be renewed after flushing. +- `bitswap/client`: Fix leak due to cid queue never getting cleaned up [#756](https://github.com/ipfs/boxo/pull/756) +- `bitswap`: Drop stream references on Close/Reset [760](https://github.com/ipfs/boxo/pull/760) -### Security ## [v0.25.0] @@ -51,16 +69,16 @@ The following emojis are used to highlight certain changes: - `gateway`: `NewCacheBlockStore` and `NewCarBackend` will use `prometheus.DefaultRegisterer` when a custom one is not specified via `WithPrometheusRegistry` [#722](https://github.com/ipfs/boxo/pull/722) - `filestore`: added opt-in `WithMMapReader` option to `FileManager` to enable memory-mapped file reads [#665](https://github.com/ipfs/boxo/pull/665) - `bitswap/routing` `ProviderQueryManager` does not require calling `Startup` separate from `New`. [#741](https://github.com/ipfs/boxo/pull/741) -- `bitswap/routing` ProviderQueryManager does not use liftcycle context. +- `bitswap/routing` ProviderQueryManager does not use lifecycle context. ### Changed - `bitswap`, `routing`, `exchange` ([#641](https://github.com/ipfs/boxo/pull/641)): - - ✨ Bitswap is no longer in charge of providing blocks to the newtork: providing functionality is now handled by a `exchange/providing.Exchange`, meant to be used with `provider.System` so that all provides follow the same rules (multiple parts of the code where handling provides) before. + - ✨ Bitswap is no longer in charge of providing blocks to the network: providing functionality is now handled by a `exchange/providing.Exchange`, meant to be used with `provider.System` so that all provides follow the same rules (multiple parts of the code where handling provides) before. - 🛠 `bitswap/client/internal/providerquerymanager` has been moved to `routing/providerquerymanager` where it belongs. In order to keep compatibility, Bitswap now receives a `routing.ContentDiscovery` parameter which implements `FindProvidersAsync(...)` and uses it to create a `providerquerymanager` with the default settings as before. Custom settings can be used by using a custom `providerquerymanager` to manually wrap a `ContentDiscovery` object and pass that in as `ContentDiscovery` on initialization while setting `bitswap.WithDefaultProviderQueryManager(false)` (to avoid re-wrapping it again). - The renovated `providedQueryManager` will trigger lookups until it manages to connect to `MaxProviders`. Before it would lookup at most `MaxInProcessRequests*MaxProviders` and connection failures may have limited the actual number of providers found. - 🛠 We have aligned our routing-related interfaces with the libp2p [`routing`](https://pkg.go.dev/github.com/libp2p/go-libp2p/core/routing#ContentRouting) ones, including in the `reprovider.System`. - - In order to obtain exactly the same behaviour as before (i.e. particularly ensuring that new blocks are still provided), what was done like: + - In order to obtain exactly the same behavior as before (i.e. particularly ensuring that new blocks are still provided), what was done like: ```go bswapnet := network.NewFromIpfsHost(host, contentRouter) @@ -247,7 +265,7 @@ The following emojis are used to highlight certain changes: ### Fixed -- 🛠️`routing/http/server`: delegated peer routing endpoint now supports both [PeerID string notaitons from libp2p specs](https://github.com/libp2p/specs/blob/master/peer-ids/peer-ids.md#string-representation). +- 🛠️`routing/http/server`: delegated peer routing endpoint now supports both [Peer ID string notations from libp2p specs](https://github.com/libp2p/specs/blob/master/peer-ids/peer-ids.md#string-representation). - `bitswap`: add missing client `WithBlockReceivedNotifier` and `WithoutDuplicatedBlockStats` options to the exchange. ## [v0.18.0] diff --git a/bitswap/README.md b/bitswap/README.md index c8fd819e8..6f699daa5 100644 --- a/bitswap/README.md +++ b/bitswap/README.md @@ -23,7 +23,7 @@ contain wantlists or blocks. A node sends a wantlist to tell peers which blocks it wants. When a node receives a wantlist it should check which blocks it has from the wantlist, and consider -sending the matching blocks to the requestor. +sending the matching blocks to the requester. When a node receives blocks that it asked for, the node should send out a notification called a 'Cancel' to tell its peers that the node no longer @@ -74,7 +74,7 @@ block, err := exchange.GetBlock(ctx, c) Parameter Notes: -1. `ctx` is the context for this request, which can be cancelled to cancel the request +1. `ctx` is the context for this request, which can be canceled to cancel the request 2. `c` is the content ID of the block you're requesting ### Get Several Blocks Asynchronously @@ -89,7 +89,7 @@ blockChannel, err := exchange.GetBlocks(ctx, cids) Parameter Notes: -1. `ctx` is the context for this request, which can be cancelled to cancel the request +1. `ctx` is the context for this request, which can be canceled to cancel the request 2. `cids` is a slice of content IDs for the blocks you're requesting ### Get Related Blocks Faster With Sessions diff --git a/bitswap/client/internal/messagequeue/messagequeue.go b/bitswap/client/internal/messagequeue/messagequeue.go index e427d18c2..37a783ac7 100644 --- a/bitswap/client/internal/messagequeue/messagequeue.go +++ b/bitswap/client/internal/messagequeue/messagequeue.go @@ -93,7 +93,7 @@ type MessageQueue struct { cancels *cid.Set priority int32 - // Dont touch any of these variables outside of run loop + // Don't touch any of these variables outside of run loop sender bsnet.MessageSender rebroadcastNow chan struct{} // For performance reasons we just clear out the fields of the message @@ -160,7 +160,7 @@ func (r *recallWantlist) MarkSent(e bswl.Entry) bool { // SentAt records the time at which a want was sent func (r *recallWantlist) SentAt(c cid.Cid, at time.Time) { - // The want may have been cancelled in the interim + // The want may have been canceled in the interim if _, ok := r.sent.Contains(c); ok { if _, ok := r.sentAt[c]; !ok { r.sentAt[c] = at @@ -222,7 +222,7 @@ type DontHaveTimeoutManager interface { // Shutdown the manager (Shutdown is final, manager cannot be restarted) Shutdown() // AddPending adds the wants as pending a response. If the are not - // cancelled before the timeout, the OnDontHaveTimeout method will be called. + // canceled before the timeout, the OnDontHaveTimeout method will be called. AddPending([]cid.Cid) // CancelPending removes the wants CancelPending([]cid.Cid) @@ -597,7 +597,7 @@ func (mq *MessageQueue) sendMessage() { } } -// If want-block times out, simulate a DONT_HAVE reponse. +// If want-block times out, simulate a DONT_HAVE response. // This is necessary when making requests to peers running an older version of // Bitswap that doesn't support the DONT_HAVE response, and is also useful to // mitigate getting blocked by a peer that takes a long time to respond. @@ -847,13 +847,13 @@ FINISH: defer mq.wllock.Unlock() for _, e := range peerEntries[:sentPeerEntries] { - if e.Cid.Defined() { // Check if want was cancelled in the interim + if e.Cid.Defined() { // Check if want was canceled in the interim mq.peerWants.SentAt(e.Cid, now) } } for _, e := range bcstEntries[:sentBcstEntries] { - if e.Cid.Defined() { // Check if want was cancelled in the interim + if e.Cid.Defined() { // Check if want was canceled in the interim mq.bcstWants.SentAt(e.Cid, now) } } diff --git a/bitswap/server/internal/decision/engine.go b/bitswap/server/internal/decision/engine.go index 9b929b99c..308673696 100644 --- a/bitswap/server/internal/decision/engine.go +++ b/bitswap/server/internal/decision/engine.go @@ -916,7 +916,7 @@ func (e *Engine) handleOverflow(ctx context.Context, p peer.ID, overflow, wants return wants } -// Split the want-havek entries from the cancel and deny entries. +// Split the want, cancel, and deny entries. func (e *Engine) splitWantsCancelsDenials(p peer.ID, m bsmsg.BitSwapMessage) ([]bsmsg.Entry, []bsmsg.Entry, []bsmsg.Entry, error) { entries := m.Wantlist() // creates copy; safe to modify if len(entries) == 0 { diff --git a/bitswap/server/internal/decision/scoreledger.go b/bitswap/server/internal/decision/scoreledger.go index 16285fcbf..433d86668 100644 --- a/bitswap/server/internal/decision/scoreledger.go +++ b/bitswap/server/internal/decision/scoreledger.go @@ -109,7 +109,7 @@ type DefaultScoreLedger struct { scorePeer ScorePeerFunc // is closed on Close closing chan struct{} - // protects the fields immediatly below + // protects the fields immediately below lock sync.RWMutex // ledgerMap lists score ledgers by their partner key. ledgerMap map[peer.ID]*scoreledger diff --git a/examples/go.mod b/examples/go.mod index 522a7c2f7..60b96487b 100644 --- a/examples/go.mod +++ b/examples/go.mod @@ -91,7 +91,7 @@ require ( github.com/koron/go-ssdp v0.0.4 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/libp2p/go-cidranger v1.1.0 // indirect - github.com/libp2p/go-doh-resolver v0.4.0 // indirect + github.com/libp2p/go-doh-resolver v0.5.0 // indirect github.com/libp2p/go-flow-metrics v0.2.0 // indirect github.com/libp2p/go-libp2p-asn-util v0.4.1 // indirect github.com/libp2p/go-libp2p-kad-dht v0.28.1 // indirect diff --git a/examples/go.sum b/examples/go.sum index 7d04d3178..dda475f9c 100644 --- a/examples/go.sum +++ b/examples/go.sum @@ -270,8 +270,8 @@ github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6 github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38yPW7c= github.com/libp2p/go-cidranger v1.1.0/go.mod h1:KWZTfSr+r9qEo9OkI9/SIEeAtw+NNoU0dXIXt15Okic= -github.com/libp2p/go-doh-resolver v0.4.0 h1:gUBa1f1XsPwtpE1du0O+nnZCUqtG7oYi7Bb+0S7FQqw= -github.com/libp2p/go-doh-resolver v0.4.0/go.mod h1:v1/jwsFusgsWIGX/c6vCRrnJ60x7bhTiq/fs2qt0cAg= +github.com/libp2p/go-doh-resolver v0.5.0 h1:4h7plVVW+XTS+oUBw2+8KfoM1jF6w8XmO7+skhePFdE= +github.com/libp2p/go-doh-resolver v0.5.0/go.mod h1:aPDxfiD2hNURgd13+hfo29z9IC22fv30ee5iM31RzxU= github.com/libp2p/go-flow-metrics v0.2.0 h1:EIZzjmeOE6c8Dav0sNv35vhZxATIXWZg6j/C08XmmDw= github.com/libp2p/go-flow-metrics v0.2.0/go.mod h1:st3qqfu8+pMfh+9Mzqb2GTiwrAGjIPszEjZmtksN8Jc= github.com/libp2p/go-libp2p v0.38.1 h1:aT1K7IFWi+gZUsQGCzTHBTlKX5QVZQOahng8DnOr6tQ= @@ -307,7 +307,6 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= -github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ= github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ= github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8= @@ -330,10 +329,8 @@ github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYg github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0= github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4= github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo= -github.com/multiformats/go-multiaddr v0.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4= github.com/multiformats/go-multiaddr v0.14.0 h1:bfrHrJhrRuh/NXH5mCnemjpbGjzRw/b+tJFOD41g2tU= github.com/multiformats/go-multiaddr v0.14.0/go.mod h1:6EkVAxtznq2yC3QT5CM1UTAwG0GTP3EWAIcjHuzQ+r4= -github.com/multiformats/go-multiaddr-dns v0.3.0/go.mod h1:mNzQ4eTGDg0ll1N9jKPOUogZPoJ30W8a7zk66FQPpdQ= github.com/multiformats/go-multiaddr-dns v0.4.1 h1:whi/uCLbDS3mSEUMb1MsoT4uzUeZB0N32yzufqS0i5M= github.com/multiformats/go-multiaddr-dns v0.4.1/go.mod h1:7hfthtB4E4pQwirrz+J0CcDUfbWzTqEzVyYKKIKpgkc= github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= @@ -347,7 +344,6 @@ github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7B github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM= github.com/multiformats/go-multistream v0.6.0 h1:ZaHKbsL404720283o4c/IHQXiS6gb8qAN5EIJ4PN5EA= github.com/multiformats/go-multistream v0.6.0/go.mod h1:MOyoG5otO24cHIg8kf9QW2/NozURlkP/rvi2FQJyCPg= -github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8= github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= @@ -673,7 +669,6 @@ golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/gateway/dns.go b/gateway/dns.go index 376c42669..c161ed8d5 100644 --- a/gateway/dns.go +++ b/gateway/dns.go @@ -10,13 +10,13 @@ import ( ) var defaultResolvers = map[string]string{ - "eth.": "https://resolver.cloudflare-eth.com/dns-query", - "crypto.": "https://resolver.cloudflare-eth.com/dns-query", + "eth.": "https://dns.eth.limo/dns-query", + "crypto.": "https://resolver.unstoppable.io/dns-query", } func newResolver(url string, opts ...doh.Option) (madns.BasicResolver, error) { - if !strings.HasPrefix(url, "https://") { - return nil, fmt.Errorf("invalid resolver url: %s", url) + if !strings.HasPrefix(url, "https://") && !strings.HasPrefix(url, "http://") { + return nil, fmt.Errorf("invalid DoH resolver URL: %s", url) } return doh.NewResolver(url, opts...) diff --git a/gateway/dns_test.go b/gateway/dns_test.go new file mode 100644 index 000000000..424a12c2a --- /dev/null +++ b/gateway/dns_test.go @@ -0,0 +1,119 @@ +package gateway + +import ( + "context" + "fmt" + "io" + "net" + "net/http" + "strings" + "testing" + + "github.com/miekg/dns" + "github.com/stretchr/testify/require" +) + +func TestAddNewDNSResolver(t *testing.T) { + ctx := context.Background() + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + l, err := net.Listen("tcp", "127.0.0.1:0") + require.NoError(t, err) + defer l.Close() + + dnslinkName := "dnslink-test.foobar" + dnslinkValue := "dnslink=/ipfs/bafkqaaa" + + go func() { + _ = http.Serve(l, http.HandlerFunc(dnslinkServerHandlerFunc(t, dnslinkName, dnslinkValue))) + }() + + listenAddr := l.Addr().(*net.TCPAddr) + r, err := NewDNSResolver(map[string]string{ + "foobar.": fmt.Sprintf("http://%s:%d", listenAddr.IP, listenAddr.Port), + }) + require.NoError(t, err) + + res, err := r.LookupTXT(ctx, fmt.Sprintf("_dnslink.%s.", dnslinkName)) + require.NoError(t, err) + require.Len(t, res, 1) + require.Equal(t, dnslinkValue, res[0]) +} + +func TestOverrideDNSDefaults(t *testing.T) { + ctx := context.Background() + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + l, err := net.Listen("tcp", "127.0.0.1:0") + require.NoError(t, err) + defer l.Close() + + dnslinkName := "dnslink-test.eth" + dnslinkValue := "dnslink=/ipfs/bafkqaaa" + + go func() { + _ = http.Serve(l, http.HandlerFunc(dnslinkServerHandlerFunc(t, dnslinkName, dnslinkValue))) + }() + + listenAddr := l.Addr().(*net.TCPAddr) + r, err := NewDNSResolver(map[string]string{ + "eth.": fmt.Sprintf("http://%s:%d", listenAddr.IP, listenAddr.Port), + }) + require.NoError(t, err) + + res, err := r.LookupTXT(ctx, fmt.Sprintf("_dnslink.%s.", dnslinkName)) + require.NoError(t, err) + require.Len(t, res, 1) + require.Equal(t, dnslinkValue, res[0]) +} + +func dnslinkServerHandlerFunc(t *testing.T, dnslinkName string, txtResponse string) func(w http.ResponseWriter, req *http.Request) { + return func(w http.ResponseWriter, req *http.Request) { + b, err := io.ReadAll(req.Body) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + msg := &dns.Msg{} + err = msg.Unpack(b) + require.NoError(t, err) + var answers []dns.RR + for _, q := range msg.Question { + if strings.ToLower(q.Name) != fmt.Sprintf("_dnslink.%s.", dnslinkName) || q.Qtype != dns.TypeTXT { + answers = append(answers, &dns.RR_Header{ + Name: q.Name, + Rrtype: dns.RcodeServerFailure, + Class: q.Qclass, + Ttl: 0, + }) + } else { + answers = append(answers, &dns.TXT{ + Hdr: dns.RR_Header{ + Name: q.Name, + Rrtype: dns.TypeTXT, + Class: dns.ClassINET, + Ttl: uint32(3600), + }, + Txt: []string{txtResponse}, + }) + } + } + var m dns.Msg + m.SetReply(msg) + m.Authoritative = true + m.Answer = answers + encoded, err := m.Pack() + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + w.Header().Set("Content-Type", "application/dns-message") + w.WriteHeader(http.StatusOK) + if _, err := w.Write(encoded); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + } +} diff --git a/gateway/gateway_test.go b/gateway/gateway_test.go index e4a9935ac..349d76a0e 100644 --- a/gateway/gateway_test.go +++ b/gateway/gateway_test.go @@ -700,13 +700,13 @@ func TestRedirects(t *testing.T) { // - Browsers will send original URI in URL-escaped form // - We expect query parameters to be persisted // - We drop fragments, as those should not be sent by a browser - {"/ipfs/?uri=ipfs%3A%2F%2FQmXoypizjW3WknFiJnKLwHCnL72vedxjQkDDP1mXWo6uco%2Fwiki%2FFoo_%C4%85%C4%99.html%3Ffilename%3Dtest-%C4%99.html%23header-%C4%85", http.StatusMovedPermanently, "/ipfs/QmXoypizjW3WknFiJnKLwHCnL72vedxjQkDDP1mXWo6uco/wiki/Foo_%c4%85%c4%99.html?filename=test-%c4%99.html"}, - {"/ipfs/?uri=ipns%3A%2F%2Fexample.com%2Fwiki%2FFoo_%C4%85%C4%99.html%3Ffilename%3Dtest-%C4%99.html", http.StatusMovedPermanently, "/ipns/example.com/wiki/Foo_%c4%85%c4%99.html?filename=test-%c4%99.html"}, + {"/ipfs/?uri=ipfs%3A%2F%2FQmXoypizjW3WknFiJnKLwHCnL72vedxjQkDDP1mXWo6uco%2Fwiki%2FFoo_%C4%85%C4%99.html%3Ffilename%3Dtest-%C4%99.html%23header-%C4%85", http.StatusMovedPermanently, "/ipfs/QmXoypizjW3WknFiJnKLwHCnL72vedxjQkDDP1mXWo6uco/wiki/Foo_%C4%85%C4%99.html?filename=test-%C4%99.html"}, + {"/ipfs/?uri=ipns%3A%2F%2Fexample.com%2Fwiki%2FFoo_%C4%85%C4%99.html%3Ffilename%3Dtest-%C4%99.html", http.StatusMovedPermanently, "/ipns/example.com/wiki/Foo_%C4%85%C4%99.html?filename=test-%C4%99.html"}, {"/ipfs/?uri=ipfs://" + cid, http.StatusMovedPermanently, "/ipfs/" + cid}, {"/ipfs?uri=ipfs://" + cid, http.StatusMovedPermanently, "/ipfs/" + cid}, {"/ipfs/?uri=ipns://" + cid, http.StatusMovedPermanently, "/ipns/" + cid}, - {"/ipns/?uri=ipfs%3A%2F%2FQmXoypizjW3WknFiJnKLwHCnL72vedxjQkDDP1mXWo6uco%2Fwiki%2FFoo_%C4%85%C4%99.html%3Ffilename%3Dtest-%C4%99.html%23header-%C4%85", http.StatusMovedPermanently, "/ipfs/QmXoypizjW3WknFiJnKLwHCnL72vedxjQkDDP1mXWo6uco/wiki/Foo_%c4%85%c4%99.html?filename=test-%c4%99.html"}, - {"/ipns/?uri=ipns%3A%2F%2Fexample.com%2Fwiki%2FFoo_%C4%85%C4%99.html%3Ffilename%3Dtest-%C4%99.html", http.StatusMovedPermanently, "/ipns/example.com/wiki/Foo_%c4%85%c4%99.html?filename=test-%c4%99.html"}, + {"/ipns/?uri=ipfs%3A%2F%2FQmXoypizjW3WknFiJnKLwHCnL72vedxjQkDDP1mXWo6uco%2Fwiki%2FFoo_%C4%85%C4%99.html%3Ffilename%3Dtest-%C4%99.html%23header-%C4%85", http.StatusMovedPermanently, "/ipfs/QmXoypizjW3WknFiJnKLwHCnL72vedxjQkDDP1mXWo6uco/wiki/Foo_%C4%85%C4%99.html?filename=test-%C4%99.html"}, + {"/ipns/?uri=ipns%3A%2F%2Fexample.com%2Fwiki%2FFoo_%C4%85%C4%99.html%3Ffilename%3Dtest-%C4%99.html", http.StatusMovedPermanently, "/ipns/example.com/wiki/Foo_%C4%85%C4%99.html?filename=test-%C4%99.html"}, {"/ipns?uri=ipns://" + cid, http.StatusMovedPermanently, "/ipns/" + cid}, {"/ipns/?uri=ipns://" + cid, http.StatusMovedPermanently, "/ipns/" + cid}, {"/ipns/?uri=ipfs://" + cid, http.StatusMovedPermanently, "/ipfs/" + cid}, diff --git a/gateway/handler.go b/gateway/handler.go index d6e1b7054..3281788fe 100644 --- a/gateway/handler.go +++ b/gateway/handler.go @@ -906,9 +906,10 @@ func handleProtocolHandlerRedirect(w http.ResponseWriter, r *http.Request, c *Co webError(w, r, c, fmt.Errorf("uri query parameter scheme must be ipfs or ipns: %w", err), http.StatusBadRequest) return true } - path := u.Path + + path := u.EscapedPath() if u.RawQuery != "" { // preserve query if present - path = path + "?" + u.RawQuery + path += "?" + url.PathEscape(u.RawQuery) } redirectURL := gopath.Join("/", u.Scheme, u.Host, path) @@ -989,7 +990,7 @@ func (i *handler) handleSuperfluousNamespace(w http.ResponseWriter, r *http.Requ } // Attempt to fix the superflous namespace - intendedPath, err := path.NewPath(strings.TrimPrefix(r.URL.Path, "/ipfs")) + intendedPath, err := path.NewPath(strings.TrimPrefix(r.URL.EscapedPath(), "/ipfs")) if err != nil { i.webError(w, r, fmt.Errorf("invalid ipfs path: %w", err), http.StatusBadRequest) return true diff --git a/gateway/handler_codec.go b/gateway/handler_codec.go index 89bff966e..b3b1fcce2 100644 --- a/gateway/handler_codec.go +++ b/gateway/handler_codec.go @@ -170,10 +170,15 @@ func (i *handler) serveCodecHTML(ctx context.Context, w http.ResponseWriter, r * suffix := "/" // preserve query parameters if r.URL.RawQuery != "" { - suffix = suffix + "?" + r.URL.RawQuery + suffix = suffix + "?" + url.PathEscape(r.URL.RawQuery) + } + // Re-escape path instead of reusing RawPath to avod mix of lawer + // and upper hex that may come from RawPath. + if strings.ContainsRune(requestURI.RawPath, '%') { + requestURI.RawPath = "" } // /ipfs/cid/foo?bar must be redirected to /ipfs/cid/foo/?bar - redirectURL := requestURI.Path + suffix + redirectURL := requestURI.EscapedPath() + suffix http.Redirect(w, r, redirectURL, http.StatusMovedPermanently) return true } diff --git a/gateway/handler_unixfs_dir.go b/gateway/handler_unixfs_dir.go index 6f9f856d1..39d7fe4a7 100644 --- a/gateway/handler_unixfs_dir.go +++ b/gateway/handler_unixfs_dir.go @@ -47,11 +47,17 @@ func (i *handler) serveDirectory(ctx context.Context, w http.ResponseWriter, r * suffix := "/" // preserve query parameters if r.URL.RawQuery != "" { - suffix = suffix + "?" + r.URL.RawQuery + suffix = suffix + "?" + url.PathEscape(r.URL.RawQuery) + } + // Re-escape path instead of reusing RawPath to avod mix of lawer + // and upper hex that may come from RawPath. + if strings.ContainsRune(requestURI.RawPath, '%') { + requestURI.RawPath = "" } // /ipfs/cid/foo?bar must be redirected to /ipfs/cid/foo/?bar - redirectURL := originalURLPath + suffix + redirectURL := requestURI.EscapedPath() + suffix rq.logger.Debugw("directory location moved permanently", "status", http.StatusMovedPermanently) + http.Redirect(w, r, redirectURL, http.StatusMovedPermanently) return true } diff --git a/go.mod b/go.mod index 2e95cd8d0..d31a2aabc 100644 --- a/go.mod +++ b/go.mod @@ -40,7 +40,7 @@ require ( github.com/ipld/go-codec-dagpb v1.6.0 github.com/ipld/go-ipld-prime v0.21.0 github.com/libp2p/go-buffer-pool v0.1.0 - github.com/libp2p/go-doh-resolver v0.4.0 + github.com/libp2p/go-doh-resolver v0.5.0 github.com/libp2p/go-libp2p v0.38.1 github.com/libp2p/go-libp2p-kad-dht v0.28.1 github.com/libp2p/go-libp2p-record v0.2.0 diff --git a/go.sum b/go.sum index 1e9689a83..6830ecfbb 100644 --- a/go.sum +++ b/go.sum @@ -271,8 +271,8 @@ github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6 github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38yPW7c= github.com/libp2p/go-cidranger v1.1.0/go.mod h1:KWZTfSr+r9qEo9OkI9/SIEeAtw+NNoU0dXIXt15Okic= -github.com/libp2p/go-doh-resolver v0.4.0 h1:gUBa1f1XsPwtpE1du0O+nnZCUqtG7oYi7Bb+0S7FQqw= -github.com/libp2p/go-doh-resolver v0.4.0/go.mod h1:v1/jwsFusgsWIGX/c6vCRrnJ60x7bhTiq/fs2qt0cAg= +github.com/libp2p/go-doh-resolver v0.5.0 h1:4h7plVVW+XTS+oUBw2+8KfoM1jF6w8XmO7+skhePFdE= +github.com/libp2p/go-doh-resolver v0.5.0/go.mod h1:aPDxfiD2hNURgd13+hfo29z9IC22fv30ee5iM31RzxU= github.com/libp2p/go-flow-metrics v0.2.0 h1:EIZzjmeOE6c8Dav0sNv35vhZxATIXWZg6j/C08XmmDw= github.com/libp2p/go-flow-metrics v0.2.0/go.mod h1:st3qqfu8+pMfh+9Mzqb2GTiwrAGjIPszEjZmtksN8Jc= github.com/libp2p/go-libp2p v0.38.1 h1:aT1K7IFWi+gZUsQGCzTHBTlKX5QVZQOahng8DnOr6tQ= @@ -308,7 +308,6 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= -github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ= github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ= github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8= @@ -331,10 +330,8 @@ github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYg github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0= github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4= github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo= -github.com/multiformats/go-multiaddr v0.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4= github.com/multiformats/go-multiaddr v0.14.0 h1:bfrHrJhrRuh/NXH5mCnemjpbGjzRw/b+tJFOD41g2tU= github.com/multiformats/go-multiaddr v0.14.0/go.mod h1:6EkVAxtznq2yC3QT5CM1UTAwG0GTP3EWAIcjHuzQ+r4= -github.com/multiformats/go-multiaddr-dns v0.3.0/go.mod h1:mNzQ4eTGDg0ll1N9jKPOUogZPoJ30W8a7zk66FQPpdQ= github.com/multiformats/go-multiaddr-dns v0.4.1 h1:whi/uCLbDS3mSEUMb1MsoT4uzUeZB0N32yzufqS0i5M= github.com/multiformats/go-multiaddr-dns v0.4.1/go.mod h1:7hfthtB4E4pQwirrz+J0CcDUfbWzTqEzVyYKKIKpgkc= github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= @@ -348,7 +345,6 @@ github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7B github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM= github.com/multiformats/go-multistream v0.6.0 h1:ZaHKbsL404720283o4c/IHQXiS6gb8qAN5EIJ4PN5EA= github.com/multiformats/go-multistream v0.6.0/go.mod h1:MOyoG5otO24cHIg8kf9QW2/NozURlkP/rvi2FQJyCPg= -github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8= github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= @@ -666,7 +662,6 @@ golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/mfs/dir.go b/mfs/dir.go index 581f446a6..5eed9426b 100644 --- a/mfs/dir.go +++ b/mfs/dir.go @@ -29,7 +29,7 @@ var ( type Directory struct { inode - // Internal cache with added entries to the directory, its cotents + // Internal cache with added entries to the directory, its contents // are synched with the underlying `unixfsDir` node in `sync()`. entriesCache map[string]FSNode diff --git a/namesys/interface.go b/namesys/interface.go index 1befee855..cef8d8c05 100644 --- a/namesys/interface.go +++ b/namesys/interface.go @@ -207,7 +207,7 @@ func PublishWithEOL(eol time.Time) PublishOption { } } -// PublishWithEOL sets [PublishOptions.TTL]. +// PublishWithTTL sets [PublishOptions.TTL]. func PublishWithTTL(ttl time.Duration) PublishOption { return func(o *PublishOptions) { o.TTL = ttl diff --git a/namesys/republisher/repub.go b/namesys/republisher/repub.go index 95e440436..71aeb4af9 100644 --- a/namesys/republisher/repub.go +++ b/namesys/republisher/repub.go @@ -196,5 +196,5 @@ func (rp *Republisher) getLastIPNSRecord(ctx context.Context, name ipns.Name) (* var tracer = otel.Tracer("boxo/namesys/republisher") func startSpan(ctx context.Context, name string, opts ...trace.SpanStartOption) (context.Context, trace.Span) { - return tracer.Start(ctx, "Namesys."+name) + return tracer.Start(ctx, "Namesys."+name, opts...) } diff --git a/pinning/pinner/dspinner/pin_test.go b/pinning/pinner/dspinner/pin_test.go index cbc1e6c34..153a3bc16 100644 --- a/pinning/pinner/dspinner/pin_test.go +++ b/pinning/pinner/dspinner/pin_test.go @@ -367,7 +367,7 @@ func TestAddLoadPin(t *testing.T) { t.Fatal(err) } if pinData.Mode != mode { - t.Error("worng pin mode") + t.Error("wrong pin mode") } if pinData.Cid != ak { t.Error("wrong pin cid") @@ -428,8 +428,8 @@ func TestPinAddOverwriteName(t *testing.T) { } func TestIsPinnedLookup(t *testing.T) { - // Test that lookups work in pins which share - // the same branches. For that construct this tree: + // Test that lookups work in pins which share the same branches. For that + // construct this tree: // // A5->A4->A3->A2->A1->A0 // / / @@ -437,8 +437,8 @@ func TestIsPinnedLookup(t *testing.T) { // \ / // C--------------- // - // This ensures that IsPinned works for all objects both when they - // are pinned and once they have been unpinned. + // This ensures that IsPinned works for all objects both when they are + // pinned and once they have been unpinned. aBranchLen := 6 ctx, cancel := context.WithCancel(context.Background()) @@ -449,8 +449,8 @@ func TestIsPinnedLookup(t *testing.T) { dserv := mdag.NewDAGService(bserv) - // Create new pinner. New will not load anything since there are - // no pins saved in the datastore yet. + // Create new pinner. New will not load anything since there are no pins + // saved in the datastore yet. p, err := New(ctx, dstore, dserv) if err != nil { t.Fatal(err) @@ -563,7 +563,7 @@ func TestPinRecursiveFail(t *testing.T) { t.Fatal(err) } - // NOTE: This isnt a time based test, we expect the pin to fail + // NOTE: This isn't a time based test, we expect the pin to fail mctx, cancel := context.WithTimeout(ctx, time.Millisecond) defer cancel() @@ -582,7 +582,7 @@ func TestPinRecursiveFail(t *testing.T) { t.Fatal(err) } - // this one is time based... but shouldnt cause any issues + // this one is time based... but shouldn't cause any issues mctx, cancel = context.WithTimeout(ctx, time.Second) defer cancel() err = p.Pin(mctx, a, true, "") @@ -732,7 +732,7 @@ func TestLoadDirty(t *testing.T) { t.Fatal("index should be deleted") } - // Create new pinner on same datastore that was never flushed. This should + // Create new pinner on same datastore that was never flushed. This should // detect the dirty flag and repair the indexes. p, err = New(ctx, dstore, dserv) if err != nil { @@ -950,7 +950,7 @@ func makeStore() (ds.Datastore, ipld.DAGService) { return dstore, dserv } -// BenchmarkLoadRebuild loads a pinner that has some number of saved pins, and +// BenchmarkLoad loads a pinner that has some number of saved pins, and // compares the load time when rebuilding indexes to loading without rebuilding // indexes. func BenchmarkLoad(b *testing.B) { @@ -995,8 +995,8 @@ func BenchmarkLoad(b *testing.B) { }) } -// BenchmarkNthPins shows the time it takes to create/save 1 pin when a number -// of other pins already exist. Each run in the series shows performance for +// BenchmarkNthPin shows the time it takes to create/save 1 pin when a number +// of other pins already exist. Each run in the series shows performance for // creating a pin in a larger number of existing pins. func BenchmarkNthPin(b *testing.B) { dstore, dserv := makeStore() @@ -1044,8 +1044,8 @@ func benchmarkNthPin(b *testing.B, count int, pinner ipfspin.Pinner, dserv ipld. } } -// BenchmarkNPins demonstrates creating individual pins. Each run in the -// series shows performance for a larger number of individual pins. +// BenchmarkNPins demonstrates creating individual pins. Each run in the series +// shows performance for a larger number of individual pins. func BenchmarkNPins(b *testing.B) { for count := 128; count < 16386; count <<= 1 { b.Run(fmt.Sprint("PinDS-", count), func(b *testing.B) { @@ -1270,7 +1270,7 @@ func TestCidIndex(t *testing.T) { defer results.Close() // Iterate all pins and check if the corresponding recursive or direct - // index is missing. If the index is missing then create the index. + // index is missing. If the index is missing then create the index. seen = false for r := range results.Next() { if seen { diff --git a/routing/http/filters/filters.go b/routing/http/filters/filters.go index 122f625de..c88bbcf41 100644 --- a/routing/http/filters/filters.go +++ b/routing/http/filters/filters.go @@ -49,7 +49,7 @@ func AddFiltersToURL(baseURL string, protocolFilter, addrFilter []string) string return parsedURL.String() } -// applyFiltersToIter applies the filters to the given iterator and returns a new iterator. +// ApplyFiltersToIter applies the filters to the given iterator and returns a new iterator. // // The function iterates over the input iterator, applying the specified filters to each record. // It supports both positive and negative filters for both addresses and protocols. diff --git a/routing/http/internal/goroutines.go b/routing/http/internal/goroutines.go index 4c44428ab..af5c14e68 100644 --- a/routing/http/internal/goroutines.go +++ b/routing/http/internal/goroutines.go @@ -7,8 +7,10 @@ import ( "github.com/samber/lo" ) -// DoBatch processes a slice of items with concurrency no higher than maxConcurrency by splitting it into batches no larger than maxBatchSize. -// If an error is returned for any batch, the process is short-circuited and the error is immediately returned. +// DoBatch processes a slice of items with concurrency no higher than +// maxConcurrency by splitting it into batches no larger than maxBatchSize. If +// an error is returned for any batch, the process is short-circuited and the +// error is immediately returned. func DoBatch[A any](ctx context.Context, maxBatchSize, maxConcurrency int, items []A, f func(context.Context, []A) error) error { if len(items) == 0 { return nil @@ -62,8 +64,8 @@ func DoBatch[A any](ctx context.Context, maxBatchSize, maxConcurrency int, items // we finished without any errors, congratulations return nil } - // short circuit on the first error we get - // canceling the worker ctx and thus all workers, + // short circuit on the first error we get canceling the worker ctx and + // thus all workers, return err case <-ctx.Done(): return ctx.Err() diff --git a/version.json b/version.json index 0bab82458..5fa2fecc2 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "v0.25.0" + "version": "v0.26.0" }