web-dev-qa-db-ja.com

GolangでCORSを有効にする

こんにちは、残りのAPIを実装しています。そのために、オリジン間のクロスリクエストを処理できるようにします。

私が現在していること:

AWSのGoサーバーコード:

func (c *UserController) Login(w http.ResponseWriter, r *http.Request, ctx *rack.Context) {
w.Header().Set("Access-Control-Allow-Origin", r.Header.Get("Origin"))
w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
...
...
c.render.Json(w,rsp, http.StatusOK)
return
}

ローカルホストのAjaxコード:

<script>
$( document ).ready(function() {
    console.log( "ready!" );
    $.ajax({
        url: 'http://ip:8080/login',
        crossDomain: true, //set as a cross domain requests
        withCredentials:false,
        type: 'post',
        success: function (data) {
            alert("Data " + data);
        },
    });
});

ブラウザコンソールで次のエラーが表示されます:XMLHttpRequestをロードできません http:// ip:8080/login 。要求されたリソースに「Access-Control-Allow-Origin」ヘッダーがありません。したがって、Origin ' http:// localhost:8081 'はアクセスを許可されません。応答のHTTPステータスコードは422でした。

プリフライトオプションを追加してみました。

func corsRoute(app *app.App) {
allowedHeaders := "Accept, Content-Type, Content-Length, Accept-Encoding, Authorization,X-CSRF-Token"

f := func(w http.ResponseWriter, r *http.Request) {
    if Origin := r.Header.Get("Origin"); Origin != "" {
        w.Header().Set("Access-Control-Allow-Origin", "*")
        w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
        w.Header().Set("Access-Control-Allow-Headers", allowedHeaders)
        w.Header().Set("Access-Control-Expose-Headers", "Authorization")
    }
    return
}
app.Router.Options("/*p", f, publicRouteConstraint)
}

しかし、それは機能していません。

それを修正するために何ができるか。

7
Yash Srivastava

gorilla/muxパッケージを使用してGo RESTful APIサーバーを構築し、クライアントがJavaScriptリクエストを使用すると機能します。

My Go Serverはlocalhost:9091で実行され、サーバーコードは次のとおりです。

router := mux.NewRouter()
//api route is /people, 
//Methods("GET", "OPTIONS") means it support GET, OPTIONS
router.HandleFunc("/people", GetPeopleAPI).Methods("GET", "OPTIONS")
log.Fatal(http.ListenAndServe(":9091", router))

ここでOPTIONSを指定することが重要です。そうしないとエラーが発生します。

オプション http:// localhost:9091/people 405(許可されていないメソッド)

ロードに失敗しました http:// localhost:9091/people :プリフライトリクエストへの応答がアクセスコントロールチェックに合格しません:要求されたリソースに「Access-Control-Allow-Origin」ヘッダーがありません。 Origin ' http:// localhost:9092 'はアクセスを許可されていません。応答のHTTPステータスコードは405です。

OPTIONSを許可した後、うまく機能します。 この記事 からアイデアを得ました。

また、 MDN CORS doc 言及:

さらに、サーバーのデータに副作用を引き起こす可能性のあるHTTP要求メソッドの場合、仕様では、ブラウザー "preflight"が要求をサポートし、サポートされているメソッドをHTTP[〜#〜] options [〜#〜]リクエストメソッドを備えたサーバー、そしてサーバーからの「承認」時に、実際の実際のHTTP要求メソッドを使用した要求。

以下はapiGetPeopleAPIメソッドです。メソッドにコメントを付けます//ここでCORSを許可*または特定Origin、CORSの概念を説明する別の同様の答えがあります ここ

func GetPeopleAPI(w http.ResponseWriter, r *http.Request) {

    //Allow CORS here By * or specific Origin
    w.Header().Set("Access-Control-Allow-Origin", "*")

    w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
    // return "OKOK"
    json.NewEncoder(w).Encode("OKOK")
}

クライアントでは、localhost:9092でjavascriptを使用してhtmlを使用し、javascriptはlocalhost:9092からサーバーにリクエストを送信します

function GetPeople() {
    try {
        var xhttp = new XMLHttpRequest();
        xhttp.open("GET", "http://localhost:9091/people", false);
        xhttp.setRequestHeader("Content-type", "text/html");
        xhttp.send();
        var response = JSON.parse(xhttp.response);
        alert(xhttp.response);
    } catch (error) {
        alert(error.message);
    }
}

リクエストはレスポンス"OKOK"を正常に取得できます。

Fiddlerなどのツールを使用して、応答/要求ヘッダー情報を確認することもできます。

14
yu yang Jian

これを確認できます https://github.com/rs/cors

これはOptionsリクエストも処理します

7

手がかりをありがとう-それはすべてヘッダーにあります!サーバー側ではこれらのgolangヘッダーのみを使用します。

w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.Header().Set("Access-Control-Allow-Origin", "*")

このJQueryで動作するようになりました:

<script 
src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js">
</script>
<script>
$.ajax({
    type: 'GET',
    url: 'https://www.XXXXXXX.org/QueryUserID?u=juXXXXny&p=blXXXXXne',
    crossDomain: true,
    dataType: 'text',
    success: function(responseData, textStatus, jqXHR) {
        alert(responseData);
            },
    error: function (responseData, textStatus, errorThrown) {
        alert('POST failed.');
    }
});
</script>
7
user2099484

GOサーバー設定:

package main

import (
  "net/http"
)


  func Cors(w http.ResponseWriter, r *http.Request) {
  w.Header().Set("Content-Type", "text/html; charset=ascii")
  w.Header().Set("Access-Control-Allow-Origin", "*")
  w.Header().Set("Access-Control-Allow-Headers","Content-Type,access-control-allow-Origin, access-control-allow-headers")
          w.Write([]byte("Hello, World!"))
  }

  func main() {
  mux := http.NewServeMux()
  mux.HandleFunc("/plm/cors",Cors)
  http.ListenAndServe(":8081", mux)
}

クライアントJQUERY AJAX SETTING:

<head>
       <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js">
       </script>
</head>
<body>

              <br> Please confirm to proceed : <button class="myConfirmButton1">Go!!</button>

             <div id="loader1" style="display:none;">loading...</div>
             <div id="loader2" style="display:none;">...done</div>
             <div id="myFeedback1"></div>

          <script>
          $(document).ready(function(){
            $(".myConfirmButton1").click(function(){
              $('#loader1').show();
              $.ajax({
                url:"http://[webserver.domain.com:8081]/plm/cors",
                dataType:'html',
                headers: {"Access-Control-Allow-Origin": "*", "Access-Control-Allow-Headers": "access-control-allow-Origin, access-control-allow-headers"},
                type:'get',
                contentType: 'application/x-www-form-urlencoded',
                success: function( data, textStatus, jQxhr ){
                $('#loader1').hide();
                $('#loader2').show();
                $('#myFeedback1').html( data );
                        },
                error: function( jqXhr, textStatus, errorThrown ){
                $('#loader1').hide();
                $('#myFeedback1').html( errorThrown );
                alert("error" + errorThrown);
                        }
                });
           });
          });
          </script>
</body>

Curlおよび取得した応答を使用したクライアントテスト要求:

curl -iXGET http:// [webserver.domain.com:8081]/plm/cors

HTTP/1.1 200 OK
Access-Control-Allow-Headers: Content-Type,access-control-allow-Origin, access-control-allow-headers
Access-Control-Allow-Origin: *
Content-Type: text/html; charset=ascii
Date: Wed, 17 Jan 2018 13:28:28 GMT
Content-Length: 13

Hello, World!
3

[〜#〜] cors [〜#〜] を許可するには、サーバーはすべてをキャッチする必要があります Preflight request ブラウザは、OPTIONSメソッドを使用した実際のクエリの前に同じパスに送信します。

最初の方法は、次のような方法でこれを手動で管理することです。

func setupCORS(w *http.ResponseWriter, req *http.Request) {
    (*w).Header().Set("Access-Control-Allow-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")
}

func indexHandler(w http.ResponseWriter, req *http.Request) {
    setupCORS(&w, req)
    if (*req).Method == "OPTIONS" {
        return
    }

    // process the request...
}

2番目の方法は、 https://github.com/rs/cors

package main

import (
    "net/http"

    "github.com/rs/cors"
)

func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Content-Type", "application/json")
        w.Write([]byte("{\"hello\": \"world\"}"))
    })

    // cors.Default() setup the middleware with default options being
    // all origins accepted with simple methods (GET, POST). See
    // documentation below for more options.
    handler := cors.Default().Handler(mux)
    http.ListenAndServe(":8080", handler)
}
0
Maxim

すべての優れた答えに追加:すべてのハンドラーでヘッダーを設定する代わりに、おそらく appHandler パターンを使用する必要があります。

type Handler func(http.ResponseWriter, *http.Request) *Error

func (fn Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Access-Control-Allow-Origin", "*")
    w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
    if e := fn(w, r); e != nil { // e is *appError, not os.Error.
        http.Error(w, e.Message, e.Code)
    }
}

func Login(w http.ResponseWriter, r *http.Request) *Error {
   ...
   return nil
}

r.Handle("/login", Handler(Login))
0
ET-CS