การเรียกใช้ REST API ใน R
ยืนยันตัวตนด้วยคีย์ API แบ่งหน้า�ลัพธ์ และจัดเก็บการตอบกลับจาก API
การเรียกใช้ REST API ใน R เป็นบทเรียน R Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน R Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส R Academy มีบทเรียนทั้งหมด 4 บทเรียน
แนวคิดเกี่ยวกับ REST API
REST API ใช้เมธอด HTTP (GET, POST, PUT, DELETE) กับ URL ของทรัพยากร โดยทั่วไปการตอบกลับจะเป็น JSON API อาจต้องมีการยืนยันตัวตน รองรับการแบ่งหน้า และบังคับใช้การจำกัดอัตราการเรียกใช้ ไคลเอ็นต์ API ของ R ที่ดีควรจัดการทั้งสามเรื่องนี้
library(httr2)
# REST API anatomy:
# Base URL: https://api.example.com/v1
# Resources: /users, /products, /orders
# Methods:
# GET /users -> list users
# POST /users -> create user
# GET /users/42 -> get user 42
# PUT /users/42 -> update user 42
# DELETE /users/42 -> delete user 42
# Query parameters for filtering/pagination:
# GET /users?page=2&size=20&sort=name
cat('REST = stateless + resource-based + HTTP methods')การยืนยันตัวตนด้วยโทเค็นแบบ Bearer
API สมัยใหม่ส่วนใหญ่ใช้โทเค็นแบบ Bearer (OAuth 2.0) ให้จัดเก็บโทเค็นไว้ในตัวแปรสภาพแวดล้อมด้วย Sys.setenv() หรือในไฟล์ .Renviron อย่าเขียนโทเค็นลงในสคริปต์แบบตายตัวโดยเด็ดขาด
library(httr2)
# Store token securely in .Renviron:
# GITHUB_PAT=ghp_your_token_here
# Access at runtime:
token <- Sys.getenv('GITHUB_PAT')
if (nchar(token) == 0) token <- 'demo_token'
# Use in requests:
# resp <- request('https://api.github.com/user') |>
# req_auth_bearer_token(token) |>
# req_headers('Accept' = 'application/vnd.github.v3+json') |>
# req_perform() |>
# resp_check_status()
# result <- resp_body_json(resp)
# result$login # your GitHub username
cat('Token from env:', if(nchar(token)>0) 'found' else 'missing')สร้างไคลเอ็นต์ API ที่นำกลับมาใช้ซ้ำได้
รวม URL พื้นฐาน การยืนยันตัวตน และการจัดการข้อผิดพลาดไว้ในฟังก์ชันตัวสร้าง แต่ละจุดเชื่อมต่อ API จะกลายเป็นเมธอดที่เรียกใช้ฟังก์ชันพื้นฐานนี้ ซึ่งเป็นรูปแบบมาตรฐานสำหรับแพ็กเกจ API ของ R
library(httr2)
# API client constructor
new_api_client <- function(base_url, token) {
list(
base_req = request(base_url) |>
req_auth_bearer_token(token) |>
req_headers('Accept' = 'application/json') |>
req_retry(max_tries = 3)
)
}
# Method: GET /users
get_users <- function(client, page = 1, size = 20) {
resp <- client$base_req |>
req_url_path_append('users') |>
req_url_query(page = page, size = size) |>
req_perform() |>
resp_check_status()
resp_body_json(resp, simplifyVector = TRUE)
}
# client <- new_api_client('https://api.example.com', token)
# users <- get_users(client, page = 1)
cat('Reusable client pattern: base request + methods')การแบ่งหน้าด้วย resp_link_url()
API จำนวนมากใช้ส่วนหัว Link สำหรับการแบ่งหน้า (RFC 5988) โดยการตอบกลับจะมีส่วนหัว Link: <url>; rel="next" ฟังก์ชัน resp_link_url(resp, 'next') จะแยก URL ของหน้าถัดไปโดยอัตโนมัติ
library(httr2)
# Generic paginator using Link headers
fetch_all_pages <- function(initial_url, token, max_pages = 50) {
all_results <- list()
next_url <- initial_url
page <- 1
while (!is.null(next_url) && page <= max_pages) {
resp <- request(next_url) |>
req_auth_bearer_token(token) |>
req_perform() |>
resp_check_status()
all_results[[page]] <- resp_body_json(resp, simplifyVector = TRUE)
# Follow Link: <url>; rel='next' header
next_url <- tryCatch(
resp_link_url(resp, 'next'),
error = function(e) NULL
)
page <- page + 1
}
do.call(rbind, all_results)
}
cat('resp_link_url() follows RFC 5988 pagination')การแบ่งหน้าโดยใช้เคอร์เซอร์
API บางแห่ง (Twitter, Slack) ใช้เคอร์เซอร์แทนหมายเลขหน้า การตอบกลับจะมีฟิลด์ next_cursor หรือ next_page_token ให้ส่งค่านี้เป็นพารามิเตอร์คำค้นสำหรับคำขอถัดไป
library(httr2)
# Cursor-based pagination pattern
fetch_cursor_pages <- function(base_url, token, max_pages = 100) {
all_data <- list()
cursor <- NULL
page <- 1
repeat {
req <- request(base_url) |>
req_auth_bearer_token(token)
if (!is.null(cursor))
req <- req |> req_url_query(cursor = cursor)
resp <- req |> req_perform() |> resp_check_status()
body <- resp_body_json(resp)
all_data[[page]] <- body$results
cursor <- body$next_cursor # NULL if last page
if (is.null(cursor) || page >= max_pages) break
page <- page + 1
}
do.call(c, all_data)
}
cat('Cursor pagination: safer for large/changing datasets')จัดการข้อผิดพลาดอย่างเหมาะสม
ไคลเอ็นต์ API ที่ใช้งานจริงควรแยกจัดการข้อผิดพลาด HTTP และความล้มเหลวของเครือข่าย ใช้ tryCatch() ครอบ req_perform() และตรวจสอบเงื่อนไขข้อผิดพลาด httr2_http_* เพื่อจัดการตามสถานะ
library(httr2)
safe_api_call <- function(req) {
tryCatch(
req |> req_perform() |> resp_check_status(),
httr2_http_401 = function(e) {
stop('Authentication failed. Check your token.')
},
httr2_http_403 = function(e) {
stop('Forbidden. Insufficient permissions.')
},
httr2_http_404 = function(e) {
message('Resource not found, returning NULL')
return(NULL)
},
httr2_http_429 = function(e) {
stop('Rate limit exceeded. Try again later.')
},
error = function(e) {
stop(paste('Request failed:', conditionMessage(e)))
}
)
}
cat('Match on specific httr2_http_NNN conditions')แคชการตอบกลับจาก API
แคชการตอบกลับจาก API เพื่อหลีกเลี่ยงคำขอที่ไม่จำเป็นระหว่างการพัฒนา req_cache() ใน httr2 จะแคชการตอบกลับลงดิสก์โดยเคารพส่วนหัว Cache-Control การแคชด้วยตนเองก็ใช้ได้กับ API ทุกประเภท
library(httr2)
# httr2 built-in disk cache
# resp <- request('https://api.example.com/static-data') |>
# req_cache(tempdir(), max_age = 3600) |> # 1 hour TTL
# req_perform()
# Manual cache pattern
cached_api_call <- function(url, cache_file, max_age = 3600) {
if (file.exists(cache_file)) {
age <- as.numeric(Sys.time() - file.mtime(cache_file))
if (age < max_age) {
cat('Cache hit\n')
return(readRDS(cache_file))
}
}
cat('Cache miss, fetching...\n')
# result <- resp_body_json(request(url) |> req_perform())
# saveRDS(result, cache_file)
# result
}
cached_api_call('https://example.com/api', 'cache.rds')คำขอแบบขนานด้วย req_perform_parallel()
req_perform_parallel() จะส่งคำขอหลายรายการพร้อมกัน ซึ่งช่วยลดเวลารวมของการดำเนินการเป็นชุดได้อย่างมาก ใช้ร่วมกับ req_throttle() เพื่อให้ยังคงปฏิบัติตามการจำกัดอัตราระหว่างการทำงานแบบขนาน
library(httr2)
# Build a list of requests
item_ids <- 1:5
reqs <- lapply(item_ids, function(id) {
request(paste0('https://jsonplaceholder.typicode.com/todos/', id))
})
# Execute all in parallel (requires internet)
# resps <- req_perform_parallel(
# reqs,
# on_error = 'continue', # skip failures
# progress = TRUE
# )
# results <- lapply(resps, resp_body_json)
# titles <- sapply(results, function(r) r$title)
# print(titles)
# on_error options:
# 'stop' -> abort on first failure
# 'continue' -> collect errors, keep going
cat('Parallel: much faster for many independent calls')ทำงานกับการจำกัดอัตรา
API จะแจ้งสถานะการจำกัดอัตราผ่านส่วนหัวการตอบกลับ ได้แก่ X-RateLimit-Remaining, X-RateLimit-Reset และ Retry-After อ่านค่าเหล่านี้เพื่อใช้สร้างการถอยรออย่างชาญฉลาด
library(httr2)
respect_rate_limit <- function(resp) {
# Check remaining calls
remaining <- resp_header(resp, 'x-ratelimit-remaining')
if (!is.na(remaining) && as.integer(remaining) < 5) {
reset_at <- as.integer(
resp_header(resp, 'x-ratelimit-reset')
)
wait_secs <- max(0, reset_at - as.integer(Sys.time()))
cat(sprintf('Rate limit nearly exhausted. Waiting %ds\n', wait_secs))
# Sys.sleep(wait_secs)
}
# Handle 429 Retry-After header
if (resp_status(resp) == 429) {
retry_after <- resp_header(resp, 'retry-after')
cat(sprintf('Rate limited. Retry after %s seconds\n', retry_after))
}
resp
}
cat('Always respect X-RateLimit-* headers')ไคลเอ็นต์ API ฉบับสมบูรณ์: ตัวอย่าง GitHub
รวมทุกอย่างเข้าด้วยกัน: ไคลเอ็นต์ GitHub API ฉบับสมบูรณ์ที่ยืนยันตัวตน ดึงรายการคลังข้อมูลแบบแบ่งหน้า และจัดการข้อผิดพลาด โดยสาธิตรูปแบบทั้งหมดที่ได้เรียนรู้มา
library(httr2)
# GitHub API client
github_repos <- function(username, token = NULL, n_pages = 3) {
base <- 'https://api.github.com'
req_base <- request(base) |>
req_headers(
'Accept' = 'application/vnd.github.v3+json',
'User-Agent' = 'R-API-Client/1.0'
)
if (!is.null(token))
req_base <- req_base |> req_auth_bearer_token(token)
all_repos <- list()
for (page in seq_len(n_pages)) {
# resp <- req_base |>
# req_url_path_append('users', username, 'repos') |>
# req_url_query(page = page, per_page = 30, sort = 'updated') |>
# req_perform() |> resp_check_status()
# repos <- resp_body_json(resp, simplifyVector = TRUE)
# if (length(repos) == 0) break
# all_repos[[page]] <- repos
cat(sprintf('Would fetch page %d for %s\n', page, username))
}
do.call(rbind, all_repos)
}
github_repos('hadley')ข้อมูลประจำตัวไคลเอ็นต์ OAuth 2.0
API บางแห่งต้องใช้กระบวนการข้อมูลประจำตัวไคลเอ็นต์ OAuth 2.0 โดยแลก client_id + client_secret เป็นโทเค็นการเข้าถึง oauth_client() และ req_oauth_client_credentials() ของ httr2 จะจัดการเรื่องนี้โดยอัตโนมัติ
library(httr2)
# OAuth 2.0 Client Credentials flow:
# client <- oauth_client(
# id = Sys.getenv('CLIENT_ID'),
# secret = Sys.getenv('CLIENT_SECRET'),
# token_url = 'https://auth.example.com/oauth/token'
# )
# Automatic token management:
# resp <- request('https://api.example.com/data') |>
# req_oauth_client_credentials(client) |>
# req_perform()
# httr2 automatically:
# 1. Gets access token using client credentials
# 2. Adds 'Authorization: Bearer <token>' header
# 3. Refreshes token when expired
cat('req_oauth_client_credentials() handles token lifecycle')
cat('Token is cached in memory automatically')ตรวจสอบความเข้าใจอย่างรวดเร็ว
ทดสอบความเข้าใจเกี่ยวกับการสร้างไคลเอ็นต์ REST API ใน R ด้วย httr2
ทบทวน: เรียกใช้ REST API
ประเด็นสำคัญ: สร้างไคลเอ็นต์ที่นำกลับมาใช้ซ้ำได้โดยรวม URL พื้นฐาน การยืนยันตัวตน และการลองส่งซ้ำไว้ในฟังก์ชันตัวสร้าง ใช้ req_auth_bearer_token() สำหรับการยืนยันตัวตน และจัดเก็บโทเค็นไว้ในตัวแปรสภาพแวดล้อม จัดการการแบ่งหน้าผ่านส่วนหัว Link ด้วย resp_link_url() หรือรูปแบบที่ใช้เคอร์เซอร์ จัดการข้อผิดพลาด HTTP ด้วย resp_check_status() และ tryCatch() เสมอ ใช้ req_perform_parallel() สำหรับคำขอเป็นชุด และแคชผลลัพธ์ระหว่างการพัฒนา
library(httr2)
# REST API client template:
make_api_call <- function(url, token,
method = 'GET',
body = NULL,
query = list()) {
req <- request(url) |>
req_method(method) |>
req_auth_bearer_token(token) |>
req_headers('Accept' = 'application/json') |>
req_retry(max_tries = 3) |>
req_throttle(rate = 10/60)
if (length(query) > 0)
req <- do.call(req_url_query, c(list(req), query))
if (!is.null(body))
req <- req |> req_body_json(body)
req |> req_perform() |> resp_check_status()
}
cat('Template: auth + retry + throttle + error check')เรียนรู้ R ด้วย AI tutor — ฟรี
เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป
- คอร์ส
- 43
- บทเรียน
- 159
คำถามที่พบบ่อย
บทเรียน “การเรียกใช้ REST API ใน R” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การเรียกใช้ REST API ใน R” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส R Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส R Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การเรียกใช้ REST API ใน R”
ยืนยันตัวตนด้วยคีย์ API แบ่งหน้า�ลัพธ์ และจัดเก็บการตอบกลับจาก API คุณปฏิบัติ R Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน R Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน R Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน
บทเรียน “การเรียกใช้ REST API ใน R” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน R Academy นี้ได้ไหม
ได้ บทเรียน R Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การแยกวิเคราะห์ JSON ด้วย jsonlite
- การส่งคำขอ HTTP ด้วย httr2
- การเรียกใช้ REST API ใน R
- การจัดการโครงสร้าง JSON แบบซ้อนกัน