123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 |
- // Example static file server.
- //
- // Serves static files from the given directory.
- // Exports various stats at /stats .
- package main
- import (
- "expvar"
- "flag"
- "log"
- "github.com/valyala/fasthttp"
- "github.com/valyala/fasthttp/expvarhandler"
- )
- var (
- addr = flag.String("addr", "localhost:8080", "TCP address to listen to")
- addrTLS = flag.String("addrTLS", "", "TCP address to listen to TLS (aka SSL or HTTPS) requests. Leave empty for disabling TLS")
- byteRange = flag.Bool("byteRange", false, "Enables byte range requests if set to true")
- certFile = flag.String("certFile", "./ssl-cert.pem", "Path to TLS certificate file")
- compress = flag.Bool("compress", false, "Enables transparent response compression if set to true")
- dir = flag.String("dir", "/usr/share/nginx/html", "Directory to serve static files from")
- generateIndexPages = flag.Bool("generateIndexPages", true, "Whether to generate directory index pages")
- keyFile = flag.String("keyFile", "./ssl-cert.key", "Path to TLS key file")
- vhost = flag.Bool("vhost", false, "Enables virtual hosting by prepending the requested path with the requested hostname")
- )
- func main() {
- // Parse command-line flags.
- flag.Parse()
- // Setup FS handler
- fs := &fasthttp.FS{
- Root: *dir,
- IndexNames: []string{"index.html"},
- GenerateIndexPages: *generateIndexPages,
- Compress: *compress,
- AcceptByteRange: *byteRange,
- }
- if *vhost {
- fs.PathRewrite = fasthttp.NewVHostPathRewriter(0)
- }
- fsHandler := fs.NewRequestHandler()
- // Create RequestHandler serving server stats on /stats and files
- // on other requested paths.
- // /stats output may be filtered using regexps. For example:
- //
- // * /stats?r=fs will show only stats (expvars) containing 'fs'
- // in their names.
- requestHandler := func(ctx *fasthttp.RequestCtx) {
- switch string(ctx.Path()) {
- case "/stats":
- expvarhandler.ExpvarHandler(ctx)
- default:
- fsHandler(ctx)
- updateFSCounters(ctx)
- }
- }
- // Start HTTP server.
- if len(*addr) > 0 {
- log.Printf("Starting HTTP server on %q", *addr)
- go func() {
- if err := fasthttp.ListenAndServe(*addr, requestHandler); err != nil {
- log.Fatalf("error in ListenAndServe: %v", err)
- }
- }()
- }
- // Start HTTPS server.
- if len(*addrTLS) > 0 {
- log.Printf("Starting HTTPS server on %q", *addrTLS)
- go func() {
- if err := fasthttp.ListenAndServeTLS(*addrTLS, *certFile, *keyFile, requestHandler); err != nil {
- log.Fatalf("error in ListenAndServeTLS: %v", err)
- }
- }()
- }
- log.Printf("Serving files from directory %q", *dir)
- log.Printf("See stats at http://%s/stats", *addr)
- // Wait forever.
- select {}
- }
- func updateFSCounters(ctx *fasthttp.RequestCtx) {
- // Increment the number of fsHandler calls.
- fsCalls.Add(1)
- // Update other stats counters
- resp := &ctx.Response
- switch resp.StatusCode() {
- case fasthttp.StatusOK:
- fsOKResponses.Add(1)
- fsResponseBodyBytes.Add(int64(resp.Header.ContentLength()))
- case fasthttp.StatusNotModified:
- fsNotModifiedResponses.Add(1)
- case fasthttp.StatusNotFound:
- fsNotFoundResponses.Add(1)
- default:
- fsOtherResponses.Add(1)
- }
- }
- // Various counters - see https://pkg.go.dev/expvar for details.
- var (
- // Counter for total number of fs calls
- fsCalls = expvar.NewInt("fsCalls")
- // Counters for various response status codes
- fsOKResponses = expvar.NewInt("fsOKResponses")
- fsNotModifiedResponses = expvar.NewInt("fsNotModifiedResponses")
- fsNotFoundResponses = expvar.NewInt("fsNotFoundResponses")
- fsOtherResponses = expvar.NewInt("fsOtherResponses")
- // Total size in bytes for OK response bodies served.
- fsResponseBodyBytes = expvar.NewInt("fsResponseBodyBytes")
- )
|