Go楽しいですね。昨日のJSおじさんも楽しかったw
Go言語でJSONを返すシンプルなAPIサーバーを作るメモとか書きましたが、Go-Json-Restを使ってAPIサーバーを作っています。
APIサーバー立てるとき最近は気をつけたいCORS
こういうメッセージがajax通信したときのエラーでよく見るようになりました。
XMLHttpRequest cannot load http://localhost:8080/countries?ie=1435165847. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://n0bisuke-centos.local' is therefore not allowed access. The response had HTTP status code 403.
これってそんなに前からあったわけじゃないですけど、最近だと大抵のブラウザがクロスオリジンへのアクセスを拒否しちゃうやつです。サーバー側でヘッダー情報に設定してあげてないといけません。
オリジンは http://localhost:3000 とかの場合
**http://
がプロトコル、 localhost
がドメイン、 :3000
**がポート番号みたいな分け方になりますが、これら全てを含めたものをオリジン(Origin)と呼ぶみたいです。
Go-Json-Restでやってみる。
このライブラリはかなり多機能で、今の所、詰まっても大体解決してくれてます。
ここに情報がありました。
サンプルコードです。
package main
import (
"github.com/ant0ine/go-json-rest/rest"
"log"
"net/http"
)
func main() {
api := rest.NewApi()
api.Use(rest.DefaultDevStack...)
api.Use(&rest.CorsMiddleware{
RejectNonCorsRequests: false,
OriginValidator: func(origin string, request *rest.Request) bool {
return origin == "http://my.other.host"
},
AllowedMethods: []string{"GET", "POST", "PUT"},
AllowedHeaders: []string{
"Accept", "Content-Type", "X-Custom-Header", "Origin"},
AccessControlAllowCredentials: true,
AccessControlMaxAge: 3600,
})
router, err := rest.MakeRouter(
rest.Get("/countries", GetAllCountries),
)
if err != nil {
log.Fatal(err)
}
api.SetApp(router)
log.Fatal(http.ListenAndServe(":8080", api.MakeHandler()))
}
type Country struct {
Code string
Name string
}
func GetAllCountries(w rest.ResponseWriter, r *rest.Request) {
w.WriteJson(
[]Country{
Country{
Code: "FR",
Name: "France",
},
Country{
Code: "US",
Name: "United States",
},
},
)
}
このコードの中で設定はこの部分が肝みたいですね。
/*省略*/
api.Use(&rest.CorsMiddleware{
RejectNonCorsRequests: false,
OriginValidator: func(origin string, request *rest.Request) bool {
return origin == "http://my.other.host"
},
AllowedMethods: []string{"GET", "POST", "PUT"},
AllowedHeaders: []string{
"Accept", "Content-Type", "X-Custom-Header", "Origin"},
AccessControlAllowCredentials: true,
AccessControlMaxAge: 3600,
})
/*省略*/
全て許可の場合
OriginValidator
ここの関数の返り値をtrue
にすれば全て許可出来ると思います。
/*省略*/
api.Use(&rest.CorsMiddleware{
OriginValidator: func(origin string, request *rest.Request) bool {
return true
},
})
/*省略*/
PHPだったらこんな感じに書くやつです。
header("Access-Control-Allow-Origin: *");
例えば、http://localhost:3000
とかgulpとかでフロント開発してるエンジニアがいる場合
OriginValidator
ここに許可するOriginを指定します。
/*省略*/
api.Use(&rest.CorsMiddleware{
OriginValidator: func(origin string, request *rest.Request) bool {
return origin == "http://localhost:3000"
},
})
/*省略*/
Basic認証付き
Basic認証機能をつける
簡単です。
こんな感じで記述します。
/*省略*/
api.Use(&rest.AuthBasicMiddleware{
Realm: "message!!!!",
Authenticator: func(userId string, password string) bool {
if userId == "userid" && password == "password" {
return true
}
return false
},
})
/*省略*/
Basic認証機能付きサーバーのCORSの設定
ちなみに、Chromeで試してます。
AllowedMethods
設定しないといけないみたい。API開発でPUT
やDELETE
って使ったことほぼ無いですし、使わない場合はGET
とPOST
だけでいいと思います。
AllowedHeaders
Accept
とAuthorization
をつけましょう。詳細は...(調べておこう...)
api.Use(&rest.CorsMiddleware{
OriginValidator: func(origin string, request *rest.Request) bool {
return origin == "http://localhost"
},
AllowedMethods: []string{"GET", "POST"},
AllowedHeaders: []string{"Accept","Authorization"},
})
###おまけ: $.ajax()からBasic認証付きアクセス
※jquery1.11です。
$(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);
});
});
こんな感じでデータ取得できます!
go-json-restのCORSなドキュメントはこちらです。
##まとめ
CORS意識していこう。
Go楽しい。
参考: GolangでXMLHttpRequestLevel2+CORSのプリフライトが通るサーバーを立てる(BasicAuth付き)