Posted at

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

More than 3 years have passed since last update.

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でやってみる。

このライブラリはかなり多機能で、今の所、詰まっても大体解決してくれてます。

ここに情報がありました。

サンプルコードです。


cors.go

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",
},
},
)
}


このコードの中で設定はこの部分が肝みたいですね。


cors.go

/*省略*/

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にすれば全て許可出来ると思います。


cors.go

/*省略*/

api.Use(&rest.CorsMiddleware{
OriginValidator: func(origin string, request *rest.Request) bool {
return true
},
})
/*省略*/

PHPだったらこんな感じに書くやつです。


cors.php

header("Access-Control-Allow-Origin: *");



例えば、http://localhost:3000とかgulpとかでフロント開発してるエンジニアがいる場合


  • OriginValidator

ここに許可するOriginを指定します。


cors.go

/*省略*/

api.Use(&rest.CorsMiddleware{
OriginValidator: func(origin string, request *rest.Request) bool {
return origin == "http://localhost:3000"
},
})

/*省略*/



Basic認証付き


Basic認証機能をつける

簡単です。

こんな感じで記述します。


cors.go

/*省略*/

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開発でPUTDELETEって使ったことほぼ無いですし、使わない場合はGETPOSTだけでいいと思います。


  • AllowedHeaders

AcceptAuthorizationをつけましょう。詳細は...(調べておこう...)


cors.go

    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です。


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);
});

});


こんな感じでデータ取得できます!

go-json-restのCORSなドキュメントはこちらです。


まとめ

CORS意識していこう。

Go楽しい。

参考: GolangでXMLHttpRequestLevel2+CORSのプリフライトが通るサーバーを立てる(BasicAuth付き)