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フィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- Plumber と REST の基礎
- GET エンドポイントと POST エンドポイントの作成
- 認証と API セキュリティ
- Plumber API を本番環境にデプロイする