175

Go Web サーバーにヘッダーを設定しようとしています。gorilla/muxnet/httpパッケージを使用しています。

Access-Control-Allow-Origin: *クロスドメインAJAXを許可するように設定したいです。

これが私のGoコードです:

func saveHandler(w http.ResponseWriter, r *http.Request) {
// do some stuff with the request data
}

func main() {
    r := mux.NewRouter()
    r.HandleFunc("/save", saveHandler)
    http.Handle("/", r)
    http.ListenAndServe(":"+port, nil)
}

パッケージには、クライアントであるかのように http 要求ヘッダーを送信する方法を説明するドキュメントがあります。net/http応答ヘッダーの設定方法が正確にわかりません。

4

8 に答える 8

243

気にしないでください、私はそれを理解しました-私は(doh!)のSet()方法を使用しましたHeader()

私のハンドラーは次のようになります。

func saveHandler(w http.ResponseWriter, r *http.Request) {
    // allow cross domain AJAX requests
    w.Header().Set("Access-Control-Allow-Origin", "*")
}

たぶん、これはいつか私と同じようにカフェインを奪われた誰かを助けるでしょう:)

于 2012-10-10T23:46:18.393 に答える
98

OPTIONSプリフライトリクエストを処理できないため、上記の回答はすべて間違っています。解決策は、マルチプレクサルーターのインターフェースをオーバーライドすることです。AngularJS の $http get リクエストがカスタム ヘッダーで失敗した (CORS で許可されている)を参照してください。

func main() {
    r := mux.NewRouter()
    r.HandleFunc("/save", saveHandler)
    http.Handle("/", &MyServer{r})
    http.ListenAndServe(":8080", nil);

}

type MyServer struct {
    r *mux.Router
}

func (s *MyServer) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
    if origin := req.Header.Get("Origin"); origin != "" {
        rw.Header().Set("Access-Control-Allow-Origin", origin)
        rw.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
        rw.Header().Set("Access-Control-Allow-Headers",
            "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
    }
    // Stop here if its Preflighted OPTIONS request
    if req.Method == "OPTIONS" {
        return
    }
    // Lets Gorilla work
    s.r.ServeHTTP(rw, req)
}
于 2014-07-18T06:37:52.177 に答える
24

完全にパブリックな振る舞いが本当に必要になるまでは、Origin に「*」を使用しないでください。ウィキペディアが言うよう
に:

「「*」の値は、要求が資格情報を提供することを許可しないという点で特別です。つまり、HTTP 認証、クライアント側の SSL 証明書、および Cookie の送信を許可しません。」

つまり、特に Chrome で簡単な認証を実装しようとすると、多くのエラーが発生します。

修正されたラッパーは次のとおりです。

// Code has not been tested.
func addDefaultHeaders(fn http.HandlerFunc) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        if origin := r.Header.Get("Origin"); origin != "" {
            w.Header().Set("Access-Control-Allow-Origin", origin)
        }
        w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
        w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token")
        w.Header().Set("Access-Control-Allow-Credentials", "true")
        fn(w, r)
    }
}

そして、これらすべてのヘッダーをプリフライト OPTIONS リクエストに返信することを忘れないでください。

于 2013-12-20T09:43:27.657 に答える
17

ルーターをオーバーライドしたくない場合(これをサポートするようにアプリを構成していない場合、またはルートごとに CORS を構成したい場合)、OPTIONS ハンドラーを追加して、フライト前の要求を処理します。 .

つまり、Gorilla Mux を使用すると、ルートは次のようになります。

accounts := router.Path("/accounts").Subrouter()
accounts.Methods("POST").Handler(AccountsCreate)
accounts.Methods("OPTIONS").Handler(AccountsCreatePreFlight)

上記の POST ハンドラに加えて、特定の OPTIONS メソッド ハンドラを定義していることに注意してください。

OPTIONS プリフライト メソッドを実際に処理するには、 AccountsCreatePreFlight を次のように定義します。

// Check the origin is valid.
origin := r.Header.Get("Origin")
validOrigin, err := validateOrigin(origin)
if err != nil {
    return err
}

// If it is, allow CORS.
if validOrigin {
    w.Header().Set("Access-Control-Allow-Origin", origin)
    w.Header().Set("Access-Control-Allow-Methods", "POST")
    w.Header().Set("Access-Control-Allow-Headers",
        "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
}

(実際に CORS がどのように機能するかを理解することに加えて) これをすべてクリックさせたのは、プリフライト リクエストの HTTP メソッドが実際のリクエストの HTTP メソッドと異なることです。CORS を開始するために、ブラウザは HTTP Method OPTIONS を使用してプリフライト リクエストを送信します。これは、ルーターで明示的に処理する必要があります。次に、アプリケーションから適切な応答 (または「*」) を受信すると"Access-Control-Allow-Origin": origin、実際のリクエスト。

また、標準タイプのリクエスト (つまり GET) に対してのみ "*" を実行できると思いますが、他のリクエストについては、上記のようにオリジンを明示的に設定する必要があります。

于 2015-02-26T23:26:47.957 に答える
14

適切な golang ミドルウェアを設定して、任意のエンドポイントで再利用できるようにします。

ヘルパーの種類と機能

type Adapter func(http.Handler) http.Handler
// Adapt h with all specified adapters.
func Adapt(h http.Handler, adapters ...Adapter) http.Handler {
    for _, adapter := range adapters {
        h = adapter(h)
    }
    return h
}

実際のミドルウェア

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

            if origin := r.Header.Get("Origin"); origin != "" {
                w.Header().Set("Access-Control-Allow-Origin", origin)
                w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
                w.Header().Set("Access-Control-Allow-Headers",
                    "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
            }
            // Stop here if its Preflighted OPTIONS request
            if r.Method == "OPTIONS" {
                return
            }
            h.ServeHTTP(w, r)
        })
    }
}

終点

覚えておいてください!ミドルウェアは逆の順序で適用されます (ExpectGET() が最初に起動されます)

mux.Handle("/watcher/{action}/{device}",Adapt(api.SerialHandler(mux),
    api.EnableCORS(),
    api.ExpectGET(),
))
于 2016-05-10T12:25:16.450 に答える
12

この場合のラッパーを作成します。

func addDefaultHeaders(fn http.HandlerFunc) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Access-Control-Allow-Origin", "*")
        fn(w, r)
    }
}
于 2013-05-08T18:06:25.573 に答える
1

上記と同じ問題がありました。上記の解決策は正しいです。セットアップは次のとおりです。1)クライアント用のAngularjs 2)GOサーバー用のBeegoフレームワーク

これらの点に従ってください 1) CORS 設定は GO サーバーでのみ有効にする必要があります 2) これを除いて、angularJS にいかなるタイプのヘッダーも追加しないでください

.config(['$httpProvider', function($httpProvider) {
        $httpProvider.defaults.useXDomain = true;
        delete $httpProvider.defaults.headers.common['X-Requested-With'];
    }])

GOサーバーで、リクエストの処理が開始される前にCORS設定を追加して、プリフライトリクエストが200 OKを受け取り、その後OPTIONSメソッドがGET、POST、PUTまたはリクエストタイプに変換されるようにします。

于 2016-05-02T08:42:31.203 に答える
-7

これが答えの別のひねりであることは知っていますが、これはWebサーバーにとってより懸念事項ではありませんか? たとえば、nginxが役立ちます。

ngx_http_headers_moduleモジュールにより、「Expires」および「Cache-Control」ヘッダー フィールド、および任意のフィールドを応答ヘッダーに追加できます。

...

location ~ ^<REGXP MATCHING CORS ROUTES> {
    add_header Access-Control-Allow-Methods POST
    ...
}
...

本番環境では、go サービスの前にnginxを追加するのが賢明です。リクエストの承認、ロギング、および変更のためのより多くの機能を提供します。また、サービスにアクセスできるユーザーを制御する機能を提供するだけでなく、上記で示したように、アプリ内の特定の場所に対して異なる動作を指定できます。

Go API で Web サーバーを使用する理由については引き続き説明できますが、それについては別の議論のトピックだと思います。

于 2015-10-04T12:59:03.593 に答える