2

Hugo で生成された (半) 静的な Web サイトを提供するために Google App Engine を使用しています。すべてのHTMLファイルが保存され、提供されるディレクトリ「public」があります。たとえば、連絡先フォームを処理するためのサーバー側スクリプトもいくつかあります。ファイルはapp.yamlこんな感じ。

// app.yaml
runtime: go
api_version: go1

handlers:
- url: /.*
  script: _go_app
  secure: always

そして、簡略化されたmain.goファイルは次のようになります

// main.go
package main

import ( 
  "net/http"
  "encoding/json"

  "appengine"
  "appengine/urlfetch"   
)

func init() {

  fileHandler := http.FileServer(http.Dir("public"))
  http.Handle("/", fileHandler)

  http.HandleFunc("/contactus/", HandleContactus)
}

これは完全にうまく機能し、html ファイルを提供します。ただし、ページが見つからず、応答が404 Not Foundたとえば (またはその他のサーバーエラー) である場合を処理するソリューションを検討しています。

私の考えは、で渡すことができhttp.Handle("/", myCustomHandler)、サーバーの応答を処理し、必要に応じてカスタムなどにリダイレクトするカスタムハンドラーを作成することでした404.html。私は Go が初めてで、これをどのように実装する必要があるのか​​ わかりません。Gorilla Mux も調べましたが、(可能であれば) シンプルにするために外部ライブラリを使用しないことをお勧めします。

この投稿に基づいて、次のことを試しました

package main

import ( 
  "net/http"
  "encoding/json"

  "appengine"
  "appengine/urlfetch"   
)

func StaticSiteHandler(h http.Handler) http.Handler {
  return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request){

    h.ServeHTTP(w, r)
  })
}


func init() {

  fileHandler := http.FileServer(http.Dir("public"))
  http.Handle("/", StaticSiteHandler(fileHandler))

  http.HandleFunc("/contactus/", HandleContactus)
}

このソリューションは、HTML ページも提供するという意味では機能しますが、サーバーの応答コードを処理する方法がまだわかりません。

どんな助けでも大歓迎です。ありがとう!

4

2 に答える 2

3

ミドルウェアを から切り離したままにするために、http.FileServerラップする際に、次の特定の実装を渡すことができますhttp.ResponseWriter

  1. ヘッダーを捨てる必要がある場合に備えて、ヘッダーを蓄積します ( WriteHeader404 で呼び出された場合)
  2. WriteHeader404 で呼び出された 場合:
    1. 蓄積されたヘッダーを閉じる
    2. カスタム 404 を送信する
    3. Writeラップされたハンドラーからの呼び出しを無視する
  3. が呼び出されていない場合WriteHeader、または 404 以外で呼び出された場合:
    1. 蓄積されたヘッダーを実体に放出するResponseWriter
    2. WriteHeaderおよびコールWriteを実際のResponseWriter
    type notFoundInterceptorWriter struct {
    rw              http.ResponseWriter // set to nil to signal a 404 has been intercepted
    h               http.Header         // set to nil to signal headers have been emitted
    notFoundHandler http.Handler
    r               *http.Request
}

func (rw *notFoundInterceptorWriter) Header() http.Header {
    if rw.h == nil && rw.rw != nil {
        return rw.rw.Header()
    }
    return rw.h
}

func (rw *notFoundInterceptorWriter) WriteHeader(status int) {
    if status == http.StatusNotFound {
        rw.notFoundHandler.ServeHTTP(rw.rw, rw.r)
        rw.rw = nil
    } else {
        for k, vs := range rw.h {
            for _, v := range vs {
                rw.rw.Header().Add(k, v)
            }
        }
        rw.rw.WriteHeader(status)
    }
    rw.h = nil
}

func (rw *notFoundInterceptorWriter) Write(b []byte) (int, error) {
    if rw.rw != nil {
        return rw.rw.Write(b)
    }
    // ignore, so do as if everything was written OK
    return len(b), nil
}

func StaticSiteHandler(h, notFoundHandler http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        w = &notFoundInterceptorWriter{
            rw:              w,
            h:               make(http.Header),
            notFoundHandler: notFoundHandler,
            r:               r,
        }
        h.ServeHTTP(w, r)
    })
}
于 2016-09-20T16:36:34.830 に答える