Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Cover image for Apache APISIX plugin priority, a leaky abstraction?
Apache APISIX profile imageNicolas Fränkel
Nicolas Fränkel forApache APISIX

Posted on • Originally published atblog.frankel.ch

     

Apache APISIX plugin priority, a leaky abstraction?

Apache APISIX is an API Gateway, which builds upon theOpenResty reverse-proxy to offer a plugin-based architecture. The main benefit of such an architecture is that it brings structure to the configuration of routes. It's a help at scale, when managing hundreds or thousands of routes.

In this post, I'd like to describe how plugins, priority, and phases play together and what pitfalls you must be aware of.

APISIX plugin's priority

When you configure a route with multiple plugins, Apache APISIX needs to execute them in aconsistent order so that the results are the same over time. For this reason, every APISIX plugin has aharcodedpriority. You can check a plugin priority directly in the code. For example, here's the relevant code fragment for thebasic-auth plugin:

local_M={version=0.1,priority=2520,#1type='auth',name=plugin_name,schema=schema,consumer_schema=consumer_schema}
Enter fullscreen modeExit fullscreen mode
  1. Priority is 2520

For documentation purposes, thedefault-config.yaml file lists the priority of all out-of-the-box plugins. Here's an excerpt:

plugins:-ldap-auth# priority: 2540-hmac-auth# priority: 2530-basic-auth# priority: 2520-jwt-auth# priority: 2510-key-auth# priority: 2500-consumer-restriction# priority: 2400-forward-auth# priority: 2002-opa# priority: 2001-authz-keycloak# priority: 2000#- error-log-logger              # priority: 1091-proxy-cache# priority: 1085-body-transformer# priority: 1080-proxy-mirror# priority: 1010-proxy-rewrite# priority: 1008-workflow# priority: 1006-api-breaker# priority: 1005-limit-conn# priority: 1003-limit-count# priority: 1002-limit-req# priority: 1001
Enter fullscreen modeExit fullscreen mode

Imagine a route configured withproxy-mirror andproxy-rewrite. Because of their respective priority,proxy-mirror would run beforeproxy-rewrite.

upstream:-id:1nodes:"oldapi:8081":1routes:-id:1uri:"/v1/hello*"upstream_id:1plugins:proxy-rewrite:#1-3regex_uri:["/v1(.*)","$1"]proxy-mirror:#2host:http://new.api:8082
Enter fullscreen modeExit fullscreen mode
  1. The plugin ordering in this file is not relevant
  2. proxy-mirror has priority 1010 and will execute first
  3. proxy-rewrite has priority 1008 and will run second

The above setup has an issue. For example, if we calllocalhost:9080/v1/hello, APISIX will first mirror the request, then remove the/v1 prefix. Hence, the new API receives/v1/hello instead of/hello. It's possible to override the default priority to fix it:

routes:-id:1uri:"/v1/hello*"upstream_id:1plugins:proxy-rewrite:_meta:priority:1020#1regex_uri:["/v1(.*)","$1"]proxy-mirror:host:http://new.api:8082
Enter fullscreen modeExit fullscreen mode
  1. Override the default priority

Now,proxy-rewrite has higher priority thanproxy-mirror: the former runs before the latter.

In this case, it works flawlessly; in others, it might not. Let's dive further.

APISIX phases

APISIX runs plugins not only according to their priorities but also through dedicated phases. Because APISIX builds upon OpenResty, which builds upon ngxinx, the phases are very similar to the phases of these two components.

nginx defines severalphases an HTTP request goes through:

  1. NGX_HTTP_POST_READ_PHASE
  2. NGX_HTTP_SERVER_REWRITE_PHASE
  3. NGX_HTTP_FIND_CONFIG_PHASE
  4. NGX_HTTP_REWRITE_PHASE
  5. NGX_HTTP_POST_REWRITE_PHASE
  6. NGX_HTTP_PREACCESS_PHASE
  7. NGX_HTTP_ACCESS_PHASE
  8. NGX_HTTP_POST_ACCESS_PHASE
  9. NGX_HTTP_PRECONTENT_PHASE
  10. NGX_HTTP_CONTENT_PHASE
  11. NGX_HTTP_LOG_PHASE

Each phase focuses on a task,i.e.,NGX_HTTP_ACCESS_PHASE verifies that the client is authorized to make the request.

In turn, OpenResty offers similarly named phases.

From nginx documentation:

Order of Lua Nginx Module Directives

image:77d1c09e-1a37-11e6-97ef-d9767035fc3e.png[,840,761]

Finally, here are the phases of Apache APISIX:

  1. rewrite
  2. access
  3. before_proxy
  4. header_filter
  5. body_filter
  6. log

From Apache APISIX documentation:

Order of Apache APISIX phases

We have seen two ways to order plugins: by priority and by phase. Now comes the most important rule:order by priority only works inside a phase!

For example, theredirect plugin has a priority of 900 and runs in phaserewrite; thegzip plugin has a priority of 995 and runs in phasebody_filter. Regardless of their respective priorities,redirect will happen beforegzip, becauserewrite happens beforebody_filter. Likewise, changing a priority won't "move" a plugin out of its phase.

The example above withproxy-mirror andproxy-rewrite worked because both run in therewrite phase.

The main issue is that priority is documented in theconfig-default.yaml file, while the phase is buried in the code. Worse, some plugins run across different phases. For example, let's check the proxyproxy-rewrite plugin and, more precisely, the functions definedthere:

  • local function is_new_headers_conf(headers)
  • local function check_set_headers(headers)
  • function _M.check_schema(conf)
  • function _M.rewrite(conf, ctx)

The name of therewrite() function is suspiciously similar to one of the phases above. Looking at other plugins, we see the same pattern repeat. Apache APISIX runs plugin functions with the same name as the phase.

I took the liberty of summarizing all plugins and their respective phases in a table.

PluginPhase
Generalrewriteaccessbefore_proxyheader_filterbody_filterlog
redirectX
echoXX
gzipX
real-ipX
ext-plugin-pre-reqX
ext-plugin-post-reqX
ext-plugin-post-respX
workflowX
Transformationrewriteaccessbefore_proxyheader_filterbody_filterlog
response-rewriteXX
proxy-rewriteX
grpc-transcodeXXX
grpc-webXXX
fault-injectionX
mockingX
degraphqlX
body-transformerXXX
Authenticationrewriteaccessbefore_proxyheader_filterbody_filterlog
key-authX
jwt-authX
basic-authX
authz-keycloakX
authz-casdoorX
wolf-rbacX
openid-connectX
cas-authX
hmac-authX
authz-casbinX
ldap-authX
opaX
forward-authX
Securityrewriteaccessbefore_proxyheader_filterbody_filterlog
corsXX
uri-blockerX
ua-restrictionX
referer-restrictionX
consumer-restrictionX
csrfXX
public-apiX
chaitin-wafX
Trafficrewriteaccessbefore_proxyheader_filterbody_filterlog
limit-reqX
limit-connXX
limit-countX
proxy-cache (init)XXX
proxy-cache (disk)XX
proxy-cache (memory)XXX
request-validationX
proxy-mirrorX
api-breakerXX
traffic-splitX
request-idXX
proxy-controlX
client-controlX
Observabilityrewriteaccessbefore_proxyheader_filterbody_filterlog
zipkinXXXX
skywalkingXX
opentelemetryXX
prometheus
node-status
datadogX
http-loggerXX
skywalking-loggerX
tcp-loggerX
kafka-loggerXX
rocketmq-loggerXX
udp-loggerX
clickhouse-loggerXX
syslogX
log-rotate
error-log-logger
sls-loggerX
google-cloud-loggingX
splunk-hec-loggingX
file-loggerXX
logglyXX
elasticsearch-loggerX
tencent-cloud-clsXXX
loki-loggerXX
Otherrewriteaccessbefore_proxyheader_filterbody_filterlog
serverlessX
openwhiskX
dubbo-proxyX
kafka-proxyX

Conclusion

I've detailed Apache APISIX plugin phases and priorities in this post. I've explained their relationship with one another. Icing on the cake, I documented each out-of-the-box plugin's phase(s). I hope it will prove helpful.

To go further:

Originally published atA Java Geek on December 10th, 2023

Top comments(0)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

More fromApache APISIX

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp