HTTP 엔드포인트
엔드포인트(http.endpoint)는 Lua 함수를 실행하는 HTTP 라우트 핸들러를 정의합니다.
정의
- name: get_user
kind: http.endpoint
router: api_router
method: GET
path: /users/{id}
func: app.users:get_user
설정
| 필드 | 타입 | 설명 |
|---|---|---|
router |
registry.ID | 부모 라우터 (라우터가 하나면 선택적) |
method |
string | HTTP 메서드 |
path |
string | URL 경로 패턴 |
func |
registry.ID | 실행할 함수 |
HTTP 메서드
지원되는 메서드:
| 메서드 | 사용 사례 |
|---|---|
GET |
리소스 조회 |
POST |
리소스 생성 |
PUT |
리소스 교체 |
PATCH |
부분 업데이트 |
DELETE |
리소스 삭제 |
HEAD |
헤더만 |
OPTIONS |
CORS 프리플라이트 (자동 처리) |
경로 파라미터
URL 파라미터에 {param} 구문 사용:
- name: get_user
kind: http.endpoint
method: GET
path: /users/{id}
func: get_user
- name: get_user_post
kind: http.endpoint
method: GET
path: /users/{user_id}/posts/{post_id}
func: get_user_post
핸들러에서 접근:
function(req, res)
local user_id = req:param("id")
local post_id = req:param("post_id")
end
와일드카드 경로
{path...}로 나머지 경로 캡처:
- name: file_handler
kind: http.endpoint
method: GET
path: /files/{path...}
func: serve_file
function(req, res)
local file_path = req:param("path")
-- /files/docs/readme.md -> path = "docs/readme.md"
end
핸들러 함수
엔드포인트 함수는 요청 및 응답 객체를 받습니다:
function(req, res)
-- 요청 읽기
local body = req:body()
local user_id = req:param("id")
local page = req:query("page")
local auth = req:header("Authorization")
-- 처리
local user = get_user(user_id)
-- 응답 쓰기
res:set_header("Content-Type", "application/json")
res:set_status(200)
res:write(json.encode(user))
end
Request 객체
| 메서드 | 반환값 | 설명 |
|---|---|---|
req:method() |
string | HTTP 메서드 |
req:path() |
string | 요청 경로 |
req:param(name) |
string | URL 파라미터 |
req:query(name) |
string | 쿼리 파라미터 |
req:header(name) |
string | 요청 헤더 |
req:headers() |
table | 모든 헤더 |
req:body() |
string | 요청 본문 |
req:cookie(name) |
string | 쿠키 값 |
req:remote_addr() |
string | 클라이언트 IP 주소 |
Response 객체
| 메서드 | 설명 |
|---|---|
res:set_status(code) |
HTTP 상태 설정 |
res:set_header(name, value) |
헤더 설정 |
res:set_cookie(name, value, opts) |
쿠키 설정 |
res:write(data) |
본문 쓰기 |
res:redirect(url, code?) |
리다이렉트 (기본값 302) |
JSON API 패턴
JSON API의 일반적인 패턴:
local json = require("json")
function(req, res)
-- JSON 본문 파싱
local data, err = json.decode(req:body())
if err then
res:set_status(400)
res:set_header("Content-Type", "application/json")
res:write(json.encode({error = "Invalid JSON"}))
return
end
-- 요청 처리
local result = process(data)
-- JSON 응답 반환
res:set_status(200)
res:set_header("Content-Type", "application/json")
res:write(json.encode(result))
end
에러 응답
local function api_error(res, status, code, message)
res:set_status(status)
res:set_header("Content-Type", "application/json")
res:write(json.encode({
error = {
code = code,
message = message
}
}))
end
function(req, res)
local user_id = req:param("id")
local user, err = db.get_user(user_id)
if err then
if errors.is(err, errors.NOT_FOUND) then
return api_error(res, 404, "USER_NOT_FOUND", "User not found")
end
return api_error(res, 500, "INTERNAL_ERROR", "Server error")
end
res:set_status(200)
res:set_header("Content-Type", "application/json")
res:write(json.encode(user))
end
예제
CRUD 엔드포인트
entries:
- name: users_router
kind: http.router
prefix: /api/users
middleware:
- cors
- compress
- name: list_users
kind: http.endpoint
router: users_router
method: GET
path: /
func: app.users:list
- name: get_user
kind: http.endpoint
router: users_router
method: GET
path: /{id}
func: app.users:get
- name: create_user
kind: http.endpoint
router: users_router
method: POST
path: /
func: app.users:create
- name: update_user
kind: http.endpoint
router: users_router
method: PUT
path: /{id}
func: app.users:update
- name: delete_user
kind: http.endpoint
router: users_router
method: DELETE
path: /{id}
func: app.users:delete
보호된 엔드포인트
- name: admin_endpoint
kind: http.endpoint
router: admin_router
method: POST
path: /settings
func: app.admin:update_settings
post_middleware:
- endpoint_firewall
post_options:
endpoint_firewall.action: "admin"