라우팅
라우터는 URL 프리픽스 아래에 엔드포인트를 그룹화하고 공유 미들웨어를 적용합니다. 엔드포인트는 HTTP 핸들러를 정의합니다.
아키텍처
flowchart TB
S[http.service
:8080] --> R1[http.router
/api]
S --> R2[http.router
/admin]
S --> ST[http.static
/]
R1 --> E1[GET /users]
R1 --> E2[POST /users]
R1 --> E3["GET /users/{id}"]
R2 --> E4[GET /stats]
R2 --> E5[POST /config]
엔트리는 메타데이터를 통해 부모를 참조합니다:
- 라우터:
meta.server: app:gateway - 엔드포인트:
meta.router: app:api
라우터 설정
- name: api
kind: http.router
meta:
server: gateway
prefix: /api/v1
middleware:
- cors
- compress
options:
cors.allow.origins: "*"
post_middleware:
- endpoint_firewall
| 필드 | 타입 | 설명 |
|---|---|---|
meta.server |
레지스트리 ID | 부모 HTTP 서버 |
prefix |
string | 모든 라우트의 URL 프리픽스 |
middleware |
[]string | 매칭 전 미들웨어 |
options |
map | 미들웨어 옵션 |
post_middleware |
[]string | 매칭 후 미들웨어 |
post_options |
map | 매칭 후 미들웨어 옵션 |
엔드포인트 설정
- name: get_user
kind: http.endpoint
meta:
router: api
method: GET
path: /users/{id}
func: app.users:get_user
| 필드 | 타입 | 설명 |
|---|---|---|
meta.router |
레지스트리 ID | 부모 라우터 |
method |
string | HTTP 메서드 (GET, POST, PUT, DELETE, PATCH, HEAD) |
path |
string | URL 경로 패턴 (/로 시작) |
func |
레지스트리 ID | 핸들러 함수 |
경로 파라미터
URL 파라미터에 {param} 구문 사용:
- name: get_post
kind: http.endpoint
meta:
router: api
method: GET
path: /users/{user_id}/posts/{post_id}
func: get_user_post
핸들러에서 접근:
local http = require("http")
local function handler()
local req = http.request()
local user_id = req:param("user_id")
local post_id = req:param("post_id")
-- ...
end
와일드카드 경로
{param...}으로 나머지 경로 세그먼트 캡처:
- name: serve_files
kind: http.endpoint
meta:
router: api
method: GET
path: /files/{filepath...}
func: serve_file
-- 요청: GET /api/v1/files/docs/guides/readme.md
local file_path = req:param("filepath") -- "docs/guides/readme.md"
와일드카드는 경로의 마지막 세그먼트여야 합니다.
핸들러 함수
엔드포인트 핸들러는 http 모듈을 사용하여 요청 및 응답 객체에 접근합니다. 전체 API는 HTTP 모듈을 참조하세요.
local http = require("http")
local json = require("json")
local function handler()
local req = http.request()
local res = http.response()
local user_id = req:param("id")
local user = get_user(user_id)
res:status(200)
res:write(json.encode(user))
end
return { handler = handler }
미들웨어 옵션
미들웨어 옵션은 미들웨어 이름을 프리픽스로 하는 점 표기법을 사용합니다:
middleware:
- cors
- ratelimit
- token_auth
options:
cors.allow.origins: "https://app.example.com"
cors.allow.methods: "GET,POST,PUT,DELETE"
ratelimit.requests: "100"
ratelimit.window: "1m"
token_auth.store: "app:tokens"
token_auth.header.name: "Authorization"
매칭 후 미들웨어는 post_options 사용:
post_middleware:
- endpoint_firewall
post_options:
endpoint_firewall.default_policy: "deny"
매칭 전 vs 매칭 후 미들웨어
매칭 전 (middleware)은 라우트 매칭 전에 실행:
- CORS (OPTIONS 프리플라이트 처리)
- 압축
- 레이트 리미팅
- 실제 IP 감지
- 토큰 인증 (컨텍스트 보강)
매칭 후 (post_middleware)는 라우트 매칭 후에 실행:
- 엔드포인트 방화벽 (인가에 라우트 정보 필요)
- 리소스 방화벽
- WebSocket 릴레이
middleware: # 매칭 전: 이 라우터로의 모든 요청
- cors
- compress
- token_auth # 액터/스코프로 컨텍스트 보강
post_middleware: # 매칭 후: 매칭된 라우트만
- endpoint_firewall # token_auth의 액터 사용
token_auth가 설정한 액터를 사용하는 endpoint_firewall 같은 매칭 후 미들웨어에서 처리합니다.
전체 예제
version: "1.0"
namespace: app
entries:
# 서버
- name: gateway
kind: http.service
addr: ":8080"
lifecycle:
auto_start: true
# API 라우터
- name: api
kind: http.router
meta:
server: gateway
prefix: /api/v1
middleware:
- cors
- compress
- ratelimit
options:
cors.allow.origins: "https://app.example.com"
ratelimit.requests: "100"
ratelimit.window: "1m"
# 핸들러 함수
- name: get_users
kind: function.lua
source: file://handlers/users.lua
method: list
modules:
- http
- json
- sql
# 엔드포인트
- name: list_users
kind: http.endpoint
meta:
router: api
method: GET
path: /users
func: get_users
- name: get_user
kind: http.endpoint
meta:
router: api
method: GET
path: /users/{id}
func: app:get_user_by_id
- name: create_user
kind: http.endpoint
meta:
router: api
method: POST
path: /users
func: app:create_user
보호된 라우트
인증이 있는 일반적인 패턴:
entries:
# 퍼블릭 라우트 (인증 없음)
- name: public
kind: http.router
meta:
server: gateway
prefix: /api/public
middleware:
- cors
# 보호된 라우트
- name: protected
kind: http.router
meta:
server: gateway
prefix: /api
middleware:
- cors
- token_auth
options:
token_store: app:tokens
post_middleware:
- endpoint_firewall