0Pricing
R Academy · 课时

使用 httr2 发起 HTTP 请求

发送 GET 和 POST 请求,处理标头并处理响应

使用 httr2 发起 HTTP 请求 是 CoddyKit 上的免费 R Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 R Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 R Academy 课程共包含 4 节课。

httr2 简介

httr2 是用于 HTTP 请求的现代 R 程序包,继承并改进了 httr。它采用基于管道的构建器模式:从 request(url) 开始,添加修饰函数,然后使用 req_perform() 执行。

library(httr2)

# Basic GET request pattern:
# request(url)     -> create request object
# |> req_*()       -> modify request
# |> req_perform() -> send request
# |> resp_*()      -> extract from response

# Minimal example (requires internet):
# resp <- request('https://httpbin.org/get') |>
#   req_perform()
# resp_status(resp)     # 200
# resp_body_json(resp)  # parsed JSON body

cat('httr2 follows: build -> perform -> extract')

request() 和 req_perform()

request(url) 会创建请求对象。req_perform() 会执行请求并返回响应对象。随后可以使用 resp_* 函数检查响应。

library(httr2)

# Build and send a GET request
# resp <- request('https://httpbin.org/get') |>
#   req_perform()

# Inspect response
# resp_status(resp)          # 200
# resp_status_desc(resp)     # 'OK'
# resp_headers(resp)         # list of headers
# resp_header(resp, 'content-type')  # single header
# resp_body_string(resp)     # raw body as string
# resp_body_json(resp)       # parsed JSON
# resp_body_raw(resp)        # raw bytes

cat('Response hierarchy:')
cat('status -> headers -> body')

req_headers():自定义标头

req_headers() 会添加或覆盖 HTTP 标头。它可用于身份验证令牌、内容类型声明、API 版本标头以及自定义请求元数据。

library(httr2)

# Add custom headers
# resp <- request('https://api.example.com/data') |>
#   req_headers(
#     'Authorization' = 'Bearer my_token',
#     'X-API-Version' = '2',
#     'Accept'        = 'application/json'
#   ) |>
#   req_perform()

# Common headers:
# 'Content-Type' = 'application/json' for POST with JSON body
# 'Accept'       = 'application/json' to request JSON response
# 'User-Agent'   = 'MyApp/1.0' for polite identification
# 'X-API-Key'    = key  for key-based auth

cat('req_headers() sets HTTP request headers')

req_url_query():查询参数

req_url_query() 会安全地将查询参数追加到 URL(并对特殊字符进行编码)。这比手动使用 paste0() 拼接字符串更加简洁。

library(httr2)

# Add query parameters
# resp <- request('https://api.example.com/search') |>
#   req_url_query(
#     q      = 'R programming',
#     page   = 1,
#     size   = 20,
#     sort   = 'relevance'
#   ) |>
#   req_perform()
# Resulting URL:
# https://api.example.com/search?q=R+programming&page=1&size=20&sort=relevance

# Inspect the URL without performing:
req <- request('https://api.example.com/search') |>
  req_url_query(q = 'hello world', page = 2)
req$url
# 'https://api.example.com/search?q=hello+world&page=2'

使用 req_body_json() 发送 POST 请求

使用 req_body_json() 在 POST 请求中发送 JSON 数据。它会自动设置 Content-Type: application/json 标头,并将 R 列表序列化为 JSON。

library(httr2)

# POST request with JSON body
# resp <- request('https://api.example.com/users') |>
#   req_method('POST') |>
#   req_body_json(list(
#     name  = 'Alice',
#     email = 'alice@example.com',
#     role  = 'admin'
#   )) |>
#   req_perform()

# resp_status(resp)     # 201 Created (if success)
# resp_body_json(resp)  # returned user object

# Other body methods:
# req_body_form(...)  -> application/x-www-form-urlencoded
# req_body_raw(bytes) -> raw bytes
# req_body_file(path) -> file upload
cat('req_body_json() handles Content-Type automatically')

resp_body_json():解析响应

resp_body_json() 会将响应正文解析为 JSON,并转换为 R 列表。使用 simplifyVector=TRUE(默认值)可以自动将 JSON 数组转换为 R 向量,并将对象转换为带名称的列表。

library(httr2)
library(jsonlite)

# Simulated API response handling
# resp <- request('https://api.github.com/users/hadley') |>
#   req_perform()
# user <- resp_body_json(resp)
# user$name    # 'Hadley Wickham'
# user$public_repos  # number of repos
# user$followers     # follower count

# For arrays (simplifyVector=TRUE converts to data frame):
# resp <- request('https://api.github.com/users/hadley/repos') |>
#   req_perform()
# repos <- resp_body_json(resp, simplifyVector = TRUE)
# repos$name  # vector of repo names

cat('resp_body_json() with simplifyVector=TRUE -> data frame')

resp_status() 和错误处理

resp_check_status() 会在响应状态为 4xx/5xx 时自动抛出错误。如果不使用它,httr2 不会因为错误的状态码而报错——您必须显式检查状态,或调用 resp_check_status()。

library(httr2)

# Pattern: check status after perform
# resp <- request('https://api.example.com/data') |>
#   req_perform() |>
#   resp_check_status()  # errors on 4xx/5xx

# Manual status checks:
# status <- resp_status(resp)
# if (status == 200) { ... }
# if (status == 404) { stop('Not found') }
# if (status == 401) { stop('Unauthorized') }
# if (status == 429) { Sys.sleep(60); retry() }

# HTTP status codes:
# 200 OK, 201 Created, 204 No Content
# 400 Bad Request, 401 Unauthorized, 403 Forbidden
# 404 Not Found, 429 Rate Limited
# 500 Server Error, 503 Service Unavailable
cat('Always check response status codes')

req_retry():自动重试

req_retry() 会自动重试失败的请求。请指定 max_tries,还可以选择指定 is_transient(用于识别可重试错误的函数,例如 429 或 503)。对于构建可靠的 API 客户端来说,这一点必不可少。

library(httr2)

# Automatic retry with exponential backoff
# resp <- request('https://api.example.com/data') |>
#   req_retry(
#     max_tries = 3,
#     is_transient = function(resp) {
#       resp_status(resp) %in% c(429, 500, 503)
#     },
#     backoff = ~ 2^.x  # exponential: 2, 4, 8 seconds
#   ) |>
#   req_perform()

# Default retry behavior:
# - Retries on 429 Too Many Requests automatically
# - Uses Retry-After header if present
# - max_tries = 1 by default (no retry)

# Simple retry:
# req_retry(max_tries = 3)  # retry up to 3 times total
cat('req_retry() adds resilience to API calls')

req_throttle():速率限制

req_throttle(rate) 可确保请求速率不超过上限。请传入 rate = n/period(例如每分钟 10 个请求)。httr2 会根据需要在请求之间自动暂停。

library(httr2)

# Throttle to at most 10 requests per minute
# urls <- paste0('https://api.example.com/items/', 1:50)
# resps <- lapply(urls, function(url) {
#   request(url) |>
#     req_throttle(rate = 10 / 60) |>  # 10/min
#     req_perform()
# })

# Alternative: use req_perform_parallel() for parallel
# with throttle built in:
# reqs <- lapply(urls, \(u) request(u))
# resps <- req_perform_parallel(
#   reqs,
#   on_error = 'continue',  # skip failures
#   progress = TRUE
# )

cat('req_throttle(rate = 10/60) = 10 req/min')

身份验证辅助函数

httr2 提供内置的身份验证辅助函数:req_auth_basic(user, pass) 用于基本身份验证,req_auth_bearer_token(token) 用于 Bearer 令牌,req_oauth_*() 用于 OAuth 流程。

library(httr2)

# Bearer token (most common for modern APIs)
# resp <- request('https://api.example.com/data') |>
#   req_auth_bearer_token('my_api_token_here') |>
#   req_perform()

# Basic authentication
# resp <- request('https://api.example.com/data') |>
#   req_auth_basic('username', 'password') |>
#   req_perform()

# Store tokens securely in environment variables
# token <- Sys.getenv('MY_API_TOKEN')
# resp <- request('https://api.example.com') |>
#   req_auth_bearer_token(token) |>
#   req_perform()

cat('Never hardcode tokens in scripts!')
cat('Use Sys.getenv() or the keyring package')

使用 req_dry_run() 进行试运行

req_dry_run() 会准确显示将要发送的请求内容(方法、URL、标头和正文),但不会真正发送请求。在访问真实 API 之前调试复杂请求时,这一功能非常重要。

library(httr2)

# Inspect the request without sending it
req <- request('https://api.example.com/users') |>
  req_method('POST') |>
  req_headers(
    'X-API-Version' = '2',
    'Accept'        = 'application/json'
  ) |>
  req_auth_bearer_token('my_token') |>
  req_body_json(list(name = 'Alice', role = 'admin')) |>
  req_url_query(notify = 'true')

# Show request details without sending
req_dry_run(req)
# POST /users?notify=true HTTP/1.1
# Host: api.example.com
# Authorization: Bearer my_token
# Content-Type: application/json
# ...

快速检查

测试您对 httr2 请求构建模式的理解。

回顾:使用 httr2 发送 HTTP 请求

要点: httr2 使用基于管道的构建器:request(url) |> req_*() |> req_perform()。使用 req_headers() 添加标头,使用 req_url_query() 添加查询参数,使用 req_body_json() 添加 JSON 正文。使用 req_auth_bearer_token() 进行身份验证。始终使用 resp_check_status() 检查状态。使用 req_retry() 增强容错能力,并使用 req_throttle() 限制速率。使用 req_dry_run() 进行调试。

library(httr2)

# Complete httr2 request pattern:
# resp <- request('https://api.example.com/endpoint') |>
#   req_headers('Accept' = 'application/json') |>
#   req_url_query(param1 = 'value', page = 1) |>
#   req_auth_bearer_token(Sys.getenv('API_TOKEN')) |>
#   req_retry(max_tries = 3) |>
#   req_throttle(rate = 10/60) |>
#   req_perform() |>
#   resp_check_status()

# Extract data:
# data <- resp_body_json(resp, simplifyVector = TRUE)

cat('build -> authenticate -> perform -> check -> extract')

常见问题解答

「使用 httr2 发起 HTTP 请求」课时是免费的吗?

是的 — 「使用 httr2 发起 HTTP 请求」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 R Academy 课程的其余内容,请升级到 CoddyKit PRO。 R Academy 课程共包含 4 节课。

「使用 httr2 发起 HTTP 请求」这节课中我会学到什么?

发送 GET 和 POST 请求,处理标头并处理响应 你通过在浏览器中直接运行的动手代码来练习 R Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 R Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 R Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。

「使用 httr2 发起 HTTP 请求」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 R Academy 课中编写并运行代码吗?

能。每节 R Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 使用 jsonlite 解析 JSON
  2. 使用 httr2 发起 HTTP 请求
  3. 在 R 中调用 REST API
  4. 处理嵌套 JSON 结构
← 返回 R Academy