go-json-restを使ってAPIサーバーを立ててCORS対応する話を前に書いたのですが、Safariだけ挙動でハマった話です。
##ハマり内容
前のコードと同じ内容です。
ChromeやFirefoxの場合はこれで問題無く動作していました。
- 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,
})
/*省略*/
- フロント側
$(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の実装の場合はAllowedHeaders
にorigin
を追加します。これでsafariでも大丈夫です。
/*省略*/
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