|
package server
|
Documentation in literate-programming-style is available at:
https://redhatinsights.github.io/ccx-data-pipeline-monitor/packages/server/server.html
|
import (
"context"
"fmt"
"github.com/gorilla/mux"
"log"
"net/http"
"os"
"strings"
"time"
"github.com/RedHatInsights/ccx-data-pipeline-monitor/config"
)
|
HTTPServer in an implementation of Server interface
|
type HTTPServer struct {
Config config . ServerConfig
Serv * http . Server
}
|
New constructs new implementation of Server interface
|
func New ( configuration config . ServerConfig ) * HTTPServer {
return & HTTPServer {
Config : configuration ,
}
}
func logRequestHandler ( writer http . ResponseWriter , request * http . Request , nextHandler http . Handler ) {
log . Println ( "Request URI: " + request . RequestURI )
log . Println ( "Request method: " + request . Method )
nextHandler . ServeHTTP ( writer , request )
}
func staticPage ( filename string ) func ( writer http . ResponseWriter , request * http . Request ) {
log . Println ( "Serving static file" , filename )
return func ( writer http . ResponseWriter , request * http . Request ) {
sendStaticPage ( writer , filename )
}
}
func sendStaticPage ( writer http . ResponseWriter , filename string ) {
|
disable "G304 (CWE-22): Potential file inclusion via variable"
|
body , err := os . ReadFile ( filename )
if err == nil {
writer . Header ( ) . Set ( "Server" , "A Go Web Server" )
writer . Header ( ) . Set ( "Content-Type" , getContentType ( filename ) )
_ , err = fmt . Fprint ( writer , string ( body ) )
if err != nil {
log . Println ( "Error sending response body" , err )
}
} else {
writer . WriteHeader ( http . StatusNotFound )
notFoundResponse ( writer )
}
}
func getContentType ( filename string ) string {
|
TODO: to map
|
switch {
case strings . HasSuffix ( filename , ".html" ) :
return "text/html"
case strings . HasSuffix ( filename , ".js" ) :
return "application/javascript"
case strings . HasSuffix ( filename , ".css" ) :
return "text/css"
}
return "text/html"
}
func writeResponse ( writer http . ResponseWriter , message string ) {
_ , err := fmt . Fprint ( writer , message )
if err != nil {
log . Println ( "Error sending response" , err )
}
}
func notFoundResponse ( writer http . ResponseWriter ) {
writeResponse ( writer , "Not found!" )
}
|
LogRequest - middleware for loging requests
|
func ( server * HTTPServer ) LogRequest ( nextHandler http . Handler ) http . Handler {
return http . HandlerFunc (
func ( writer http . ResponseWriter , request * http . Request ) {
logRequestHandler ( writer , request , nextHandler )
} )
}
|
Initialize perform the server initialization
|
func ( server * HTTPServer ) Initialize ( address string ) http . Handler {
log . Println ( "Initializing HTTP server at" , address )
router := mux . NewRouter ( ) . StrictSlash ( false )
router . Use ( server . LogRequest )
|
HTML etc.
|
router . HandleFunc ( "/" , staticPage ( "html/index.html" ) ) . Methods ( http . MethodGet )
router . HandleFunc ( "/bootstrap.min.css" , staticPage ( "html/bootstrap.min.css" ) )
router . HandleFunc ( "/bootstrap.min.js" , staticPage ( "html/bootstrap.min.js" ) )
router . HandleFunc ( "/ccx.css" , staticPage ( "html/ccx.css" ) )
|
common REST API endpoints
|
return router
}
|
Start starts server
|
func ( server * HTTPServer ) Start ( ) error {
address := server . Config . Address
log . Println ( "Starting HTTP server at" , address )
router := server . Initialize ( address )
server . Serv = & http . Server {
Addr : address ,
Handler : router ,
ReadTimeout : 10 * time . Second ,
ReadHeaderTimeout : 5 * time . Second ,
WriteTimeout : 30 * time . Second ,
}
err := server . Serv . ListenAndServe ( )
if err != nil && err != http . ErrServerClosed {
log . Printf ( "Unable to start HTTP server %v" , err )
return err
}
return nil
}
|
Stop stops server's execution
|
func ( server * HTTPServer ) Stop ( ctx context . Context ) error {
return server . Serv . Shutdown ( ctx )
}
|