Golang. What to use? http.ServeFile(..) or http.FileServer(..)?

前端 未结 2 860
后悔当初
后悔当初 2020-12-01 00:34

I\'m a little bit confused. Much of examples shows usage of both: http.ServeFile(..) and http.FileServer(..), but seems they have very close functi

2条回答
  •  抹茶落季
    2020-12-01 01:30

    Here a handler which sends a redirect to "/" if file is not found. This comes in handy when adding a fallback for an Angular application, as suggested here, which is served from within a golang service.

    Note: This code is not production ready. Only illustrative (at best :-)

        package main
    
        import "net/http"
    
        type (
            // FallbackResponseWriter wraps an http.Requesthandler and surpresses
            // a 404 status code. In such case a given local file will be served.
            FallbackResponseWriter struct {
                WrappedResponseWriter http.ResponseWriter
                FileNotFound          bool
            }
        )
    
        // Header returns the header of the wrapped response writer
        func (frw *FallbackResponseWriter) Header() http.Header {
            return frw.WrappedResponseWriter.Header()
        }
    
        // Write sends bytes to wrapped response writer, in case of FileNotFound
        // It surpresses further writes (concealing the fact though)
        func (frw *FallbackResponseWriter) Write(b []byte) (int, error) {
            if frw.FileNotFound {
                return len(b), nil
            }
            return frw.WrappedResponseWriter.Write(b)
        }
    
        // WriteHeader sends statusCode to wrapped response writer
        func (frw *FallbackResponseWriter) WriteHeader(statusCode int) {
            Log.Printf("INFO: WriteHeader called with code %d\n", statusCode)
            if statusCode == http.StatusNotFound {
                Log.Printf("INFO: Setting FileNotFound flag\n")
                frw.FileNotFound = true
                return
            }
            frw.WrappedResponseWriter.WriteHeader(statusCode)
        }
    
        // AddFallbackHandler wraps the handler func in another handler func covering authentication
        func AddFallbackHandler(handler http.HandlerFunc, filename string) http.HandlerFunc {
            Log.Printf("INFO: Creating fallback handler")
            return func(w http.ResponseWriter, r *http.Request) {
                Log.Printf("INFO: Wrapping response writer in fallback response writer")
                frw := FallbackResponseWriter{
                    WrappedResponseWriter: w,
                    FileNotFound:          false,
                }
                handler(&frw, r)
                if frw.FileNotFound {
                    Log.Printf("INFO: Serving fallback")
                    http.Redirect(w, r, "/", http.StatusSeeOther)
                }
            }
        }
    

    It can be added as in this example (using goji as mux):

        mux.Handle(pat.Get("/*"),
            AddFallbackHandler(http.FileServer(http.Dir("./html")).ServeHTTP, "/"))
    
    

提交回复
热议问题