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  }