Example #1
0
func Serve(node *core.IpfsNode, lis net.Listener, options ...ServeOption) error {
	handler, err := makeHandler(node, options...)
	if err != nil {
		return err
	}

	addr, err := manet.FromNetAddr(lis.Addr())
	if err != nil {
		return err
	}

	// if the server exits beforehand
	var serverError error
	serverExited := make(chan struct{})

	node.Children().Add(1)
	defer node.Children().Done()

	go func() {
		serverError = http.Serve(lis, 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)

		lis.Close()

	outer:
		for {
			// wait until server exits
			select {
			case <-serverExited:
				// if the server exited as we are closing, we really dont care about errors
				serverError = nil
				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
}