演習問題
基本問題は解答を置いてありますが、できるだけ自力で頑張ってみてください。
最後に全問題をまとめて動作確認できるシェルスクリプトが置いてあるので、作ったエンドポイントは消さないで残しておくと良いです。
基本問題 GET /ping
pong と返すエンドポイントを作成してください。
スキーマ
リクエスト
/ping
レスポンス
content-type: text/plain
status code: 200
pong
完成したら、以下のコマンドをターミナルで実行して上手く機能しているか確認しましょう。
$ curl -X GET "http://localhost:8080/ping" # pong
解答
package main
import (
"net/http"
"github.com/labstack/echo/v4"
)
func main() {
e := echo.New()
// 「/ping」というエンドポイントを設定する
e.GET("/ping", func(c echo.Context) error {
// HTTPステータスコードは 200 Ok で、文字列「pong」をクライアントに返す
return c.String(http.StatusOK, "pong\n")
})
e.Logger.Fatal(e.Start(":8080"))
}
基本問題 GET /fizzbuzz
クエリパラメータcount
で渡された数までの FizzBuzz を返してください。count
がない場合は 30 として扱い、count
が整数として解釈できない場合はステータスコード400
を返してください。
スキーマ
リクエスト
/fizzbuzz?count=10
レスポンス
content-type: text/plain
status code: 200
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
適切でないリクエストの場合
content-type: text/plain
status code: 400
Bad Request
完成したら、以下のコマンドをターミナルで実行して上手く機能しているか確認しましょう。
$ curl -X GET "http://localhost:8080/fizzbuzz?count=20"
$ curl -X GET "http://localhost:8080/fizzbuzz" # count=30 と同じ
$ curl -X GET "http://localhost:8080/fizzbuzz?count=a" # Bad Request
/fizzbuzzが上手く動いたら、講習会の実況用チャンネルに↑の実行結果を投稿しましょう!
解答
package main
import (
"fmt"
"net/http"
"strconv"
"github.com/labstack/echo/v4"
)
func main() {
e := echo.New()
// 「/fizzbuzz」というエンドポイントを設定する
e.GET("/fizzbuzz", fizzBuzzHandler)
e.Logger.Fatal(e.Start(":8080"))
}
func fizzBuzzHandler(c echo.Context) error {
// クエリパラメーター "count" の値をcountStrに格納
countStr := c.QueryParam("count")
// もしcountStrが空っぽ("")だったら、
if countStr == "" {
// countStrを30に設定
countStr = "30"
}
// strconv.Atoi()でstringをintに変換する(分からなかったらググりましょう!)
count, err := strconv.Atoi(countStr)
// ↑でエラーが起きたら、"count" が整数として解釈できないということなので、
if err != nil {
// ステータスコード 400 Bad Request を返す
return c.String(http.StatusBadRequest, "Bad Request\n")
}
// fizzBuzzの処理を行う
fizzBuzzStr := fizzBuzz(count)
// ステータスコード 200 Ok とfizzBuzzの結果を返す
return c.String(http.StatusOK, fizzBuzzStr)
}
// fizzBuzzの処理。これは競プロ
func fizzBuzz(n int) string {
result := ""
for i := 1; i <= n; i++ {
fizz := i%3 == 0
buzz := i%5 == 0
if fizz && buzz {
result += "FizzBuzz\n"
} else if fizz {
result += "Fizz\n"
} else if buzz {
result += "Buzz\n"
} else {
result += fmt.Sprintf("%d\n", i)
}
}
return result
}
基本問題 POST /add
送信される値を足した数値を返してください。
スキーマ
リクエスト
content-type: application/json
{
"left": 27,
"right": 57
}
レスポンス
content-type: application/json
status code: 200
{
"answer": 84
}
適切でないリクエストの場合
content-type: application/json
status code: 400
{
"error": "Bad Request"
}
を返してください。
完成したら、以下のコマンドをターミナルで実行して上手く機能しているか確認しましょう。
$ curl -X POST "http://localhost:8080/add" -H "Content-Type: application/json" -d '{"left": 18781, "right": 18783}' # 37564
$ curl -X POST "http://localhost:8080/add" -H "Content-Type: application/json" -d '{"left": 0, "right": -0}' # 0
$ curl -X POST "http://localhost:8080/add" -H "Content-Type: application/json" -d '{"left": a, "right": b}' # Bad Request
$ curl -X POST "http://localhost:8080/add" -H "Content-Type: application/json" -d '{"left": 100}' # Bad Request
解答
package main
import (
"net/http"
"github.com/labstack/echo/v4"
)
// Jsonで受け取って構造体に変換するための構造体を定義
type requestData struct {
Left *int `json:"left"`
Right *int `json:"right"`
}
// 計算結果をJsonで返すための構造体を定義
type responseData struct {
Answer int `json:"answer"`
}
// エラーをJsonで返すための構造体を定義
type errorData struct {
Error string `json:"error,omitempty"`
}
func main() {
e := echo.New()
// 「/add」というエンドポイントを設定する
e.POST("/add", addHandler)
e.Logger.Fatal(e.Start(":8080"))
}
func addHandler(c echo.Context) error {
// 受け取りたい JSON を示す空の変数を先に用意する。
numbers := &requestData{}
// 受け取った JSON を data に代入する
err := c.Bind(numbers)
// JSON を data に代入する時にエラーが発生したり、値が空だった時、つまりリクエストが適切ではなかった時、
if err != nil || numbers.Left == nil || numbers.Right == nil {
// ステータスコード 400 Bad Request で"Bad Request"が入ったJSONを返す
return c.JSON(http.StatusBadRequest, &errorData{Error: "Bad Request"})
}
// 計算結果
result := *numbers.Left + *numbers.Right
// 計算結果をステータスコード 200 Ok で返す
return c.JSON(http.StatusOK, &responseData{Answer: result})
}
発展問題 GET /students/:class/:studentNumber
前提:以下のデータをサーバー側で持っておく。
[
{"class_number": 1, "students": [
{"student_number": 1, "name": "pikachu"},
{"student_number": 2, "name": "ikura-hamu"},
{"student_number": 3, "name": "noc7t"}
]},
{"class_number": 2, "students": [
{"student_number": 1, "name": "Sora"},
{"student_number": 2, "name": "Kaito"},
{"student_number": 3, "name": "Haruka"},
{"student_number": 4, "name": "Shingo"}
]},
{"class_number": 3, "students": [
{"student_number": 1, "name": "Hikaru"},
{"student_number": 2, "name": "Eri"},
{"student_number": 3, "name": "Ryo"}
]},
{"class_number": 4, "students": [
{"student_number": 1, "name": "Marina"},
{"student_number": 2, "name": "Takumi"}
]}
]
classNumber
、studentNumber
に対応する学生の情報を JSON で返してください。
学生が存在しない場合、404
を返してください。
スキーマ
リクエスト
/students/2/3
レスポンス
content-type: application/json
status code: 200
{
"student_number": 3,
"name": "Haruka"
}
学生が存在しない場合
content-type: application/json
status code: 404
{
"error": "Student Not Found"
}
TIP
ヒント: 最後の課題のデータは次のような構造体を用意して、json.Unmarshal すると定義しやすいです。
type Student struct {
Number int `json:"student_number"`
Name string `json:"name"`
}
type Class struct {
Number int `json:"class_number"`
Students []Student `json:"students"`
}
完成したら、以下のコマンドをターミナルで実行して上手く機能しているか確認しましょう。
$ curl -X GET "http://localhost:8080/students/1/1" # pikachu
$ curl -X GET "http://localhost:8080/students/3/4" # Student Not Found
$ curl -X GET "http://localhost:8080/students/5/1" # Student Not Found
自分のサーバーが正しく動作しているか確認しよう
カレントディレクトリ(main.go
があるディレクトリ)に、新しくtest.sh
というファイルを作成し、以下をコピー&ペーストしてください。
#!/bin/bash
# ↓これを自分のIDに変更してください
ID=pikachu
# ↑これを自分のIDに変更してください
echo ""
echo "===================="
echo "[TEST] /${ID}"
echo 'curl -X GET http://localhost:8080/'${ID}
curl -X GET "http://localhost:8080/${ID}"
echo ""
echo "===================="
echo "[TEST] /ping"
echo 'curl -X GET http://localhost:8080/ping'
curl -X GET "http://localhost:8080/ping"
echo ""
echo "===================="
echo "[TEST] /fizzbuzz 1of3"
echo '-X GET http://localhost:8080/fizzbuzz?count=20'
curl -X GET "http://localhost:8080/fizzbuzz?count=20"
echo ""
echo "===================="
echo "[TEST] /fizzbuzz 2of3"
echo 'curl -X GET http://localhost:8080/fizzbuzz'
curl -X GET "http://localhost:8080/fizzbuzz"
echo ""
echo "===================="
echo "[TEST] /fizzbuzz 3of3"
echo 'curl -X GET http://localhost:8080/fizzbuzz?count=a'
curl -X GET "http://localhost:8080/fizzbuzz?count=a"
echo ""
echo "===================="
echo "[TEST] /add 1of4"
echo 'curl -X POST http://localhost:8080/add -H "Content-Type: application/json" -d "{\"left\": 18781, \"right\": 18783}"'
curl -X POST "http://localhost:8080/add" -H "Content-Type: application/json" -d '{"left": 18781, "right": 18783}'
echo ""
echo "===================="
echo "[TEST] /add 2of4"
echo 'curl -X POST http://localhost:8080/add -H "Content-Type: application/json" -d "{\"left\": 0, \"right\": -0}"'
curl -X POST "http://localhost:8080/add" -H "Content-Type: application/json" -d '{"left": 0, "right": -0}'
echo ""
echo "===================="
echo "[TEST] /add 3of4"
echo 'curl -X POST http://localhost:8080/add -H "Content-Type: application/json" -d "{\"left\": a, \"right\": b}"'
curl -X POST "http://localhost:8080/add" -H "Content-Type: application/json" -d '{"left": a, "right": b}'
echo ""
echo "===================="
echo "[TEST] /add 4of4"
echo 'curl -X POST http://localhost:8080/add -H "Content-Type: application/json" -d "{\"left\": 100}"'
curl -X POST "http://localhost:8080/add" -H "Content-Type: application/json" -d '{"left": 100}'
echo ""
echo "===================="
echo "[TEST] /students 1of3"
echo 'curl -X GET http://localhost:8080/students/1/1'
curl -X GET "http://localhost:8080/students/1/1"
echo ""
echo "===================="
echo "[TEST] /students 2of3"
echo 'curl -X GET http://localhost:8080/students/3/4'
curl -X GET "http://localhost:8080/students/3/4"
echo ""
echo "===================="
echo "[TEST] /students 3of3"
echo 'curl -X GET http://localhost:8080/students/5/1'
curl -X GET "http://localhost:8080/students/5/1"
echo ""
ペーストした後、ファイル内の以下の部分を自分の ID に書き換えてください。
# ↓これを自分のIDに変更してください
ID=pikachu
# ↑これを自分のIDに変更してください
最後に、ターミナルを開き、以下を実行してください。
$ chmod +x test.sh # 実行権限を付与
$ ./test.sh # シェルスクリプトtest.shを実行
使用例は以下の通りです。
使用例
$ ./test.sh
====================
[TEST] /pikachu
curl -X GET http://localhost:8080/pikachu
始めまして、@pikachuです。
ケモノ(特に四足歩行)や、低頭身デフォルメマスコット(TDM)が大好きです。
普段はVRChatに生息しています。twitter: @pikachu0310VRC
====================
[TEST] /ping
curl -X GET http://localhost:8080/ping
pong
====================
[TEST] /fizzbuzz 1of3
-X GET http://localhost:8080/fizzbuzz?count=20
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
16
17
Fizz
19
Buzz
====================
[TEST] /fizzbuzz 2of3
curl -X GET http://localhost:8080/fizzbuzz
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
16
17
Fizz
19
Buzz
Fizz
22
23
Fizz
Buzz
26
Fizz
28
29
FizzBuzz
====================
[TEST] /fizzbuzz 3of3
curl -X GET http://localhost:8080/fizzbuzz?count=a
Bad Request
====================
[TEST] /add 1of4
curl -X POST http://localhost:8080/add -H "Content-Type: application/json" -d "{\"left\": 18781, \"right\": 18783}"
{"answer":37564}
====================
[TEST] /add 2of4
curl -X POST http://localhost:8080/add -H "Content-Type: application/json" -d "{\"left\": 0, \"right\": -0}"
{"answer":0}
====================
[TEST] /add 3of4
curl -X POST http://localhost:8080/add -H "Content-Type: application/json" -d "{\"left\": a, \"right\": b}"
{"error":"Bad Request"}
====================
[TEST] /add 4of4
curl -X POST http://localhost:8080/add -H "Content-Type: application/json" -d "{\"left\": 100}"
{"error":"Bad Request"}
====================
[TEST] /students 1of2
curl -X GET http://localhost:8080/students/1/1
{"student_number":1,"name":"pikachu"}
====================
[TEST] /students 2of2
curl -X GET http://localhost:8080/students/3/4
{"error":"Student Not Found"}
ここまで出来たら、講習会の実況用チャンネルに./test.sh
の出力結果を貼りましょう!
発展問題は出来てなくても大丈夫ですが、チャレンジしてみてください。
TIP
出力結果は長いので、
```
ここに内容
```
のように内容を```で囲い、コードブロックにして送信すると良いです。