11package server
22
33import (
4+ "errors"
45 "reflect"
56 "slices"
67 "strings"
78
89 "github.com/ipfs/boxo/routing/http/types"
10+ "github.com/ipfs/boxo/routing/http/types/iter"
911 "github.com/multiformats/go-multiaddr"
1012)
1113
@@ -18,18 +20,68 @@ func parseFilter(param string) []string {
1820 return strings .Split (strings .ToLower (param ), "," )
1921}
2022
21- func filterProviders (providers []types.Record , filterAddrs , filterProtocols []string ) []types.Record {
23+ // applyFiltersToIter applies the filters to the given iterator and returns a new iterator.
24+ func applyFiltersToIter (recordsIter iter.ResultIter [types.Record ], filterAddrs , filterProtocols []string ) iter.ResultIter [types.Record ] {
25+ mappedIter := iter .Map (recordsIter , func (v iter.Result [types.Record ]) iter.Result [types.Record ] {
26+ if v .Err != nil || v .Val == nil {
27+ return v
28+ }
29+
30+ switch v .Val .GetSchema () {
31+ case types .SchemaPeer :
32+ record , ok := v .Val .(* types.PeerRecord )
33+ if ! ok {
34+ logger .Errorw ("problem casting find providers record" , "Schema" , v .Val .GetSchema (), "Type" , reflect .TypeOf (v ).String ())
35+ // TODO: Do we want to let failed type assertions to pass through?
36+ return v
37+ }
38+
39+ record = applyFilters (record , filterAddrs , filterProtocols )
40+ if record == nil {
41+ return iter.Result [types.Record ]{Err : errors .New ("record is nil" )}
42+ }
43+ v .Val = record
44+
45+ //lint:ignore SA1019 // ignore staticcheck
46+ case types .SchemaBitswap :
47+ //lint:ignore SA1019 // ignore staticcheck
48+ record , ok := v .Val .(* types.BitswapRecord )
49+ if ! ok {
50+ logger .Errorw ("problem casting find providers record" , "Schema" , v .Val .GetSchema (), "Type" , reflect .TypeOf (v ).String ())
51+ // TODO: Do we want to let failed type assertions to pass through?
52+ return v
53+ }
54+ peerRecord := types .FromBitswapRecord (record )
55+ peerRecord = applyFilters (peerRecord , filterAddrs , filterProtocols )
56+ if peerRecord == nil {
57+ return iter.Result [types.Record ]{Err : errors .New ("record is nil" )}
58+ }
59+ v .Val = peerRecord
60+ }
61+ return v
62+ })
63+
64+ // filter out nil results and errors
65+ filteredIter := iter .Filter (mappedIter , func (v iter.Result [types.Record ]) bool {
66+ return v .Err == nil && v .Val != nil
67+ })
68+
69+ return filteredIter
70+ }
71+
72+ func filterRecords (records []types.Record , filterAddrs , filterProtocols []string ) []types.Record {
2273 if len (filterAddrs ) == 0 && len (filterProtocols ) == 0 {
23- return providers
74+ return records
2475 }
2576
26- filtered := make ([]types.Record , 0 , len (providers ))
77+ filtered := make ([]types.Record , 0 , len (records ))
2778
28- for _ , provider := range providers {
29- if schema := provider .GetSchema (); schema == types .SchemaPeer {
30- peer , ok := provider .(* types.PeerRecord )
79+ for _ , record := range records {
80+ // TODO: Handle SchemaBitswap
81+ if schema := record .GetSchema (); schema == types .SchemaPeer {
82+ peer , ok := record .(* types.PeerRecord )
3183 if ! ok {
32- logger .Errorw ("problem casting find providers result" , "Schema" , provider .GetSchema (), "Type" , reflect .TypeOf (provider ).String ())
84+ logger .Errorw ("problem casting find providers result" , "Schema" , record .GetSchema (), "Type" , reflect .TypeOf (record ).String ())
3385 // if the type assertion fails, we exlude record from results
3486 continue
3587 }
@@ -42,7 +94,7 @@ func filterProviders(providers []types.Record, filterAddrs, filterProtocols []st
4294
4395 } else {
4496 // Will we ever encounter the SchemaBitswap type? Evidence seems to suggest that no longer
45- logger .Errorw ("encountered unknown provider schema" , "Schema" , provider .GetSchema (), "Type" , reflect .TypeOf (provider ).String ())
97+ logger .Errorw ("encountered unknown provider schema" , "Schema" , record .GetSchema (), "Type" , reflect .TypeOf (record ).String ())
4698 }
4799 }
48100 return filtered
@@ -51,6 +103,10 @@ func filterProviders(providers []types.Record, filterAddrs, filterProtocols []st
51103// Applies the filters. Returns nil if the provider does not pass the protocols filter
52104// The address filter is more complicated because it potentially modifies the Addrs slice.
53105func applyFilters (provider * types.PeerRecord , filterAddrs , filterProtocols []string ) * types.PeerRecord {
106+ if len (filterAddrs ) == 0 && len (filterProtocols ) == 0 {
107+ return provider
108+ }
109+
54110 if ! applyProtocolFilter (provider .Protocols , filterProtocols ) {
55111 // If the provider doesn't match any of the passed protocols, the provider is omitted from the response.
56112 return nil
0 commit comments