github.com/tickoalcantara12/micro/v3@v3.0.0-20221007104245-9d75b9bcbab9/service/api/server/http/http.go (about) 1 // Copyright 2020 Asim Aslam 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // Original source: github.com/micro/go-micro/v3/api/server/http/http.go 16 17 // Package http provides a http server with features; acme, cors, etc 18 package http 19 20 import ( 21 "crypto/tls" 22 "net" 23 "net/http" 24 "os" 25 "sync" 26 27 "github.com/gorilla/handlers" 28 "github.com/tickoalcantara12/micro/v3/service/api" 29 "github.com/tickoalcantara12/micro/v3/service/logger" 30 ) 31 32 type httpServer struct { 33 mux *http.ServeMux 34 opts api.Options 35 36 mtx sync.RWMutex 37 address string 38 exit chan chan error 39 } 40 41 func NewServer(address string, opts ...api.Option) api.Server { 42 var options api.Options 43 for _, o := range opts { 44 o(&options) 45 } 46 47 return &httpServer{ 48 opts: options, 49 mux: http.NewServeMux(), 50 address: address, 51 exit: make(chan chan error), 52 } 53 } 54 55 func (s *httpServer) Address() string { 56 s.mtx.RLock() 57 defer s.mtx.RUnlock() 58 return s.address 59 } 60 61 func (s *httpServer) Init(opts ...api.Option) error { 62 for _, o := range opts { 63 o(&s.opts) 64 } 65 return nil 66 } 67 68 func (s *httpServer) Handle(path string, handler http.Handler) { 69 // TODO: move this stuff out to one place with ServeHTTP 70 71 // apply the wrappers, e.g. auth 72 for _, wrapper := range s.opts.Wrappers { 73 handler = wrapper(handler) 74 } 75 76 // wrap with cors 77 if s.opts.EnableCORS { 78 handler = CombinedCORSHandler(handler) 79 } 80 81 // wrap with logger 82 handler = handlers.CombinedLoggingHandler(os.Stdout, handler) 83 84 s.mux.Handle(path, handler) 85 } 86 87 func (s *httpServer) Start() error { 88 var l net.Listener 89 var err error 90 91 if s.opts.EnableACME && s.opts.ACMEProvider != nil { 92 // should we check the address to make sure its using :443? 93 l, err = s.opts.ACMEProvider.Listen(s.opts.ACMEHosts...) 94 } else if s.opts.EnableTLS && s.opts.TLSConfig != nil { 95 l, err = tls.Listen("tcp", s.address, s.opts.TLSConfig) 96 } else { 97 // otherwise plain listen 98 l, err = net.Listen("tcp", s.address) 99 } 100 if err != nil { 101 return err 102 } 103 104 if logger.V(logger.InfoLevel, logger.DefaultLogger) { 105 logger.Infof("HTTP Server Listening on %s", l.Addr().String()) 106 } 107 108 s.mtx.Lock() 109 s.address = l.Addr().String() 110 s.mtx.Unlock() 111 112 go func() { 113 if err := http.Serve(l, s.mux); err != nil { 114 // temporary fix 115 //logger.Fatal(err) 116 } 117 }() 118 119 go func() { 120 ch := <-s.exit 121 ch <- l.Close() 122 }() 123 124 return nil 125 } 126 127 func (s *httpServer) Stop() error { 128 ch := make(chan error) 129 s.exit <- ch 130 return <-ch 131 } 132 133 func (s *httpServer) String() string { 134 return "http" 135 }