package main import ( "bytes" "fmt" "html/template" "net" "net/http" "os" "strings" "github.com/pkg/errors" log "github.com/Sirupsen/logrus" "github.com/cloudflare/cloudflare-warp/origin" tunnelpogs "github.com/cloudflare/cloudflare-warp/tunnelrpc/pogs" cli "gopkg.in/urfave/cli.v2" ) type templateData struct { ServerName string Request *http.Request Tags []tunnelpogs.Tag } const defaultServerName = "the Cloudflare Warp test server" const indexTemplate = ` Cloudflare Warp Connection

Congrats! You created your first tunnel!

Cloudflare Warp exposes locally running applications to the internet by running an encrypted, virtual tunnel from your laptop or server to Cloudflare's edge network.

Ready for the next step?

Get started here {{if .Tags}}

Connection

{{range .Tags}}
{{.Name}}
{{.Value}}
{{end}}
{{end}}
` func hello(c *cli.Context) error { address := fmt.Sprintf(":%d", c.Int("port")) server := NewHelloWorldServer() if hostname, err := os.Hostname(); err != nil { server.serverName = hostname } err := server.ListenAndServe(address) return errors.Wrap(err, "Fail to start Hello World Server") } func startHelloWorldServer(listener net.Listener, shutdownC <-chan struct{}) error { server := NewHelloWorldServer() if hostname, err := os.Hostname(); err != nil { server.serverName = hostname } httpServer := &http.Server{Addr: listener.Addr().String(), Handler: server} go func() { <-shutdownC httpServer.Close() }() err := httpServer.Serve(listener) return err } type HelloWorldServer struct { responseTemplate *template.Template serverName string } func NewHelloWorldServer() *HelloWorldServer { return &HelloWorldServer{ responseTemplate: template.Must(template.New("index").Parse(indexTemplate)), serverName: defaultServerName, } } func findAvailablePort() (net.Listener, error) { // If the port in address is empty, a port number is automatically chosen. listener, err := net.Listen("tcp", "127.0.0.1:") return listener, err } func (s *HelloWorldServer) ListenAndServe(address string) error { log.Infof("Starting Hello World server on %s", address) err := http.ListenAndServe(address, s) return err } func (s *HelloWorldServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { log.WithField("client", r.RemoteAddr).Infof("%s %s %s", r.Method, r.URL, r.Proto) var buffer bytes.Buffer err := s.responseTemplate.Execute(&buffer, &templateData{ ServerName: s.serverName, Request: r, Tags: tagsFromHeaders(r.Header), }) if err != nil { w.WriteHeader(http.StatusInternalServerError) fmt.Fprintf(w, "error: %v", err) } else { buffer.WriteTo(w) } } func tagsFromHeaders(header http.Header) []tunnelpogs.Tag { var tags []tunnelpogs.Tag for headerName, headerValues := range header { trimmed := strings.TrimPrefix(headerName, origin.TagHeaderNamePrefix) if trimmed == headerName { continue } for _, value := range headerValues { tags = append(tags, tunnelpogs.Tag{Name: trimmed, Value: value}) } } return tags }