github.com/simpleiot/simpleiot@v0.18.3/api/server.go (about) 1 package api 2 3 import ( 4 "fmt" 5 "log" 6 "net" 7 "net/http" 8 "net/url" 9 10 "github.com/koding/websocketproxy" 11 "github.com/nats-io/nats.go" 12 ) 13 14 // App is a struct that implements http.Handler interface 15 type App struct { 16 PublicHandler http.Handler 17 V1ApiHandler http.Handler 18 WebsocketProxy http.Handler 19 } 20 21 // Top level handler for http requests in the coap-server process 22 func (h *App) ServeHTTP(res http.ResponseWriter, req *http.Request) { 23 switch req.URL.Path { 24 case "/": 25 headerUpgrade := req.Header["Upgrade"] 26 if h.WebsocketProxy != nil && len(headerUpgrade) > 0 && headerUpgrade[0] == "websocket" { 27 h.WebsocketProxy.ServeHTTP(res, req) 28 } else { 29 h.PublicHandler.ServeHTTP(res, req) 30 } 31 case "/sign-in": 32 req.URL.Path = "/" 33 h.PublicHandler.ServeHTTP(res, req) 34 35 default: 36 head, path := ShiftPath(req.URL.Path) 37 switch head { 38 case "v1": 39 req.URL.Path = path 40 h.V1ApiHandler.ServeHTTP(res, req) 41 default: 42 h.PublicHandler.ServeHTTP(res, req) 43 } 44 } 45 } 46 47 // NewAppHandler returns a new application (root) http handler 48 func NewAppHandler(args ServerArgs) http.Handler { 49 v1 := NewV1Handler(args) 50 if args.Debug { 51 //args.Debug = false 52 v1 = NewHTTPLogger("v1").Handler(v1) 53 } 54 55 var wsProxy http.Handler 56 57 if args.NatsWSPort > 0 { 58 uS := fmt.Sprintf("ws://localhost:%v", args.NatsWSPort) 59 u, err := url.Parse(uS) 60 if err != nil { 61 log.Println("Error with WebSocket URL:", err) 62 } else { 63 wsProxy = websocketproxy.NewProxy(u) 64 } 65 } 66 67 return &App{ 68 PublicHandler: http.FileServer(args.Filesystem), 69 V1ApiHandler: v1, 70 WebsocketProxy: wsProxy, 71 } 72 } 73 74 // ServerArgs can be used to pass arguments to the server subsystem 75 type ServerArgs struct { 76 Port string 77 Filesystem http.FileSystem 78 Debug bool 79 JwtAuth Authorizer 80 AuthToken string 81 NatsWSPort int 82 Nc *nats.Conn 83 } 84 85 // Server represents the HTTP API server 86 type Server struct { 87 args ServerArgs 88 ln net.Listener 89 chStop chan struct{} 90 } 91 92 // NewServer .. 93 func NewServer(args ServerArgs) *Server { 94 return &Server{ 95 args: args, 96 chStop: make(chan struct{}), 97 } 98 } 99 100 // Start the api server 101 func (s *Server) Start() error { 102 log.Println("Starting http server, debug:", s.args.Debug) 103 log.Println("Starting portal on port:", s.args.Port) 104 address := fmt.Sprintf(":%s", s.args.Port) 105 106 var err error 107 s.ln, err = net.Listen("tcp", address) 108 if err != nil { 109 return fmt.Errorf("Error starting api server: %v", err) 110 } 111 112 chError := make(chan error) 113 114 go func() { 115 chError <- http.Serve(s.ln, NewAppHandler(s.args)) 116 }() 117 118 select { 119 case <-s.chStop: 120 s.ln.Close() 121 err = <-chError 122 case err = <-chError: 123 } 124 125 return err 126 } 127 128 // Stop HTTP API 129 func (s *Server) Stop(_ error) { 130 close(s.chStop) 131 }