AngularJSのhttp通信からのpostリクエストをgo側で取得


Goの勉強録

Goを本格的に勉強をし始めて割とモチベが保てているなと思います。PHPのWebソフトウェア開発と並行して勉強できているので生活にハリと艶が出てきているような気がします。(・∀・)

余談ですが、最近JSの他のフレームワークに魅了を感じますね、例えばVue.jsとかは綺麗なサイトができるのでAngularから浮気をしそうになります。(まだしていません。。)

しかし、Angular界隈を盛り上げていきたいためまだまだAngular頑張ります!

Go言語に関する過去記事は以下になります。


過去の記事


本題

さて、今回の本題のAngular側からhttp通信でPOSTリクエストをGo言語でそのデータをJSONで取得するというものをやっていきます。

これPHPなら一行でできるのですが。。

今回の実装のフローは

- テキストボックスとボタンのhtmlを作る

- AngularJSでテキストボックスの値を取得できるようにする。

- ボタンを押した際に実行されるリスナーを定義する。

- go 側でhttp通信で送られて来るデータと同じ形式の構造体を定義する。

- レスポンスのBodyをjson.NewDecoder(io Reader)でDecoderを作成する。

- 生成したdecoderからDecodeを行いgoで定義した構造体に格納

- その構造体を出力

フローはこんな感じですが 百聞は一見にしかず なのでコードを見ていきましょう。

ちなみに、ディレクトリの構造は以下のようになっています。


ディレクトリ

workspace/

├ HTML/
│ ├ index.html
│ ├ test.js

├ POST/
│ ├ post.go

├ Host.go


ソースコード

まずは、表示側のindex.html


index.html

<html ng-app="test">

<head>
<title>post test</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.5/angular.min.js"></script>
<script src="./test.js"></script>
</head>
<body ng-controller="test">
<input type="text" ng-model="val">
<input type="button" value="送信" ng-Click="test()">
</body>
</html>

通信を送る側のtest.js


test.js

var test = angular.module("test",[])

test.controller("test",function($scope,$http){
$scope.test = function(){
send = {
name: $scope.val
}
console.log(send);
$http({
method: 'POST',
url: '../Host.go',
contentType: 'application/JSON',
data: send
}).then(function DoneCallback(res){
console.log("通信成功");
console.log(res)
},function failCallback(res){
console.log("通信失敗");
});
}
})


Host.goはサーバを立てるスクリプトです。

リクエストはHost.goで受けていますが、処理はpost.goに投げています。


Host.go

package main

import (
"fmt"
"log"
"net/http"
"os"
"reflect"

"./POST"
)

func main() {
// リクエストがきた際の処理の定義
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
POST.Procreq(w, r)
})
dir, _ := os.Getwd()
fmt.Println(reflect.TypeOf(dir))
http.Handle("/posttest/", http.StripPrefix("/posttest/", http.FileServer(http.Dir(dir+"/HTML/"))))
log.Fatal(http.ListenAndServe(":8080", nil))
}


実際に来るリクエストのデータの取得はこのpost.goで行なっています。


post.go

package POST

import (
"encoding/json"
"fmt"
"net/http"
)

// リクエストのデータ構造と形式が同じ構造体を定義
type Test struct {
Name string
// for debug
// Val string
// Ope string
}

func Procreq(w http.ResponseWriter, r *http.Request) {
// パース
r.ParseForm()
// インスタンスの生成
var test = Test{}
// postのリクエストを処理する
//decoderの生成
decoder := json.NewDecoder(r.Body)
// testにリクエストデータを格納
err := decoder.Decode(&test)
if err != nil {
panic(err)
}
fmt.Println("method : " + r.Method)
fmt.Println("name : " + test.Name)
}


ソースコードはこんな感じです。


bash

go run Host.go


を叩くと、http://localhost:8080/posttest/にindex.htmlが出力されていてテキストボックスにtestを入力してボタンを押すとコンソール側は次のようなログを表示します

string

method : POST
name : test

このようにデータをJSON形式で受け取ることができているので、あとはこのデータを煮るなり焼くなりすればいいと思います。


まとめ

データを取得するのに手こずってしまいました。

teratailでも質問しましたが、試行錯誤で自己解決できました。(回答を送っていただいた方々ありがとうございました。)

phpと違う点は受け取り側がデータの構造体を定義しないといけないということで、初学者ながらgo言語のコンセプトである一貫性を持たせることなのかなと思いました。


参考

https://www.pebblewind.com/entry/2017/03/03/181956

https://teratail.com/questions/177365#reply-264307