diff --git a/cmd/main.go b/cmd/main.go index c3a6ac5..46dbd11 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -2,8 +2,11 @@ package main import ( "errors" + "fmt" "log" "net/http" + "os" + "strings" "time" "github.com/bnkamalesh/webgo/v5" @@ -11,6 +14,10 @@ import ( "github.com/bnkamalesh/webgo/v5/middleware/cors" ) +var ( + lastModified = time.Now().Format(http.TimeFormat) +) + func helloWorld(w http.ResponseWriter, r *http.Request) { // WebGo context wctx := webgo.Context(r) @@ -70,6 +77,16 @@ func errLogger(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { } } +// StaticFiles is used to serve static files +func StaticFiles(rw http.ResponseWriter, r *http.Request) { + wctx := webgo.Context(r) + // '..' is replaced to prevent directory traversal which could go out of static directory + path := strings.ReplaceAll(wctx.Params()["w"], "..", "-") + + rw.Header().Set("Last-Modified", lastModified) + http.ServeFile(rw, r, fmt.Sprintf("./cmd/static/%s", path)) +} + func getRoutes() []*webgo.Route { return []*webgo.Route{ { @@ -115,13 +132,24 @@ func getRoutes() []*webgo.Route { Handlers: []http.HandlerFunc{originalResponseWriter}, TrailingSlash: true, }, + { + Name: "static", + Method: http.MethodGet, + Pattern: "/static/:w*", + Handlers: []http.HandlerFunc{StaticFiles}, + TrailingSlash: true, + }, } } func main() { + port := strings.TrimSpace(os.Getenv("HTTP_PORT")) + if port == "" { + port = "8080" + } cfg := &webgo.Config{ Host: "", - Port: "8080", + Port: port, ReadTimeout: 15 * time.Second, WriteTimeout: 60 * time.Second, } diff --git a/cmd/static/images/bird.jpg b/cmd/static/images/bird.jpg new file mode 100644 index 0000000..ba97816 Binary files /dev/null and b/cmd/static/images/bird.jpg differ diff --git a/router.go b/router.go index d9a7caa..a5c30ab 100644 --- a/router.go +++ b/router.go @@ -58,7 +58,7 @@ type customResponseWriter struct { // WriteHeader is the interface implementation to get HTTP response code and add // it to the custom response writer func (crw *customResponseWriter) WriteHeader(code int) { - if crw.written || crw.headerWritten { + if crw.headerWritten { return } @@ -70,13 +70,7 @@ func (crw *customResponseWriter) WriteHeader(code int) { // Write is the interface implementation to respond to the HTTP request, // but check if a response was already sent. func (crw *customResponseWriter) Write(body []byte) (int, error) { - if crw.written { - LOGHANDLER.Warn(errMultiWrite) - return 0, nil - } - crw.WriteHeader(crw.statusCode) - crw.written = true return crw.ResponseWriter.Write(body) }