4343 DefaultIdleConnTimeout = 30 * time .Second
4444 DefaultResponseHeaderTimeout = 10 * time .Second
4545 DefaultMaxIdleConns = 50
46- DefaultSupportsHave = true
4746 DefaultInsecureSkipVerify = false
4847 DefaultMaxBackoff = time .Minute
4948 DefaultMaxHTTPAddressesPerPeer = 10
@@ -54,6 +53,8 @@ var pingCid = "bafkqaaa" // identity CID
5453
5554const http2proto = "HTTP/2.0"
5655
56+ const peerstoreSupportsHeadKey = "http-retrieval-head-support"
57+
5758// Option allows to configure the Network.
5859type Option func (net * Network )
5960
@@ -103,15 +104,6 @@ func WithMaxIdleConns(n int) Option {
103104 }
104105}
105106
106- // WithSupportsHave specifies whether want to expose that we can handle Have
107- // messages (i.e. to the MessageQueue). Have messages trigger HEAD HTTP
108- // requests. Not all HTTP-endpoints may know how to handle a HEAD request.
109- func WithSupportsHave (b bool ) Option {
110- return func (net * Network ) {
111- net .supportsHave = b
112- }
113- }
114-
115107// WithInsecureSkipVerify allows making HTTPS connections to test servers.
116108// Use for testing.
117109func WithInsecureSkipVerify (b bool ) Option {
@@ -169,7 +161,6 @@ type Network struct {
169161 idleConnTimeout time.Duration
170162 responseHeaderTimeout time.Duration
171163 maxIdleConns int
172- supportsHave bool
173164 insecureSkipVerify bool
174165 maxHTTPAddressesPerPeer int
175166 httpWorkers int
@@ -203,7 +194,6 @@ func New(host host.Host, opts ...Option) network.BitSwapNetwork {
203194 idleConnTimeout : DefaultIdleConnTimeout ,
204195 responseHeaderTimeout : DefaultResponseHeaderTimeout ,
205196 maxIdleConns : DefaultMaxIdleConns ,
206- supportsHave : DefaultSupportsHave ,
207197 insecureSkipVerify : DefaultInsecureSkipVerify ,
208198 maxHTTPAddressesPerPeer : DefaultMaxHTTPAddressesPerPeer ,
209199 httpWorkers : DefaultHTTPWorkers ,
@@ -408,42 +398,37 @@ func (ht *Network) Connect(ctx context.Context, p peer.AddrInfo) error {
408398 // time with the client. We call peer.Connected()
409399 // on success.
410400 var workingAddrs []multiaddr.Multiaddr
401+ supportsHead := true
411402 for i , u := range urls {
412- req , err := buildRequest (ctx , u , "GET" , pingCid , ht .userAgent )
413- if err != nil {
414- log .Debug (err )
415- return err
416- }
417-
418- log .Debugf ("connect request to %s %q" , p .ID , req .URL )
419- resp , err := ht .client .Do (req )
403+ err := ht .connect (ctx , p .ID , u , "GET" )
420404 if err != nil {
421- log . Debugf ( "connect error %s" , err )
405+ // abort if context cancelled
422406 if ctxErr := ctx .Err (); ctxErr != nil {
423- // abort when context cancelled
424407 return ctxErr
425408 }
426409 continue
427410 }
428-
429- if resp .Proto != http2proto {
430- log .Warnf ("%s://%q is not using HTTP/2 (%s)" , req .URL .Scheme , req .URL .Host , resp .Proto )
411+ // GET works. Does HEAD work though?
412+ err = ht .connect (ctx , p .ID , u , "HEAD" )
413+ if err != nil {
414+ // abort if context cancelled
415+ if ctxErr := ctx .Err (); ctxErr != nil {
416+ return ctxErr
417+ }
418+ supportsHead = false
431419 }
432420
433- if resp .StatusCode >= 500 { // 5xx
434- log .Debugf ("connect error %d <- %s %q" , resp .StatusCode , p .ID , req .URL )
435- // We made a proper request and got a 5xx back.
436- // We cannot consider this a working connection.
437- continue
438- }
439421 workingAddrs = append (workingAddrs , htaddrs .Addrs [i ])
440422 }
441423
442424 if len (workingAddrs ) > 0 {
443425 ht .host .Peerstore ().AddAddrs (p .ID , workingAddrs , peerstore .PermanentAddrTTL )
426+ // ignoring error
427+ _ = ht .host .Peerstore ().Put (p .ID , peerstoreSupportsHeadKey , supportsHead )
428+
444429 ht .connEvtMgr .Connected (p .ID )
445430 ht .pinger .startPinging (p .ID )
446- log .Debugf ("connect success to %s" , p .ID )
431+ log .Debugf ("connect success to %s (supports HEAD: %t) " , p .ID , supportsHead )
447432 // We "connected"
448433 return nil
449434 }
@@ -453,6 +438,32 @@ func (ht *Network) Connect(ctx context.Context, p peer.AddrInfo) error {
453438 return err
454439}
455440
441+ func (ht * Network ) connect (ctx context.Context , p peer.ID , u network.ParsedURL , method string ) error {
442+ req , err := buildRequest (ctx , u , method , pingCid , ht .userAgent )
443+ if err != nil {
444+ log .Debug (err )
445+ return err
446+ }
447+
448+ log .Debugf ("connect request to %s %s %q" , p , method , req .URL )
449+ resp , err := ht .client .Do (req )
450+ if err != nil {
451+ return err
452+ }
453+
454+ if resp .Proto != http2proto {
455+ log .Warnf ("%s://%q is not using HTTP/2 (%s)" , req .URL .Scheme , req .URL .Host , resp .Proto )
456+ }
457+
458+ if resp .StatusCode >= 500 { // 5xx
459+ log .Debugf ("connect error: %d <- %q (%s)" , resp .StatusCode , req .URL , p )
460+ // We made a proper request and got a 5xx back.
461+ // We cannot consider this a working connection.
462+ return err
463+ }
464+ return nil
465+ }
466+
456467// DisconnectFrom marks this peer as Disconnected in the connection event
457468// manager, stops pinging for latency measurements and removes it from the
458469// peerstore.
0 commit comments