1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

GCP Cloud Functions<GET/POST> の使い方【初心者】

Posted at

AWS Lambda + API Gateway <GET> の使い方【初心者】
AWS Lambda + API Gateway <POST> の使い方【初心者】
GCP Cloud Function版です。

Cloud Functions の作成

AWSの場合、API Gateway と Lambda で WEB API を作成しましたが
GCPの場合、トリガーに「HTTP」を選択することにより、Cloud Functions のみで対応が可能です。

ランタイムは、「Go 1.11」を選択しています。
ポイントは、packageに「main」を指定せずに、「main」関数も指定しません。

以下のソースを「インラインエディタ」で記述します。
実行する関数は、「HelloWorld」です。

function.go
package p

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"strconv"
)

type Calc struct {
	Value1 int `json:"Value1"`
	Value2 int `json:"Value2"`
}

type ReturnCalc struct {
	Calc     // 埋め込み(embedded) 継承的な意味合い
	Ans  int `json:"Ans"`
}

// メソッド定義
func (c Calc) Add() int {
	return c.Value1 + c.Value2
}
func (c *ReturnCalc) Add() {
	c.Ans = c.Value1 + c.Value2
}

func HelloWorld(w http.ResponseWriter, r *http.Request) {
	// クエリパラメータ取得してみる
	var err_flg = 0
	var data Calc

	if r.Method == http.MethodGet {
		for key, values := range r.URL.Query() {
			for _, v := range values {
				switch key {
				case "Value1":
					i, err := strconv.Atoi(v)
					if err != nil {
						fmt.Fprintln(w, "Value1が数値じゃない")
						err_flg = 1
						break
					}
					data.Value1 = i
				case "Value2":
					i, err := strconv.Atoi(v)
					if err != nil {
						fmt.Fprintln(w, "Value2が数値じゃない")
						err_flg = 1
						break
					}
					data.Value2 = i
				default:
					fmt.Fprintln(w, "パラメータエラー")
					err_flg = 1
					break
				}
			}
		}
		if err_flg == 0 {
			fmt.Fprintf(w, "%d + %d = %d \n", data.Value1, data.Value2, data.Add())
		} else {
			w.WriteHeader(http.StatusInternalServerError)
		}

	} else if r.Method == http.MethodPost {
		// CORS対策
		w.Header().Set("Access-Control-Allow-Origin", "*")
		w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
        
		// Bodyデータを扱う場合には、事前にパースを行う(POSTの場合、必ず実施する)
		r.ParseForm()

		if r.Header.Get("Content-Type") != "application/json" {
			w.WriteHeader(http.StatusInternalServerError)
			fmt.Fprintln(w, "json形式じゃない")
			return
		}

		//parse json
		var data Calc
		jsondata, err := ioutil.ReadAll(r.Body)
		// 構造体に格納しているが、 data をmap[string]int や map[string]interfase{}にしても格納可能
		err = json.Unmarshal(jsondata, &data)
		if err != nil {
			fmt.Fprintf(w, "json変換できない %v \n", err)
			w.WriteHeader(http.StatusInternalServerError)
			return
		}
		//返信用データ作成
		var rdata ReturnCalc
		rdata.Value1 = data.Value1
		rdata.Value2 = data.Value2
		rdata.Add()
		v, _ := json.Marshal(rdata)
		fmt.Fprint(w, string(v))

	} else if r.Method == http.MethodOptions {
		// CORS対策
		w.Header().Set("Access-Control-Allow-Origin", "*")
		w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
	}
}

GETの作成

r.Method == http.MethodGet内がGETの処理です。

以下のページを参考に、URLパラメータを取得します。
golangでURLをパース

POSTの作成

OPTIONSの指定とCORS対策

POSTの場合、AWS Lambda + API Gateway <POST> の使い方【初心者】にあったように
OPTIONSの指定とCORS対策が必要です。

POSTすると、r.Method == http.MethodOptionsが先に実行され
r.Method == http.MethodPostが実行されます。

CORS対策は、以下のヘッダー情報を付加することにより対応できます。

        w.Header().Set("Access-Control-Allow-Origin", "*")
        w.Header().Set("Access-Control-Allow-Headers", "Content-Type")

r.ParseForm()

POST処理の場合、ParseForm()でパース処理が必要らしいです。

jsonデータ読み取り・書き込み

ioutil.ReadAll(r.Body)で、リクエストボディを読み取ることが可能です。
Unmarshalで、jsonデータをGo言語の構造体などに格納することができます。
Marshalは、構造体などのデータをjsonデータに変換します。

メソッド

func (c *ReturnCalc) Add() {
    c.Ans = c.Value1 + c.Value2
}

上記のメソッドで加算した結果を Ansに格納していますが
以下のようにポインタレシーバを値レシーバのメソッドにした場合、正しい結果になりません。

func (c ReturnCalc) Add() {
    c.Ans = c.Value1 + c.Value2
}

ポインタレシーバと値レシーバの違いは、構造体の値の変更が、メソッド呼び出し後にも反映されるか否かです。
関数内で構造体の値を変更する場合には、ポインターメソッドで定義する必要があります。

以下が参考になりました。
[Go] 構造体で、値メソッドとポインタメソッドを使い分ける

テスト

Cloud Functions にもテストはありますが、POSTとして実行されるようです。

スクリーンショット 2019-09-26 0.26.03.png

参考

golangでURLをパース
[Go] 構造体で、値メソッドとポインタメソッドを使い分ける

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?