package p2p import ( "bytes" "fmt" "net/http" "strings" "github.com/libp2p/go-libp2p-core/host" "github.com/libp2p/go-libp2p-core/peer" ma "github.com/multiformats/go-multiaddr" "github.com/sirupsen/logrus" ) // InfoHandler is a handler to serve /p2p page in metrics. func (s *Service) InfoHandler(w http.ResponseWriter, _ *http.Request) { buf := new(bytes.Buffer) if _, err := fmt.Fprintf(buf, `bootnode=%s self=%s %d peers %v `, s.cfg.BootstrapNodeAddr, selfAddresses(s.host), len(s.host.Network().Peers()), formatPeers(s.host), // Must be last. Writes one entry per row. ); err != nil { logrus.WithError(err).Error("Failed to render p2p info page") return } w.WriteHeader(http.StatusOK) if _, err := w.Write(buf.Bytes()); err != nil { log.WithError(err).Error("Failed to render p2p info page") } } // selfAddresses formats the host data into dialable strings, comma separated. func selfAddresses(h host.Host) string { var addresses []string for _, ma := range h.Addrs() { addresses = append(addresses, ma.String()+"/p2p/"+h.ID().Pretty()) } return strings.Join(addresses, ",") } // Format peer list to dialable addresses, separated by new line. func formatPeers(h host.Host) string { var addresses []string for _, pid := range h.Network().Peers() { addresses = append(addresses, formatPeer(pid, h.Peerstore().PeerInfo(pid).Addrs)) } return strings.Join(addresses, "\n") } // Format single peer info to dialable addresses, comma separated. func formatPeer(pid peer.ID, ma []ma.Multiaddr) string { var addresses []string for _, a := range ma { addresses = append(addresses, a.String()+"/p2p/"+pid.Pretty()) } return strings.Join(addresses, ",") }