Last active
April 12, 2023 00:25
-
-
Save Lajule/e7f98d5839056d83bb286764a307570a to your computer and use it in GitHub Desktop.
Golang HTTP Server
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package server | |
import ( | |
"context" | |
"crypto/tls" | |
"crypto/x509" | |
"fmt" | |
"html/template" | |
"io/fs" | |
"log" | |
"net/http" | |
"os" | |
"os/signal" | |
"syscall" | |
"time" | |
"github.com/gin-gonic/gin" | |
) | |
type Server struct { | |
http.Server | |
} | |
func NewServer(bindAddr, caCert string, views, assets fs.FS) *Server { | |
router := gin.Default() | |
if views != nil { | |
templates := template.New("") | |
if err := fs.WalkDir(views, ".", func(path string, info fs.DirEntry, e error) error { | |
if e != nil { | |
return fmt.Errorf("failed accessing path: %w", e) | |
} | |
if info.IsDir() { | |
return nil | |
} | |
file, err := fs.ReadFile(views, path) | |
if err != nil { | |
return fmt.Errorf("failed reading file: %w", err) | |
} | |
if _, err := templates.Parse(string(file)); err != nil { | |
return fmt.Errorf("failed parsing template: %w", err) | |
} | |
return nil | |
}); err != nil { | |
log.Fatalf("failed creating views resources: %v", err) | |
} | |
router.SetHTMLTemplate(templates) | |
} | |
if assets != nil { | |
router.StaticFS("/assets", http.FS(assets)) | |
} | |
var tlsConfig *tls.Config | |
if len(caCert) > 0 { | |
pool := x509.NewCertPool() | |
data, err := os.ReadFile(caCert) | |
if err != nil { | |
log.Fatalf("failed opening trusted SSL Certificate Authorities file: %v", err) | |
} | |
if !pool.AppendCertsFromPEM(data) { | |
log.Fatal("failed parsing CA certificate") | |
} | |
tlsConfig = &tls.Config{ | |
RootCAs: pool, | |
ClientAuth: tls.RequireAndVerifyClientCert, | |
MinVersion: tls.VersionTLS12, | |
} | |
} | |
return &Server{ | |
Server: http.Server{ | |
Addr: bindAddr, | |
Handler: router, | |
TLSConfig: tlsConfig, | |
}, | |
} | |
} | |
func (srv *Server) Start(clientCert, clientKey string, gracefulShutdownTimeout time.Duration) { | |
go func() { | |
var fn string | |
var err error | |
if len(clientCert) > 0 && len(clientKey) > 0 { | |
fn = "ListenAndServeTLS" | |
err = srv.ListenAndServeTLS(clientCert, clientKey) | |
} else { | |
fn = "ListenAndServe" | |
err = srv.ListenAndServe() | |
} | |
if err != http.ErrServerClosed { | |
log.Fatalf("failed listenning and serving (%v): %v", fn, err) | |
} | |
}() | |
quit := make(chan os.Signal, 1) | |
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) | |
<-quit | |
log.Println("shutting down server...") | |
ctx, cancel := context.WithTimeout(context.Background(), gracefulShutdownTimeout) | |
defer cancel() | |
if err := srv.Shutdown(ctx); err != nil { | |
log.Fatalf("server forced to shutdown: %v", err) | |
} | |
log.Println("server exiting...") | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.