Posted at

Go言語(Go-Json-Rest)のCORSでのハマり。Safariだけでハマった話。

More than 3 years have passed since last update.

go-json-restを使ってAPIサーバーを立ててCORS対応する話を前に書いたのですが、Safariだけ挙動でハマった話です。


参考: Go言語(Go-Json-Rest)でAPIサーバーを立てるときのCORS設定 (Basic認証機能付きも)



ハマり内容

前のコードと同じ内容です。

ChromeやFirefoxの場合はこれで問題無く動作していました。


  • Go側


app.go


/*省略*/
api.Use(&rest.CorsMiddleware{
RejectNonCorsRequests: false,
OriginValidator: func(origin string, request *rest.Request) bool {
return origin == "http://localhost:3000" || origin == "http://192.168.43.158:3000" || origin == "http://localhost"
},
AllowedMethods: []string{"GET", "POST", "OPTIONS"},
AllowedHeaders: []string{"Accept","Authorization","content-type"},
AccessControlAllowCredentials: true,
AccessControlMaxAge: 3600,
})

/*省略*/



  • フロント側


api.js


$(function(){
var host = 'localhost:8080';
var rand_param = '?ie=' + parseInt((new Date())/1000, 10);
var endpoint = '/countries';
var url = 'http://'+host+endpoint+rand_param;

function make_base_auth(user, password) {
var tok = user + ':' + password;
var hash = btoa(tok);
return "Basic " + hash;
}

$.ajax({
url: url,
beforeSend: function (xhr){
xhr.setRequestHeader('Authorization', make_base_auth('userud', 'password'));
},
}).done(function(data){
console.log(data);
}).fail(function(data){
console.log(data);
});

});


ここまでは前回と同様のソースコードです。


chromeやfirefoxだと普通です。


safariだけでエラーが発生。(しかもPOSTのみ)


※ safariのバージョンは8.0.7(OSはYosemite)です。


iPhoneで確認して、最初はiPhoneだけの問題かと思いきや、Safari特有の問題みたいです。

※ GETメソッドは問題無く動作してました。


解決: Access-Control-Allow-Headersにoriginを追加しましょう。

色々試行錯誤した結果解決しました。

Access-Control-Allow-Headersにoriginを追加することで解決しました。逆に言えば、Safari以外はこの指定が無くても動いてくれるんですね。

go-json-restの実装の場合はAllowedHeadersoriginを追加します。これでsafariでも大丈夫です。


app.go


/*省略*/
AllowedHeaders: []string{"origin", "Accept","Authorization","content-type"},
/*省略*/

これだけで半日くらいハマった...

Safariだけで発生した問題だったのでブラウザごとのxhr実装とかの関係かと思ってフロント側調査ばかりしてました。

こちらの記事(GolangでXMLHttpRequestLevel2+CORSのプリフライトが通るサーバーを立てる(BasicAuth付き))をもとにサーバーを構築しなおしてみたら同じJSコードで通ったのでGo側の実装に問題がありそうだという糸口です。


まとめ

GETメソッドは問題無く動作していたのでややこしかったです。

Access-Control-Allow-Headersはしっかり設定しましょう。

勉強になりました。→ 異なるドメインのURLからデータを参照する方法 - Cross-Origin Resource Sharing