0Pricing
R Academy · レッスン

GET エンドポイントと POST エンドポイントの作成

パスパラメーター、クエリ文字列、リクエストボディのパースを扱います。

「GET エンドポイントと POST エンドポイントの作成」はCoddyKit上の無料R Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはR Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 R Academyコースには全4レッスンが含まれています。

Plumberとは

plumberは、特殊なコメントアノテーションを使って、通常のR関数をHTTP APIエンドポイントに変換します。関数に#* @get /pathを付けると、Plumberはその関数を呼び出して結果をJSONで返すGETルートを作成します。

install.packages('plumber')でインストールできます。

最初のGETエンドポイント

基本的なPlumber APIはファイル(例:api.R)に記述します。関数に#* @getとパスを続けて記述します。Plumberは関数の戻り値を自動的にJSONへシリアライズします。

# api.R
# library(plumber)
#
# #* Return a greeting
# #* @get /hello
# function() {
#   list(message = 'Hello from Plumber!')
# }
#
# Start with:
# pr <- plumb('api.R')
# pr$run(port = 8000)

型ヒント付きパスパラメーター

山かっこ構文を使うと、パスに可変のセグメントを埋め込めます:/users/<id:int>。Plumberはそのセグメントを解析し、型付きの引数として関数に渡します。対応している型にはint、dbl、chrがあります。

# #* Get a user by ID
# #* @get /users/<id:int>
# function(id) {
#   # id is already an integer
#   list(
#     user_id = id,
#     name    = paste('User', id)
#   )
# }
#
# GET /users/42  =>  {"user_id":42, "name":"User 42"}

#* @paramによるクエリパラメーター

#* @param name Descriptionを使ってクエリパラメーターをドキュメント化します。パラメーター名は関数の引数名と一致している必要があります。Plumberがクエリ文字列から自動的に読み取るため、手動で解析する必要はありません。

# #* Search users by name
# #* @param name The name to search for
# #* @param limit Maximum results to return
# #* @get /users/search
# function(name = '', limit = '10') {
#   limit <- as.integer(limit)
#   # query string: /users/search?name=Alice&limit=5
#   list(query = name, max = limit)
# }

POSTエンドポイントの作成

リクエスト本文を受け取るエンドポイントには#* @post /pathを使用します。特殊なreq引数から、生のリクエストオブジェクトにアクセスできます。関数の引数名をreqにすると、Plumberが自動的に渡します。

# #* Create a new user
# #* @post /users
# function(req) {
#   body <- jsonlite::fromJSON(req$postBody)
#   # body$name, body$email are now available
#   list(
#     status  = 'created',
#     user_id = sample(1000:9999, 1),
#     name    = body$name
#   )
# }

リクエスト本文の解析

req$postBodyには、POST本文に含まれる生のJSON文字列が格納されます。jsonlite::fromJSON(req$postBody)で解析すると、名前付きRリストを取得できます。処理を行う前に、必須フィールドを必ず検証してください。

# #* @post /orders
# function(req, res) {
#   body <- jsonlite::fromJSON(req$postBody)
#   if (is.null(body$product_id)) {
#     res$status <- 400L
#     return(list(error = 'product_id is required'))
#   }
#   list(
#     order_id   = as.integer(Sys.time()),
#     product_id = body$product_id,
#     quantity   = body$quantity %||% 1
#   )
# }

res$statusによるHTTPステータスコード

res引数(Plumberによって自動的に注入されます)を使うと、HTTPレスポンスのステータスコードを設定できます。戻り値を返す前に設定してください:res$status <- 404L。一般的なコードは次のとおりです。

  • 200 — OK(デフォルト)
  • 201 — 作成済み
  • 400 — 不正なリクエスト
  • 404 — 見つかりません
  • 500 — 内部サーバーエラー
# #* @get /items/<id:int>
# function(id, res) {
#   items <- list(
#     list(id=1, name='Widget'),
#     list(id=2, name='Gadget')
#   )
#   found <- Filter(function(x) x$id == id, items)
#   if (length(found) == 0) {
#     res$status <- 404L
#     return(list(error = paste('Item', id, 'not found')))
#   }
#   found[[1]]
# }

名前付きリストをJSONとして返す

Plumberはjsonliteを使って、Rの戻り値をJSONにシリアライズします。名前付きリストはJSONオブジェクトに、名前なしリストはJSON配列になります。構造化されたレスポンスには、名前付きリストを返してください。

# Named list => JSON object
# list(id=1, name='Alice')  => {"id":1, "name":"Alice"}
#
# Unnamed list => JSON array
# list(1, 2, 3)  =>  [1, 2, 3]
#
# Nested structures work too:
# list(
#   user   = list(id=1, name='Alice'),
#   orders = list(list(id=101), list(id=102))
# )
# => {"user":{"id":1,"name":"Alice"}, "orders":[{"id":101},{"id":102}]}

Plumberルーターオブジェクト

アノテーション付きのRファイルをplumb('api.R')で読み込むと、Plumberのrouterオブジェクトが作成されます。pr$run(port = 8000)を呼び出すとサーバーが起動します。本番環境では通常、pr_run(pr, host='0.0.0.0', port=8000)を呼び出します。

# Standard plumber startup in api_start.R:
# library(plumber)
# pr <- plumb('api.R')
# pr$run(port = 8000, host = '0.0.0.0')
#
# Or with pipe style:
# plumb('api.R') |> pr_run(port = 8000)
#
# Test with:
# curl http://localhost:8000/hello

複数のHTTPメソッドへの対応

アノテーション付きの関数を別々に記述することで、1つのパスで複数のメソッドをサポートできます。Plumberは、使用されたHTTPメソッドに基づいて、リクエストを適切な関数に振り分けます。

# #* List all products
# #* @get /products
# function() {
#   list(products = list(list(id=1, name='Widget')))
# }
#
# #* Create a product
# #* @post /products
# function(req) {
#   body <- jsonlite::fromJSON(req$postBody)
#   list(created = TRUE, name = body$name)
# }

APIエンドポイントのテスト

サーバーの実行中に、ターミナルからcurlを使用するか、Rからhttr2を使用してエンドポイントをテストします。httr2を使うと、APIコードと一緒に再現可能なテストを記述できます。

# From terminal:
# curl http://localhost:8000/users/42
# curl -X POST http://localhost:8000/users \
#      -H 'Content-Type: application/json' \
#      -d '{"name":"Alice","email":"alice@example.com"}'
#
# From R:
# library(httr2)
# resp <- request('http://localhost:8000/users/42') |> req_perform()
# resp_body_json(resp)

クイックチェック:パスパラメーター

Plumberが整数として解析する、idという名前のパスパラメーターはどのように宣言しますか?

GETおよびPOSTエンドポイントのまとめ

PlumberでRESTエンドポイントを構築する方法:

  • #* @get /pathはGETルートを作成し、#* @post /pathはPOSTルートを作成します
  • パスパラメーターには<name:type>構文(int、dbl、chr)を使用します
  • クエリパラメーターは、一致する関数の引数に自動的に解析されます
  • POST本文にはjsonlite::fromJSON(req$postBody)でアクセスできます
  • 200以外のHTTPレスポンスにはres$statusを設定します
  • 名前付きリストを返すと、自動的にJSONオブジェクトへシリアライズされます

よくある質問

「GET エンドポイントと POST エンドポイントの作成」レッスンは無料ですか?

はい。「GET エンドポイントと POST エンドポイントの作成」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、R Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 R Academyコースには全4レッスンが含まれています。

「GET エンドポイントと POST エンドポイントの作成」で何を学びますか?

パスパラメーター、クエリ文字列、リクエストボディのパースを扱います。 ブラウザで直接実行するハンズオンコードでR Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

R Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのR Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。

「GET エンドポイントと POST エンドポイントの作成」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このR Academyレッスンでコードを書いて実行できますか?

はい。すべてのR Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. Plumber と REST の基礎
  2. GET エンドポイントと POST エンドポイントの作成
  3. 認証と API セキュリティ
  4. Plumber API を本番環境にデプロイする
← R Academyに戻る