web-dev-qa-db-ja.com

ゴラン。使用するものhttp.ServeFile(..)またはhttp.FileServer(..)?

私は少し混乱しています。多くの例では、http.ServeFile(..)http.FileServer(..)の両方の使用法を示していますが、非常に近い機能を持っているようです。また、カスタムNotFoundハンドラーの設定方法に関する情報も見つかりませんでした。

_// This works and strip "/static/" fragment from path
fs := http.FileServer(http.Dir("static"))
http.Handle("/static/", http.StripPrefix("/static/", fs))

// This works too, but "/static2/" fragment remains and need to be striped manually
http.HandleFunc("/static2/", func(w http.ResponseWriter, r *http.Request) {
    http.ServeFile(w, r, r.URL.Path[1:])
})

http.ListenAndServe(":8080", nil)
_

私はソースコードを読み込もうとしましたが、どちらもserveFile(ResponseWriter, *Request, FileSystem, string, bool)基になる関数を使用しています。ただし、_http.FileServer_は、独自のServeHTTP()メソッドでfileHandlerを返し、ファイル(path.Clean()など)を提供する前に準備作業を行います。

では、なぜこの分離が必要なのでしょうか?使用する方が良い方法は?また、要求されたファイルが見つからない場合など、カスタムのNotFoundハンドラーを設定するにはどうすればよいですか?

34

ここでは、ファイルが見つからない場合に「/」にリダイレクトを送信するハンドラー。これは、Angularアプリケーション、推奨される here のフォールバックを追加するときに便利です。これはgolangサービス内から提供されます。

注:このコードは生産準備ができていません。説明のみ(せいぜい:-)

    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)
            }
        }
    }

この例のように追加できます(gojiをmuxとして使用):

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

2
Oliver Koeth