Chapter 03無料公開

curlコマンドからランブックを生成する

Ken’ichiro Oyama
Ken’ichiro Oyama
2023.01.06に更新

ターミナルからHTTPリクエストを送信するために使われるコマンドとして curl があります。

https://curl.se/

runnはcurlコマンドからランブックを生成できます。

まずcurlコマンドを組み立てます。

例として https://httpbin.org/json へGETリクエストを送信します。

$ curl https://httpbin.org/json -H "accept: application/json"
{
  "slideshow": {
    "author": "Yours Truly",
    "date": "date of publication",
    "slides": [
      {
        "title": "Wake up to WonderWidgets!",
        "type": "all"
      },
      {
        "items": [
          "Why <em>WonderWidgets</em> are great",
          "Who <em>buys</em> WonderWidgets"
        ],
        "title": "Overview",
        "type": "all"
      }
    ],
    "title": "Sample Slide Show"
  }
}

JSON形式のレスポンスが返ってきていることがわかります。

runn new でcurlコマンドをランブック形式に変換する

runn new はランブック形式に変換するコマンドです。

curlコマンドの先頭に runn new -- をつけて実行すると、curlコマンドをランブック形式に変換して標準出力に出力します。

$ runn new -- curl https://httpbin.org/json -H "accept: application/json"
desc: Generated by `runn new`
runners:
  req: https://httpbin.org
steps:
- req:
    /json:
      get:
        headers:
          Accept: application/json
        body: null

--and-run オプションで、curlコマンドを変換したランブックを実行して test: も生成する

--and-run オプションは、対象(今回はcurlコマンド)ランブック形式に変換するだけでなく、実際にそのランブックを実行して受け取ったレスポンスを test: セクションとして追加するオプションです。

curlコマンドの先頭に runn new --and-run -- をつけて実行すると、curlコマンドを test: セクション付きのランブック形式に変換して標準出力に出力します。

$ runn new --and-run -- curl https://httpbin.org/json -H "accept: application/json"
desc: Generated by `runn new`
runners:
  req: https://httpbin.org
steps:
- req:
    /json:
      get:
        headers:
          Accept: application/json
        body: null
  test: |
    current.res.status == 200
    && current.res.headers['Access-Control-Allow-Credentials'][0] == "true"
    && current.res.headers['Access-Control-Allow-Origin'][0] == "*"
    && current.res.headers['Content-Length'][0] == "429"
    && current.res.headers['Content-Type'][0] == "application/json"
    && 'Date' in current.res.headers
    && current.res.headers['Server'][0] == "gunicorn/19.9.0"
    && compare(current.res.body, {"slideshow":{"author":"Yours Truly","date":"date of publication","slides":[{"title":"Wake up to WonderWidgets!","type":"all"},{"items":["Why <em>WonderWidgets</em> are great","Who <em>buys</em> WonderWidgets"],"title":"Overview","type":"all"}],"title":"Sample Slide Show"}})

[コラム] curlコマンドのパース

runnではcurlコマンドのパースに github.com/k1LoW/curlreq パッケージを使用しています。

https://github.com/k1LoW/curlreq

tj/parse-curl.js を参考に、いくつかの修正とGoのパッケージとしての使いやすさを加えています。

curlコマンドの文字列から *http.Request を直接生成するというのはGoが net/http パッケージを標準で持っているからこそのアプローチです。

package main

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

	"github.com/k1LoW/curlreq"
)

func main() {
	cmd := "curl https://example.com"
	req, err := curlreq.NewRequest(cmd)
	if err != nil {
		log.Fatal(err)
	}
	client := http.DefaultClient
	resp, err := client.Do(req)
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()

	fmt.Println(resp.StatusCode)

	// Output:
	// 200
}