mirror of
https://github.com/ipfs/kubo.git
synced 2026-02-22 02:47:48 +08:00
I'm not entirely clear on the role that this package is filling, but this description seems like a reasonable guess based on a quick skim through it's exported API.
107 lines
2.9 KiB
Go
107 lines
2.9 KiB
Go
/*
|
|
Package corehttp provides utilities for the webui, gateways, and other
|
|
high-level HTTP interfaces to IPFS.
|
|
*/
|
|
package corehttp
|
|
|
|
import (
|
|
"net/http"
|
|
"time"
|
|
|
|
manners "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/braintree/manners"
|
|
ma "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
|
|
manet "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr-net"
|
|
core "github.com/ipfs/go-ipfs/core"
|
|
eventlog "github.com/ipfs/go-ipfs/thirdparty/eventlog"
|
|
)
|
|
|
|
var log = eventlog.Logger("core/server")
|
|
|
|
// ServeOption registers any HTTP handlers it provides on the given mux.
|
|
// It returns the mux to expose to future options, which may be a new mux if it
|
|
// is interested in mediating requests to future options, or the same mux
|
|
// initially passed in if not.
|
|
type ServeOption func(*core.IpfsNode, *http.ServeMux) (*http.ServeMux, error)
|
|
|
|
// makeHandler turns a list of ServeOptions into a http.Handler that implements
|
|
// all of the given options, in order.
|
|
func makeHandler(n *core.IpfsNode, options ...ServeOption) (http.Handler, error) {
|
|
topMux := http.NewServeMux()
|
|
mux := topMux
|
|
for _, option := range options {
|
|
var err error
|
|
mux, err = option(n, mux)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
return topMux, nil
|
|
}
|
|
|
|
// ListenAndServe runs an HTTP server listening at |listeningMultiAddr| with
|
|
// the given serve options. The address must be provided in multiaddr format.
|
|
//
|
|
// TODO intelligently parse address strings in other formats so long as they
|
|
// unambiguously map to a valid multiaddr. e.g. for convenience, ":8080" should
|
|
// map to "/ip4/0.0.0.0/tcp/8080".
|
|
func ListenAndServe(n *core.IpfsNode, listeningMultiAddr string, options ...ServeOption) error {
|
|
addr, err := ma.NewMultiaddr(listeningMultiAddr)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
handler, err := makeHandler(n, options...)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return listenAndServe(n, addr, handler)
|
|
}
|
|
|
|
func listenAndServe(node *core.IpfsNode, addr ma.Multiaddr, handler http.Handler) error {
|
|
_, host, err := manet.DialArgs(addr)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
server := manners.NewServer()
|
|
|
|
// if the server exits beforehand
|
|
var serverError error
|
|
serverExited := make(chan struct{})
|
|
|
|
node.Children().Add(1)
|
|
defer node.Children().Done()
|
|
|
|
go func() {
|
|
serverError = server.ListenAndServe(host, handler)
|
|
close(serverExited)
|
|
}()
|
|
|
|
// wait for server to exit.
|
|
select {
|
|
case <-serverExited:
|
|
|
|
// if node being closed before server exits, close server
|
|
case <-node.Closing():
|
|
log.Infof("server at %s terminating...", addr)
|
|
|
|
// make sure keep-alive connections do not keep the server running
|
|
server.InnerServer.SetKeepAlivesEnabled(false)
|
|
|
|
server.Shutdown <- true
|
|
|
|
outer:
|
|
for {
|
|
// wait until server exits
|
|
select {
|
|
case <-serverExited:
|
|
break outer
|
|
case <-time.After(5 * time.Second):
|
|
log.Infof("waiting for server at %s to terminate...", addr)
|
|
}
|
|
}
|
|
}
|
|
|
|
log.Infof("server at %s terminated", addr)
|
|
return serverError
|
|
}
|