惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Google DeepMind News
Google DeepMind News
人人都是产品经理
人人都是产品经理
S
Securelist
P
Proofpoint News Feed
H
Help Net Security
S
Schneier on Security
T
Tenable Blog
C
Cisco Blogs
S
Security @ Cisco Blogs
博客园 - 司徒正美
博客园 - 叶小钗
Cisco Talos Blog
Cisco Talos Blog
Google DeepMind News
Google DeepMind News
C
Cybersecurity and Infrastructure Security Agency CISA
Google Online Security Blog
Google Online Security Blog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Hacker News: Ask HN
Hacker News: Ask HN
NISL@THU
NISL@THU
云风的 BLOG
云风的 BLOG
V
Vulnerabilities – Threatpost
T
The Blog of Author Tim Ferriss
aimingoo的专栏
aimingoo的专栏
W
WeLiveSecurity
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Jina AI
Jina AI
腾讯CDC
WordPress大学
WordPress大学
Simon Willison's Weblog
Simon Willison's Weblog
Vercel News
Vercel News
小众软件
小众软件
N
Netflix TechBlog - Medium
有赞技术团队
有赞技术团队
AWS News Blog
AWS News Blog
雷峰网
雷峰网
Forbes - Security
Forbes - Security
The Hacker News
The Hacker News
博客园 - 聂微东
F
Full Disclosure
量子位
Scott Helme
Scott Helme
宝玉的分享
宝玉的分享
A
About on SuperTechFans
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Schneier on Security
Schneier on Security
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
K
Kaspersky official blog
AI
AI
SecWiki News
SecWiki News
Webroot Blog
Webroot Blog
Martin Fowler
Martin Fowler

博客园 - 张占岭

springboot~关于构造方法注入和字段注入的选择 keycloak~aud受众字段的作用及如何生成 wso2~关于workbuddy中mcp在wso2中的授权端点 k8s~避免调度资源碎片化 WEB安全~csrf介绍 WEB安全~DPoP的介绍 WEB安全~csp的介绍 什么是中间人攻击 WEB安全~xss的介绍 k8s~pod资源限制和JVM的XMX配置 关于对wso2和keycloak的token交换的调研 keycloak~实现OAuth 2.0 Token Exchange backstage~实体的介绍及它们的关系 backstage~openapi的接入与protobuf的对比 backstage~将java服务添加到backstage backstage~对接github和gitlab backstage~开始一个backstage应用 apisix~graphQL的支持 wso2几个核心项目介绍 docker~BuildKit的介绍 k8s~secret资源的使用 算法~时间戳计算两个日期是否为同天同时同分 wso2~4.5升级到4.6需要更新的数据表 backstage~Backstage的概述 springboot~jpa优雅的软删除能力 springboot~ImportBeanDefinitionRegistrar在自定义RPC框架中的使用 keycloak~深入了解DefaultSegmentedDataContainer对象解决内存泄漏 keycloak~分布式部署中会话过期清理机制 wso2~通过三方IDP的token置换wso2的token jmeter进行接口压测 Keycloak~infinispan中MergedUpdate中lifespanMs和maxIdleTimeMs wso2~添加mcp服务的注意点
apisix~OpenResty各阶段的介绍
张占岭 · 2026-07-01 · via 博客园 - 张占岭

OpenResty 基于 Nginx 的请求处理模型,在标准 Nginx 阶段上增加了 Lua 钩子。下面按实际执行顺序说明各阶段及其作用。

一、Worker 启动阶段(非请求级)

阶段 作用
init_by_lua Master 进程启动时执行一次,用于加载模块、初始化全局配置
init_worker_by_lua 每个 Worker 进程启动时执行一次,用于定时器、连接池预热等
exit_worker_by_lua Worker 退出前执行,用于清理资源

二、HTTP 请求处理阶段(按顺序)

客户端请求
    │
    ▼
┌─────────────────┐
│  1. POST_READ   │  读完请求头后
└────────┬────────┘
         ▼
┌─────────────────┐
│ 2. SERVER_REWRITE│  Server 级 rewrite(较少用)
└────────┬────────┘
         ▼
┌─────────────────┐
│  3. FIND_CONFIG │  匹配 server/location(内部阶段,一般无 Lua)
└────────┬────────┘
         ▼
┌─────────────────┐
│   4. REWRITE    │  URL 重写、路由跳转
└────────┬────────┘
         ▼
┌─────────────────┐
│   5. PREACCESS  │  限流、限连(limit_req/limit_conn 等)
└────────┬────────┘
         ▼
┌─────────────────┐
│   6. ACCESS     │  访问控制、鉴权、ACL
└────────┬────────┘
         ▼
┌─────────────────┐
│  7. CONTENT     │  生成/转发响应(proxy_pass、静态文件等)
└────────┬────────┘
         ▼
     上游响应返回
         │
         ▼
┌─────────────────┐
│ 8. HEADER_FILTER│  修改响应头(可多次执行)
└────────┬────────┘
         ▼
┌─────────────────┐
│  9. BODY_FILTER │  修改响应体(分块,可多次执行)
└────────┬────────┘
         ▼
┌─────────────────┐
│    10. LOG      │  记录访问日志
└─────────────────┘

三、各阶段详细说明

1. POST_READ

  • 时机:读完 HTTP 请求头之后
  • 典型用途:根据请求头做早期判断、限流前置逻辑
  • 特点:此时请求体通常还未读

2. SERVER_REWRITE

  • 时机:Server 块级别的 rewrite
  • 典型用途:Server 级 URL 重写(比 location rewrite 更早)

3. REWRITE

  • 时机:Location 匹配后,执行 rewrite 规则
  • 典型用途
    • URL 重写、路径跳转
    • 修改 uriargs
    • APISIX 中很多插件在此阶段运行(如你的 authz-keycloakrewrite 做 introspect)
  • Lua 钩子rewrite_by_lua*

4. PREACCESS

  • 时机:Access 之前
  • 典型用途limit_reqlimit_conn 等限流/限连

5. ACCESS

  • 时机:真正访问上游之前
  • 典型用途
    • 鉴权、IP 黑白名单
    • 决定是否允许继续处理
    • return 403/401 终止请求
  • Lua 钩子access_by_lua*
  • APISIX:多数认证/授权插件的 access 在此执行

6. CONTENT

  • 时机:生成或转发响应内容
  • 典型用途
    • proxy_pass 转发到上游
    • 返回静态文件
    • 自定义响应体
  • Lua 钩子content_by_lua*
  • 特点:这是“干活”阶段,请求会真正发到后端
  • 时机:收到上游响应头、发给客户端之前
  • 典型用途:增删改响应头(CORS、缓存头、安全头等)
  • 注意:可能被多次调用(如 subrequest)

8. BODY_FILTER

  • 时机:响应体发给客户端之前
  • 典型用途:响应体改写、压缩、加密
  • 注意:分块流式处理,可能被多次调用

9. LOG

  • 时机:请求完全结束后
  • 典型用途:访问日志、指标统计、审计
  • 特点:此时不能再修改响应,也不能 return 影响客户端

四、OpenResty 特有的 Lua 阶段

Lua 指令 对应 Nginx 阶段 说明
set_by_lua* REWRITE(变量求值时) 为 Nginx 变量赋值,禁止 I/O
rewrite_by_lua* REWRITE 可 rewrite、可读 body(需显式 read)
access_by_lua* ACCESS 鉴权、访问控制
content_by_lua* CONTENT 完全由 Lua 生成响应
header_filter_by_lua* HEADER_FILTER 改响应头
body_filter_by_lua* BODY_FILTER 改响应体
log_by_lua* LOG 日志/统计
balancer_by_lua* 选 upstream 时 动态负载均衡
ssl_certificate_by_lua* SSL 握手 动态证书

五、与 APISIX 插件的对应关系

APISIX 插件可注册不同 phase 的钩子,常见映射:

APISIX 插件方法 大致对应阶段 典型场景
rewrite REWRITE URL 重写、早期 token 校验
access ACCESS 鉴权、限流、权限校验
header_filter HEADER_FILTER 改响应头
body_filter BODY_FILTER 改响应体
log LOG 日志上报

执行顺序:同一插件内 rewriteaccess → … → log;多个插件按 priority 数值越大越先执行


六、几个实用原则

  1. 越早终止越好:鉴权失败尽量在 access 或更早返回,避免无效 upstream 调用。
  2. REWRITE vs ACCESS
    • REWRITE:改 URI、早期预处理
    • ACCESS:做“能不能访问”的判断
  3. HEADER/BODY_FILTER 不能阻断请求:只能改响应,不能 return 错误码给客户端(错误应在更早阶段处理)。
  4. LOG 阶段只做记录:不影响业务响应。
  5. set_by_lua 禁止 I/O:不能发 HTTP、不能查 Redis,只适合纯计算。