■前置き
何かしらのユーザアクティビティを収集するWebページをjavascriptで書いていて、セキュリティの関係でクライアントのローカルストレージに一切アクセスできないということに気づいたとき
Webサーバ側にクライアントの情報を送信するしかないってことに同時に気付くことになるわけですよね
つい先日Windows 環境で IIS を使ってお手軽にローカルネットワークで Webサーバを構築したわけですけど、実はこの Web サーバ側も javascript で動くわけですから、もちろんローカルストレージに一切アクセスできません。
はぁ( ゚Д゚)?って思いながら解決策を調べると
ポート番号80でWebサーバを起動している傍らで、別ポート番号でWebAPIサーバを起動して、クライアントからのアクセスにより特別な処理を行うそうです。
POSTメッセージを送信する場合は、この別ポートを指定して送ります。
その別ポート番号で HTTP を処理するサーバを node とか go で書くという話で、記述が見つかります。
今回は go で HTTP メッセージをさばく WebAPIサーバとやらをゼロから組んで疎通確認まで行ってみます。
■思想
ポート番号を指定して http サーバスタート!
クエリストリングを見て、実行する関数をスイッチ
という非常に簡素なロジックから説明して、書式を示す優れたエンジニアの記事を探してみたところ…
qiita.com
あった!
以下の go をデバッグ実行すると、ちゃんと localhost:62874 にアクセスしたときに handler 関数にてブレークポイントを張っているとブレークします。
package main import ( "fmt" "net/http" ) func handler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello, World") } func main() { http.HandleFunc("/", handler) http.ListenAndServe(":62874", nil) }
すごいと思ったのが、次のように apiname1って書いたら、localhost:62874/apiname1にアクセスしたときにだけ反応しました。
http.HandleFunc("/apiname1", handler)
次に、単純に post するクライアントコードを作ってみてWebAPIサーバが反応するか見てみましょう。
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> <script language="javascript" type="text/javascript"> function Post() { var xhr = new XMLHttpRequest(); var rootURL = window.location.href.split('/').slice(0, 3).join('/'); var url = rootURL + ":62874/apiname1"; // WebAPI Server port and API name var params = "hoge=fuga&test=hello"; xhr.open("POST", url, true); xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); xhr.onreadystatechange = function () { if (xhr.readyState == 4) { target = document.getElementById("output"); target.innerHTML = "complete status = " + xhr.status; } } xhr.send(params); } </script> </head> <body> <input type="button" value="Post" onclick="Post();" /> <div id="output"></div> </body> </html>
さらにサーバーコードを次のように書き換えます。
package main import ( "fmt" "net/http" ) func apiname1(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { fmt.Fprintf(w, "this is apiname1") return } w.Header().Set("Content-Type", "text/plain") r.ParseForm() form := r.PostForm fmt.Printf("form = %v\n", form) params := r.Form fmt.Printf("params = %v\n", params) } func main() { http.HandleFunc("/apiname1", apiname1) http.ListenAndServe(":62874", nil) }
クライアントから go のサーバへparams情報が渡ることを確認しました。
疎通確認はとれたことになる