mirror of
https://github.com/giongto35/cloud-game.git
synced 2026-07-22 17:47:11 +00:00
* Merge HTTP and HTTPS routes builder in coordinator * Extract HTTP/S routes * Rename config in coordinator * Generalize child services * Extract games library helper function * Use string address instead of port for HTTP/S * Use a dedicated port extractor function * Add missing GA tag templating * Rename shared server address and port params * Introduce TLS config parameters * Simplify HTTP/S server constructors * Update server auto port roll * Extract init function in worker * Reorder return params of address type port fn * Refactor config handler names * Update TLS default config params * Extract HTTP to HTTPS redirect function * Use httpx in monitoring * Don't log echo requests * Remove error return from the abstract server * Add WSS option to the worker-coordinator connection * Change default worker config * Make worker send its internal connection params * Decouple gamelib from the coordinator * Expose HTTP/S listener address * Keep original HTTP/S addresses * Remove no config handler in worker * Use HTTP-HTTPS redirection * Wrap net.Listener into a struct * Clean http server creation fn * Redirect to https with a generated address * Use URL in the redirector * Use zone address param in worker * Make use of actual addr and port in the monitoring servers * Use auto-justified monitoring addresses info * Add the non-HTTPS worker to HTTPS coordinator connection warning * Embed TLS struct * Move connection API struct into cws package
136 lines
3.1 KiB
Go
136 lines
3.1 KiB
Go
package httpx
|
|
|
|
import (
|
|
"context"
|
|
"log"
|
|
"net/http"
|
|
"net/url"
|
|
"time"
|
|
|
|
"github.com/giongto35/cloud-game/v2/pkg/service"
|
|
"golang.org/x/crypto/acme/autocert"
|
|
)
|
|
|
|
type Server struct {
|
|
http.Server
|
|
service.RunnableService
|
|
|
|
autoCert *autocert.Manager
|
|
opts Options
|
|
|
|
listener *Listener
|
|
redirect *Server
|
|
}
|
|
|
|
func NewServer(address string, handler func(*Server) http.Handler, options ...Option) (*Server, error) {
|
|
opts := &Options{
|
|
Https: false,
|
|
HttpsRedirect: true,
|
|
IdleTimeout: 120 * time.Second,
|
|
ReadTimeout: 5 * time.Second,
|
|
WriteTimeout: 5 * time.Second,
|
|
}
|
|
opts.override(options...)
|
|
|
|
server := &Server{
|
|
Server: http.Server{
|
|
Addr: address,
|
|
IdleTimeout: opts.IdleTimeout,
|
|
ReadTimeout: opts.ReadTimeout,
|
|
WriteTimeout: opts.WriteTimeout,
|
|
},
|
|
opts: *opts,
|
|
}
|
|
// (╯°□°)╯︵ ┻━┻
|
|
server.Handler = handler(server)
|
|
|
|
if opts.Https && opts.IsAutoHttpsCert() {
|
|
server.autoCert = NewTLSConfig(opts.HttpsDomain).CertManager
|
|
server.TLSConfig = server.autoCert.TLSConfig()
|
|
}
|
|
|
|
addr := server.Addr
|
|
if server.Addr == "" {
|
|
addr = ":http"
|
|
if opts.Https {
|
|
addr = ":https"
|
|
}
|
|
log.Printf("Warning! Empty server address has been changed to %v", server.Addr)
|
|
}
|
|
listener, err := NewListener(addr, server.opts.PortRoll)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
server.listener = listener
|
|
|
|
addr = buildAddress(server.Addr, opts.Zone, *listener)
|
|
log.Printf("[server] address was set to %v (%v)", addr, server.Addr)
|
|
server.Addr = addr
|
|
|
|
return server, nil
|
|
}
|
|
|
|
func (s *Server) Run() {
|
|
protocol := s.GetProtocol()
|
|
log.Printf("Starting %s server on %s", protocol, s.Addr)
|
|
|
|
if s.opts.Https && s.opts.HttpsRedirect {
|
|
rdr, err := s.redirection()
|
|
if err != nil {
|
|
log.Fatalf("couldn't init redirection server: %v", err)
|
|
}
|
|
s.redirect = rdr
|
|
go s.redirect.Run()
|
|
}
|
|
|
|
var err error
|
|
if s.opts.Https {
|
|
err = s.ServeTLS(*s.listener, s.opts.HttpsCert, s.opts.HttpsKey)
|
|
} else {
|
|
err = s.Serve(*s.listener)
|
|
}
|
|
switch err {
|
|
case http.ErrServerClosed:
|
|
log.Printf("%s server was closed", protocol)
|
|
return
|
|
default:
|
|
log.Printf("error: %s", err)
|
|
}
|
|
}
|
|
|
|
func (s *Server) Shutdown(ctx context.Context) (err error) {
|
|
if s.redirect != nil {
|
|
err = s.redirect.Shutdown(ctx)
|
|
}
|
|
err = s.Server.Shutdown(ctx)
|
|
return
|
|
}
|
|
|
|
func (s *Server) GetHost() string { return extractHost(s.Addr) }
|
|
|
|
func (s *Server) GetProtocol() string {
|
|
protocol := "http"
|
|
if s.opts.Https {
|
|
protocol = "https"
|
|
}
|
|
return protocol
|
|
}
|
|
|
|
func (s *Server) redirection() (*Server, error) {
|
|
srv, err := NewServer(s.opts.HttpsRedirectAddress, func(serv *Server) http.Handler {
|
|
h := http.NewServeMux()
|
|
h.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
httpsURL := url.URL{Scheme: "https", Host: s.Addr, Path: r.URL.Path, RawQuery: r.URL.RawQuery}
|
|
rdr := httpsURL.String()
|
|
log.Printf("Redirect: http://%s%s -> %s", r.Host, r.URL.String(), rdr)
|
|
http.Redirect(w, r, rdr, http.StatusFound)
|
|
}))
|
|
// do we need this after all?
|
|
if serv.autoCert != nil {
|
|
return serv.autoCert.HTTPHandler(h)
|
|
}
|
|
return h
|
|
})
|
|
log.Printf("Starting HTTP->HTTPS redirection server on %s", srv.Addr)
|
|
return srv, err
|
|
}
|