You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by "slow-groovin (via GitHub)" <gi...@apache.org> on 2025/05/22 06:08:36 UTC

[PR] docs: improve `plugin-develop` docs [apisix]

slow-groovin opened a new pull request, #12242:
URL: https://github.com/apache/apisix/pull/12242

   ### Description
   
   <!-- Please include a summary of the change and which issue is fixed. -->
   
   <!-- Please also include relevant motivation and context. -->
   I encountered some difficulties while following the plugin-develop documentation during development:
   1. The structure of the document was confusing and not clearly organized; it didn’t progress from basic to advanced concepts.
   2. Some critical parts were not explained. https://github.com/apache/apisix/issues/11835#issuecomment-2545125455
   
   Therefore, I restructured the overall layout, provided more detailed explanations in some sections, and added some relevant resources.
   
   
   #### Which issue(s) this PR fixes:
   <!--
   *Automatically closes linked issue when PR is merged.
   Usage: `Fixes #<issue number>`, or `Fixes (paste link of issue)`.
   -->
   Fixes #
   
   ### Checklist
   
   - [x] I have explained the need for this PR and the problem it solves
   - [x] I have explained the changes or the new features added to this PR
   - [ ] I have added tests corresponding to this change
   - [ ] I have updated the documentation to reflect this change
   - [ ] I have verified that this change is backward compatible (If not, please discuss on the [APISIX mailing list](https://github.com/apache/apisix/tree/master#community) first)
   
   <!--
   
   Note
   
   1. Mark the PR as draft until it's ready to be reviewed.
   2. Always add/update tests for any changes unless you have a good reason.
   3. Always update the documentation to reflect the changes made in the PR.
   4. Make a new commit to resolve conversations instead of `push -f`.
   5. To resolve merge conflicts, merge master instead of rebasing.
   6. Use "request review" to notify the reviewer after making changes.
   7. Only a reviewer can mark a conversation as resolved.
   
   -->
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@apisix.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] docs: improve `plugin-develop` docs [apisix]

Posted by "kayx23 (via GitHub)" <gi...@apache.org>.
kayx23 commented on PR #12242:
URL: https://github.com/apache/apisix/pull/12242#issuecomment-2903754411

   Please resolve lint errors.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@apisix.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] docs: improve `plugin-develop` docs [apisix]

Posted by "kayx23 (via GitHub)" <gi...@apache.org>.
kayx23 commented on code in PR #12242:
URL: https://github.com/apache/apisix/pull/12242#discussion_r2131850270


##########
docs/en/latest/plugin-develop.md:
##########
@@ -228,55 +159,28 @@ local metadata_schema = {
     required = {"ikey", "skey"},
 }
 
-local plugin_name = "example-plugin"
-
-local _M = {
-    version = 0.1,
-    priority = 0,        -- TODO: add a type field, may be a good idea
-    name = plugin_name,
-    schema = schema,
-    metadata_schema = metadata_schema,
-}
-```
-
-You might have noticed the key-auth plugin has `type = 'auth'` in its definition.
-When we set the type of plugin to `auth`, it means that this plugin is an authentication plugin.
-
-An authentication plugin needs to choose a consumer after execution. For example, in key-auth plugin, it calls the `consumer.attach_consumer` to attach a consumer, which is chosen via the `apikey` header.
-
-To interact with the `consumer` resource, this type of plugin needs to provide a `consumer_schema` to check the `plugins` configuration in the `consumer`.
-
-Here is the consumer configuration for key-auth plugin:
-
-```json
-{
-  "username": "Joe",
-  "plugins": {
-    "key-auth": {
-      "key": "Joe's key"
-    }
-  }
-}
+function _M.check_schema(conf, schema_type)
+    --- check schema for metadata
+    if schema_type == core.schema.TYPE_METADATA then
+        return core.schema.check(metadata_schema, conf)
+    end
+    return core.schema.check(schema, conf)
+end
 ```
 
-It will be used when you try to create a [Consumer](./admin-api.md#consumer)
-
-To validate the configuration, the plugin uses a schema like this:
+Another example, the [key-auth](https://github.com/apache/apisix/blob/master/apisix/plugins/key-auth.lua) plugin needs to provide a `consumer_schema` to check the configuration of the `plugins` attribute of the `consumer` resource in order to be used with the [Consumer](./admin-api.md#consumer) resource.
 
 ```lua

Review Comment:
   Can put the title like this:
   
   ```suggestion
   ```lua title="key-auth.lua"
   ```
   
   and remove the comment in the code block:
   
   <img width="149" alt="image" src="https://github.com/user-attachments/assets/5fffe4dc-c693-4cfb-8a7d-87b7abf4bed1" />
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@apisix.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] docs: improve `plugin-develop` docs [apisix]

Posted by "slow-groovin (via GitHub)" <gi...@apache.org>.
slow-groovin commented on code in PR #12242:
URL: https://github.com/apache/apisix/pull/12242#discussion_r2110886795


##########
docs/en/latest/plugin-develop.md:
##########
@@ -24,84 +24,58 @@ title: Plugin Develop
 This documentation is about developing plugin in Lua. For other languages,
 see [external plugin](./external-plugin.md).
 
-## where to put your plugins
+## Where to put your plugins
 
-There are two ways to add new features based on APISIX.
+Setup the `extra_lua_path` in `conf/config.yaml` to load your own code (or `extra_lua_cpath` for compiled .so or .dll file).
 
-1. modify the source of APISIX and redistribute it (not so recommended)
-1. setup the `extra_lua_path` and `extra_lua_cpath` in `conf/config.yaml` to load your own code. Your own code will be loaded instead of the builtin one with the same name, so you can use this way to override the builtin behavior if needed.
+For example, you can create a directory `/path/to/example`:
 
-For example, you can create a directory structure like this:
+```yaml
+apisix:
+    ...
+    extra_lua_path: "/path/to/example/?.lua"
+```
+
+The structure of the `example` directory should look like this:
 
 ```
 ├── example
-│   └── apisix
-│       ├── plugins
-│       │   └── 3rd-party.lua
-│       └── stream

Review Comment:
   I know nothing about the stream folder, please revise this section yourself.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@apisix.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] docs: improve `plugin-develop` docs [apisix]

Posted by "kayx23 (via GitHub)" <gi...@apache.org>.
kayx23 commented on code in PR #12242:
URL: https://github.com/apache/apisix/pull/12242#discussion_r2108618051


##########
docs/en/latest/plugin-develop.md:
##########
@@ -24,84 +24,58 @@ title: Plugin Develop
 This documentation is about developing plugin in Lua. For other languages,
 see [external plugin](./external-plugin.md).
 
-## where to put your plugins
+## Where to put your plugins
 
-There are two ways to add new features based on APISIX.
+Setup the `extra_lua_path` in `conf/config.yaml` to load your own code (or `extra_lua_cpath` for compiled .so or .dll file).

Review Comment:
   ```suggestion
   Use the `extra_lua_path` parameter in `conf/config.yaml` file to load your custom plugin code (or use `extra_lua_cpath` for compiled `.so` or `.dll` file).
   ```



##########
docs/en/latest/plugin-develop.md:
##########
@@ -24,84 +24,58 @@ title: Plugin Develop
 This documentation is about developing plugin in Lua. For other languages,
 see [external plugin](./external-plugin.md).
 
-## where to put your plugins
+## Where to put your plugins
 
-There are two ways to add new features based on APISIX.
+Setup the `extra_lua_path` in `conf/config.yaml` to load your own code (or `extra_lua_cpath` for compiled .so or .dll file).
 
-1. modify the source of APISIX and redistribute it (not so recommended)
-1. setup the `extra_lua_path` and `extra_lua_cpath` in `conf/config.yaml` to load your own code. Your own code will be loaded instead of the builtin one with the same name, so you can use this way to override the builtin behavior if needed.
+For example, you can create a directory `/path/to/example`:
 
-For example, you can create a directory structure like this:
+```yaml
+apisix:
+    ...
+    extra_lua_path: "/path/to/example/?.lua"
+```
+
+The structure of the `example` directory should look like this:
 
 ```
 ├── example
-│   └── apisix
-│       ├── plugins
-│       │   └── 3rd-party.lua
-│       └── stream
-│           └── plugins
-│               └── 3rd-party.lua
+│   └── apisix
+│       └── plugins
+│           └── 3rd-party.lua
 ```
 
 :::note
 
-If you need to customize the directory of plugin, please create a subdirectory of `/apisix/plugins` under this directory.
+The directory (`/path/to/example`) must contain the `/apisix/plugins` subdirectory.
 
 :::
 
-Then add this configuration into your `conf/config.yaml`:
+## Enable the plugin
 
-```yaml
-apisix:
-    ...
-    extra_lua_path: "/path/to/example/?.lua"
-```
-
-Now using `require "apisix.plugins.3rd-party"` will load your plugin, just like `require "apisix.plugins.jwt-auth"` will load the `jwt-auth` plugin.
-
-Sometimes you may want to override a method instead of a whole file. In this case, you can configure `lua_module_hook` in `conf/config.yaml`
-to introduce your hook.
-
-Assumed your configuration is:
+To enable your custom plugin, add the plugin list to `conf/config.yaml` and append your plugin name. For instance:
 
 ```yaml
-apisix:
-    ...
-    extra_lua_path: "/path/to/example/?.lua"
-    lua_module_hook: "my_hook"
+plugins: # See `conf/config.yaml.example` for an example
+  - ... # Add existing plugins
+  - your-plugin # Add your custom plugin name (name is the plugin name defined in the code)
 ```
 
-The `example/my_hook.lua` will be loaded when APISIX starts, and you can use this hook to replace a method in APISIX.
-The example of [my_hook.lua](https://github.com/apache/apisix/blob/master/example/my_hook.lua) can be found under the `example` directory of this project.
+:::warning
 
-## check dependencies
+In particular, most APISIX plugins are enabled by default when the plugins field configuration is not defined (The default enabled plugins can be found in [apisix/cli/config.lua](https://github.com/apache/apisix/blob/master/apisix/cli/config.lua)).
 
-if you have dependencies on external libraries, check the dependent items. if your plugin needs to use shared memory, it
-needs to declare via [customizing Nginx configuration](./customize-nginx-configuration.md), for example :
+Once the plugins configuration is defined in `conf/config.yaml`, the new plugins list will replace the default configuration instead of merging. Therefore, when defining the `plugins` field, make sure to include the built-in plugins that are being used. To maintain consistency with the default behavior, you can include all the default enabled plugins defined in **apisix/cli/config.lua**.

Review Comment:
   ```suggestion
   Once the plugins configuration is defined in `conf/config.yaml`, the new plugins list will replace the default configuration instead of merging. Therefore, when defining the `plugins` field, make sure to include the built-in plugins that are being used. To maintain consistency with the default behavior, you can include all the default enabled plugins defined in `apisix/cli/config.lua`.
   ```



##########
docs/en/latest/plugin-develop.md:
##########
@@ -437,7 +246,119 @@ function _M.access(conf, ctx)
 end
 ```
 
-## register public API
+### Others
+
+If your plugin has a new code directory of its own, and you need to redistribute it with the APISIX source code, you will need to modify the `Makefile` to create directory, such as:
+
+```
+$(INSTALL) -d $(INST_LUADIR)/apisix/plugins/skywalking
+$(INSTALL) apisix/plugins/skywalking/*.lua $(INST_LUADIR)/apisix/plugins/skywalking/
+```
+
+There are other fields in the `_M` which affect the plugin's behavior.
+
+```lua
+local _M = {
+    ...
+    type = 'auth',
+    run_policy = 'prefer_route',
+}
+```
+
+`run_policy` field can be used to control the behavior of the plugin execution.
+When this field set to `prefer_route`, and the plugin has been configured both
+in the global and at the route level, only the route level one will take effect.
+
+`type` field is required to be set to `auth` if your plugin needs to work with consumer.
+
+## Load plugin and replace plugin
+
+Using `require "apisix.plugins.3rd-party"` will load your plugin, just like `require "apisix.plugins.jwt-auth"` will load the `jwt-auth` plugin.
+
+Sometimes you may want to override a method instead of a whole file. In this case, you can configure `lua_module_hook` in `conf/config.yaml`
+to introduce your hook.
+
+Assumed your configuration is:

Review Comment:
   ```suggestion
   Assume that your configuration is as follows:
   ```



##########
docs/en/latest/plugin-develop.md:
##########
@@ -437,7 +246,119 @@ function _M.access(conf, ctx)
 end
 ```
 
-## register public API
+### Others
+
+If your plugin has a new code directory of its own, and you need to redistribute it with the APISIX source code, you will need to modify the `Makefile` to create directory, such as:
+
+```
+$(INSTALL) -d $(INST_LUADIR)/apisix/plugins/skywalking
+$(INSTALL) apisix/plugins/skywalking/*.lua $(INST_LUADIR)/apisix/plugins/skywalking/
+```
+
+There are other fields in the `_M` which affect the plugin's behavior.
+
+```lua
+local _M = {
+    ...
+    type = 'auth',
+    run_policy = 'prefer_route',
+}
+```
+
+`run_policy` field can be used to control the behavior of the plugin execution.
+When this field set to `prefer_route`, and the plugin has been configured both
+in the global and at the route level, only the route level one will take effect.
+
+`type` field is required to be set to `auth` if your plugin needs to work with consumer.
+
+## Load plugin and replace plugin
+
+Using `require "apisix.plugins.3rd-party"` will load your plugin, just like `require "apisix.plugins.jwt-auth"` will load the `jwt-auth` plugin.
+
+Sometimes you may want to override a method instead of a whole file. In this case, you can configure `lua_module_hook` in `conf/config.yaml`
+to introduce your hook.
+
+Assumed your configuration is:
+
+```yaml
+apisix:
+    ...
+    extra_lua_path: "/path/to/example/?.lua"
+    lua_module_hook: "my_hook"
+```
+
+The `example/my_hook.lua` will be loaded when APISIX starts, and you can use this hook to replace a method in APISIX.
+The example of [my_hook.lua](https://github.com/apache/apisix/blob/master/example/my_hook.lua) can be found under the `example` directory of this project.
+
+## Check external dependencies
+
+If you have dependencies on external libraries, check the dependent items. if your plugin needs to use shared memory, it
+needs to declare via [customizing Nginx configuration](./customize-nginx-configuration.md), for example :
+
+```yaml
+# put this in config.yaml:
+nginx_config:
+    http_configuration_snippet: |
+        # for openid-connect plugin
+        lua_shared_dict discovery             1m; # cache for discovery metadata documents
+        lua_shared_dict jwks                  1m; # cache for JWKs
+        lua_shared_dict introspection        10m; # cache for JWT verification results
+```
+
+The plugin itself provides the init method. It is convenient for plugins to perform some initialization after
+the plugin is loaded. If you need to clean up the initialization, you can put it in the corresponding destroy method.
+
+Note : if the dependency of some plugin needs to be initialized when Nginx start, you may need to add logic to the initialization
+method "http_init" in the file __apisix/init.lua__, and you may need to add some processing on generated part of Nginx
+configuration file in __apisix/cli/ngx_tpl.lua__ file. But it is easy to have an impact on the overall situation according to the
+existing plugin mechanism, **we do not recommend this unless you have a complete grasp of the code**.
+
+## Encrypted storage fields
+
+::: note
+APISIX version is not less than 3.1
+:::
+
+Some plugins require parameters to be stored encrypted, such as the `password` parameter of the `basic-auth` plugin. This plugin needs to specify in the `schema` which parameters need to be stored encrypted.
+
+```lua
+encrypt_fields = {"password"}
+```
+
+If it is a nested parameter, such as the `clickhouse.password` parameter of the `error-log-logger` plugin, it needs to be separated by `.`:
+
+```lua
+encrypt_fields = {"clickhouse.password"}
+```
+
+Currently not supported yet:
+
+1. more than two levels of nesting
+2. fields in arrays
+
+Parameters can be stored encrypted by specifying `encrypt_fields = {"password"}` in the `schema`. APISIX will provide the following functionality.
+
+- When adding and updating resources via the `Admin API`, APISIX automatically encrypts the parameters declared in `encrypt_fields` and stores them in etcd
+- When fetching resources via the `Admin API` and when running the plugin, APISIX automatically decrypts the parameters declared in `encrypt_fields`

Review Comment:
   <img width="194" alt="image" src="https://github.com/user-attachments/assets/fb0afb82-5dfa-451a-9752-e80e4dd53a26" />
   
   No need to put Admin API in line.



##########
docs/en/latest/plugin-develop.md:
##########
@@ -437,7 +246,119 @@ function _M.access(conf, ctx)
 end
 ```
 
-## register public API
+### Others
+
+If your plugin has a new code directory of its own, and you need to redistribute it with the APISIX source code, you will need to modify the `Makefile` to create directory, such as:
+
+```
+$(INSTALL) -d $(INST_LUADIR)/apisix/plugins/skywalking
+$(INSTALL) apisix/plugins/skywalking/*.lua $(INST_LUADIR)/apisix/plugins/skywalking/
+```
+
+There are other fields in the `_M` which affect the plugin's behavior.
+
+```lua
+local _M = {
+    ...
+    type = 'auth',
+    run_policy = 'prefer_route',
+}
+```
+
+`run_policy` field can be used to control the behavior of the plugin execution.
+When this field set to `prefer_route`, and the plugin has been configured both
+in the global and at the route level, only the route level one will take effect.
+
+`type` field is required to be set to `auth` if your plugin needs to work with consumer.
+
+## Load plugin and replace plugin
+
+Using `require "apisix.plugins.3rd-party"` will load your plugin, just like `require "apisix.plugins.jwt-auth"` will load the `jwt-auth` plugin.
+
+Sometimes you may want to override a method instead of a whole file. In this case, you can configure `lua_module_hook` in `conf/config.yaml`
+to introduce your hook.
+
+Assumed your configuration is:
+
+```yaml
+apisix:
+    ...
+    extra_lua_path: "/path/to/example/?.lua"
+    lua_module_hook: "my_hook"
+```
+
+The `example/my_hook.lua` will be loaded when APISIX starts, and you can use this hook to replace a method in APISIX.
+The example of [my_hook.lua](https://github.com/apache/apisix/blob/master/example/my_hook.lua) can be found under the `example` directory of this project.
+
+## Check external dependencies
+
+If you have dependencies on external libraries, check the dependent items. if your plugin needs to use shared memory, it
+needs to declare via [customizing Nginx configuration](./customize-nginx-configuration.md), for example :
+
+```yaml
+# put this in config.yaml:
+nginx_config:
+    http_configuration_snippet: |
+        # for openid-connect plugin
+        lua_shared_dict discovery             1m; # cache for discovery metadata documents
+        lua_shared_dict jwks                  1m; # cache for JWKs
+        lua_shared_dict introspection        10m; # cache for JWT verification results
+```
+
+The plugin itself provides the init method. It is convenient for plugins to perform some initialization after
+the plugin is loaded. If you need to clean up the initialization, you can put it in the corresponding destroy method.
+
+Note : if the dependency of some plugin needs to be initialized when Nginx start, you may need to add logic to the initialization
+method "http_init" in the file __apisix/init.lua__, and you may need to add some processing on generated part of Nginx
+configuration file in __apisix/cli/ngx_tpl.lua__ file. But it is easy to have an impact on the overall situation according to the
+existing plugin mechanism, **we do not recommend this unless you have a complete grasp of the code**.
+
+## Encrypted storage fields
+
+::: note
+APISIX version is not less than 3.1
+:::

Review Comment:
   <img width="281" alt="image" src="https://github.com/user-attachments/assets/36039c9d-3929-4825-9f40-c795fbf08758" />
   
   I think this sentence can be removed since the doc (next) will be released when 3.13 is out. 3.1. is way back in the days already.
   
   If you think this note is still relevant, there is a formatting issue: it should be `:::note` (without the space); otherwise the admonition will not be rendered properly.



##########
docs/en/latest/plugin-develop.md:
##########
@@ -286,59 +178,9 @@ function _M.check_schema(conf, schema_type)
 end
 ```
 
-```lua
--- example-plugin
-function _M.check_schema(conf, schema_type)
-    return core.schema.check(schema, conf)
-end
-```
-
-### encrypted storage fields
-
-Specify the parameters to be stored encrypted. (Requires APISIX version >= 3.1.0)
-
-Some plugins require parameters to be stored encrypted, such as the `password` parameter of the `basic-auth` plugin. This plugin needs to specify in the `schema` which parameters need to be stored encrypted.
-
-```lua
-encrypt_fields = {"password"}
-```
-
-If it is a nested parameter, such as the `clickhouse.password` parameter of the `error-log-logger` plugin, it needs to be separated by `.`:
-
-```lua
-encrypt_fields = {"clickhouse.password"}
-```
-
-Currently not supported yet:
-
-1. more than two levels of nesting
-2. fields in arrays
-
-Parameters can be stored encrypted by specifying `encrypt_fields = {"password"}` in the `schema`. APISIX will provide the following functionality.
-
-- When adding and updating resources via the `Admin API`, APISIX automatically encrypts the parameters declared in `encrypt_fields` and stores them in etcd
-- When fetching resources via the `Admin API` and when running the plugin, APISIX automatically decrypts the parameters declared in `encrypt_fields`
-
-How to enable this feature?
-
-Enable `data_encryption` in `config.yaml`.
-
-```yaml
-apisix:
-    data_encryption:
-        enable: true
-        keyring:
-            - edd1c9f0985e76a2
-            - qeddd145sfvddff4
-```
-
-APISIX will try to decrypt the data with keys in the order of the keys in the keyring (only for parameters declared in `encrypt_fields`). If the decryption fails, the next key will be tried until the decryption succeeds.
-
-If none of the keys in `keyring` can decrypt the data, the original data is used.
-
-## choose phase to run
+### Choose phase to run
 
-Determine which phase to run, generally access or rewrite. If you don't know the [OpenResty lifecycle](https://github.com/openresty/lua-nginx-module/blob/master/README.markdown#directives), it's
+Determine which [phase](./terminology/plugin.md#plugins-execution-lifecycle) to run, generally access or rewrite. If you don't know the [OpenResty lifecycle](https://github.com/openresty/lua-nginx-module/blob/master/README.markdown#directives), it's
 recommended to know it in advance. For example key-auth is an authentication plugin, thus the authentication should be completed

Review Comment:
   ```suggestion
   recommended to learn about it in advance. For example `key-auth` is an authentication plugin, thus the authentication should be completed
   ```



##########
docs/en/latest/plugin-develop.md:
##########
@@ -24,84 +24,58 @@ title: Plugin Develop
 This documentation is about developing plugin in Lua. For other languages,
 see [external plugin](./external-plugin.md).
 
-## where to put your plugins
+## Where to put your plugins
 
-There are two ways to add new features based on APISIX.
+Setup the `extra_lua_path` in `conf/config.yaml` to load your own code (or `extra_lua_cpath` for compiled .so or .dll file).
 
-1. modify the source of APISIX and redistribute it (not so recommended)
-1. setup the `extra_lua_path` and `extra_lua_cpath` in `conf/config.yaml` to load your own code. Your own code will be loaded instead of the builtin one with the same name, so you can use this way to override the builtin behavior if needed.
+For example, you can create a directory `/path/to/example`:
 
-For example, you can create a directory structure like this:
+```yaml
+apisix:
+    ...
+    extra_lua_path: "/path/to/example/?.lua"
+```
+
+The structure of the `example` directory should look like this:
 
 ```
 ├── example
-│   └── apisix
-│       ├── plugins
-│       │   └── 3rd-party.lua
-│       └── stream
-│           └── plugins
-│               └── 3rd-party.lua
+│   └── apisix
+│       └── plugins
+│           └── 3rd-party.lua
 ```
 
 :::note
 
-If you need to customize the directory of plugin, please create a subdirectory of `/apisix/plugins` under this directory.
+The directory (`/path/to/example`) must contain the `/apisix/plugins` subdirectory.

Review Comment:
   How about
   
   ```suggestion
   The directory (`/path/to/example`) must contain the `/apisix/plugins` subdirectory for L7 plugins.
   ```



##########
docs/en/latest/plugin-develop.md:
##########
@@ -24,84 +24,58 @@ title: Plugin Develop
 This documentation is about developing plugin in Lua. For other languages,
 see [external plugin](./external-plugin.md).
 
-## where to put your plugins
+## Where to put your plugins
 
-There are two ways to add new features based on APISIX.
+Setup the `extra_lua_path` in `conf/config.yaml` to load your own code (or `extra_lua_cpath` for compiled .so or .dll file).
 
-1. modify the source of APISIX and redistribute it (not so recommended)
-1. setup the `extra_lua_path` and `extra_lua_cpath` in `conf/config.yaml` to load your own code. Your own code will be loaded instead of the builtin one with the same name, so you can use this way to override the builtin behavior if needed.
+For example, you can create a directory `/path/to/example`:
 
-For example, you can create a directory structure like this:
+```yaml
+apisix:
+    ...
+    extra_lua_path: "/path/to/example/?.lua"
+```
+
+The structure of the `example` directory should look like this:
 
 ```
 ├── example
-│   └── apisix
-│       ├── plugins
-│       │   └── 3rd-party.lua
-│       └── stream
-│           └── plugins
-│               └── 3rd-party.lua
+│   └── apisix
+│       └── plugins
+│           └── 3rd-party.lua
 ```
 
 :::note
 
-If you need to customize the directory of plugin, please create a subdirectory of `/apisix/plugins` under this directory.
+The directory (`/path/to/example`) must contain the `/apisix/plugins` subdirectory.
 
 :::
 
-Then add this configuration into your `conf/config.yaml`:
+## Enable the plugin
 
-```yaml
-apisix:
-    ...
-    extra_lua_path: "/path/to/example/?.lua"
-```
-
-Now using `require "apisix.plugins.3rd-party"` will load your plugin, just like `require "apisix.plugins.jwt-auth"` will load the `jwt-auth` plugin.
-
-Sometimes you may want to override a method instead of a whole file. In this case, you can configure `lua_module_hook` in `conf/config.yaml`
-to introduce your hook.
-
-Assumed your configuration is:
+To enable your custom plugin, add the plugin list to `conf/config.yaml` and append your plugin name. For instance:
 
 ```yaml
-apisix:
-    ...
-    extra_lua_path: "/path/to/example/?.lua"
-    lua_module_hook: "my_hook"
+plugins: # See `conf/config.yaml.example` for an example
+  - ... # Add existing plugins
+  - your-plugin # Add your custom plugin name (name is the plugin name defined in the code)
 ```
 
-The `example/my_hook.lua` will be loaded when APISIX starts, and you can use this hook to replace a method in APISIX.
-The example of [my_hook.lua](https://github.com/apache/apisix/blob/master/example/my_hook.lua) can be found under the `example` directory of this project.
+:::warning
 
-## check dependencies
+In particular, most APISIX plugins are enabled by default when the plugins field configuration is not defined (The default enabled plugins can be found in [apisix/cli/config.lua](https://github.com/apache/apisix/blob/master/apisix/cli/config.lua)).
 
-if you have dependencies on external libraries, check the dependent items. if your plugin needs to use shared memory, it
-needs to declare via [customizing Nginx configuration](./customize-nginx-configuration.md), for example :
+Once the plugins configuration is defined in `conf/config.yaml`, the new plugins list will replace the default configuration instead of merging. Therefore, when defining the `plugins` field, make sure to include the built-in plugins that are being used. To maintain consistency with the default behavior, you can include all the default enabled plugins defined in **apisix/cli/config.lua**.
 
-```yaml
-# put this in config.yaml:
-nginx_config:
-    http_configuration_snippet: |
-        # for openid-connect plugin
-        lua_shared_dict discovery             1m; # cache for discovery metadata documents
-        lua_shared_dict jwks                  1m; # cache for JWKs
-        lua_shared_dict introspection        10m; # cache for JWT verification results
-```
+:::
 
-The plugin itself provides the init method. It is convenient for plugins to perform some initialization after
-the plugin is loaded. If you need to clean up the initialization, you can put it in the corresponding destroy method.
+## Writing plugins
 
-Note : if the dependency of some plugin needs to be initialized when Nginx start, you may need to add logic to the initialization
-method "http_init" in the file __apisix/init.lua__, and you may need to add some processing on generated part of Nginx
-configuration file in __apisix/cli/ngx_tpl.lua__ file. But it is easy to have an impact on the overall situation according to the
-existing plugin mechanism, **we do not recommend this unless you have a complete grasp of the code**.
+The [example-plugin](https://github.com/apache/apisix/blob/master/apisix/plugins/example-plugin.lua) plugin (local location: **apisix/plugins/example-plugin.lua**) provides an example.

Review Comment:
   ```suggestion
   The [`example-plugin`](https://github.com/apache/apisix/blob/master/apisix/plugins/example-plugin.lua) plugin in this repo provides an example.
   ```



##########
docs/en/latest/plugin-develop.md:
##########
@@ -24,84 +24,58 @@ title: Plugin Develop
 This documentation is about developing plugin in Lua. For other languages,
 see [external plugin](./external-plugin.md).
 
-## where to put your plugins
+## Where to put your plugins
 
-There are two ways to add new features based on APISIX.
+Setup the `extra_lua_path` in `conf/config.yaml` to load your own code (or `extra_lua_cpath` for compiled .so or .dll file).
 
-1. modify the source of APISIX and redistribute it (not so recommended)
-1. setup the `extra_lua_path` and `extra_lua_cpath` in `conf/config.yaml` to load your own code. Your own code will be loaded instead of the builtin one with the same name, so you can use this way to override the builtin behavior if needed.
+For example, you can create a directory `/path/to/example`:
 
-For example, you can create a directory structure like this:
+```yaml
+apisix:
+    ...
+    extra_lua_path: "/path/to/example/?.lua"
+```
+
+The structure of the `example` directory should look like this:
 
 ```
 ├── example
-│   └── apisix
-│       ├── plugins
-│       │   └── 3rd-party.lua
-│       └── stream

Review Comment:
   Maybe leave the `stream` and mention in text that if you would like to load a custom stream (L4) plugin, this is how it should structured. My concern is that once the stream folder is removed, it is not documented anywhere else.



##########
docs/en/latest/plugin-develop.md:
##########
@@ -437,7 +246,119 @@ function _M.access(conf, ctx)
 end
 ```
 
-## register public API
+### Others
+
+If your plugin has a new code directory of its own, and you need to redistribute it with the APISIX source code, you will need to modify the `Makefile` to create directory, such as:
+
+```
+$(INSTALL) -d $(INST_LUADIR)/apisix/plugins/skywalking
+$(INSTALL) apisix/plugins/skywalking/*.lua $(INST_LUADIR)/apisix/plugins/skywalking/
+```
+
+There are other fields in the `_M` which affect the plugin's behavior.
+
+```lua
+local _M = {
+    ...
+    type = 'auth',
+    run_policy = 'prefer_route',
+}
+```
+
+`run_policy` field can be used to control the behavior of the plugin execution.
+When this field set to `prefer_route`, and the plugin has been configured both
+in the global and at the route level, only the route level one will take effect.
+
+`type` field is required to be set to `auth` if your plugin needs to work with consumer.
+
+## Load plugin and replace plugin
+
+Using `require "apisix.plugins.3rd-party"` will load your plugin, just like `require "apisix.plugins.jwt-auth"` will load the `jwt-auth` plugin.
+
+Sometimes you may want to override a method instead of a whole file. In this case, you can configure `lua_module_hook` in `conf/config.yaml`
+to introduce your hook.
+
+Assumed your configuration is:
+
+```yaml
+apisix:
+    ...
+    extra_lua_path: "/path/to/example/?.lua"
+    lua_module_hook: "my_hook"
+```
+
+The `example/my_hook.lua` will be loaded when APISIX starts, and you can use this hook to replace a method in APISIX.
+The example of [my_hook.lua](https://github.com/apache/apisix/blob/master/example/my_hook.lua) can be found under the `example` directory of this project.
+
+## Check external dependencies
+
+If you have dependencies on external libraries, check the dependent items. if your plugin needs to use shared memory, it
+needs to declare via [customizing Nginx configuration](./customize-nginx-configuration.md), for example :
+
+```yaml
+# put this in config.yaml:
+nginx_config:
+    http_configuration_snippet: |
+        # for openid-connect plugin
+        lua_shared_dict discovery             1m; # cache for discovery metadata documents
+        lua_shared_dict jwks                  1m; # cache for JWKs
+        lua_shared_dict introspection        10m; # cache for JWT verification results
+```
+
+The plugin itself provides the init method. It is convenient for plugins to perform some initialization after
+the plugin is loaded. If you need to clean up the initialization, you can put it in the corresponding destroy method.
+
+Note : if the dependency of some plugin needs to be initialized when Nginx start, you may need to add logic to the initialization
+method "http_init" in the file __apisix/init.lua__, and you may need to add some processing on generated part of Nginx
+configuration file in __apisix/cli/ngx_tpl.lua__ file. But it is easy to have an impact on the overall situation according to the
+existing plugin mechanism, **we do not recommend this unless you have a complete grasp of the code**.
+
+## Encrypted storage fields
+
+::: note
+APISIX version is not less than 3.1
+:::
+
+Some plugins require parameters to be stored encrypted, such as the `password` parameter of the `basic-auth` plugin. This plugin needs to specify in the `schema` which parameters need to be stored encrypted.
+
+```lua
+encrypt_fields = {"password"}
+```
+
+If it is a nested parameter, such as the `clickhouse.password` parameter of the `error-log-logger` plugin, it needs to be separated by `.`:
+
+```lua
+encrypt_fields = {"clickhouse.password"}
+```
+
+Currently not supported yet:
+
+1. more than two levels of nesting
+2. fields in arrays
+
+Parameters can be stored encrypted by specifying `encrypt_fields = {"password"}` in the `schema`. APISIX will provide the following functionality.
+
+- When adding and updating resources via the `Admin API`, APISIX automatically encrypts the parameters declared in `encrypt_fields` and stores them in etcd
+- When fetching resources via the `Admin API` and when running the plugin, APISIX automatically decrypts the parameters declared in `encrypt_fields`
+
+How to enable this feature?
+
+Enable `data_encryption` in `config.yaml`.

Review Comment:
   This feature is enabled by default now
   
   <img width="582" alt="image" src="https://github.com/user-attachments/assets/a57a78c4-e91b-47c6-a47c-e61dc1f06c00" />
   



##########
docs/en/latest/plugin-develop.md:
##########
@@ -437,7 +246,119 @@ function _M.access(conf, ctx)
 end
 ```
 
-## register public API
+### Others
+
+If your plugin has a new code directory of its own, and you need to redistribute it with the APISIX source code, you will need to modify the `Makefile` to create directory, such as:
+
+```
+$(INSTALL) -d $(INST_LUADIR)/apisix/plugins/skywalking
+$(INSTALL) apisix/plugins/skywalking/*.lua $(INST_LUADIR)/apisix/plugins/skywalking/
+```
+
+There are other fields in the `_M` which affect the plugin's behavior.
+
+```lua
+local _M = {
+    ...
+    type = 'auth',
+    run_policy = 'prefer_route',
+}
+```
+
+`run_policy` field can be used to control the behavior of the plugin execution.
+When this field set to `prefer_route`, and the plugin has been configured both
+in the global and at the route level, only the route level one will take effect.
+
+`type` field is required to be set to `auth` if your plugin needs to work with consumer.
+
+## Load plugin and replace plugin
+
+Using `require "apisix.plugins.3rd-party"` will load your plugin, just like `require "apisix.plugins.jwt-auth"` will load the `jwt-auth` plugin.
+
+Sometimes you may want to override a method instead of a whole file. In this case, you can configure `lua_module_hook` in `conf/config.yaml`
+to introduce your hook.
+
+Assumed your configuration is:
+
+```yaml
+apisix:
+    ...
+    extra_lua_path: "/path/to/example/?.lua"
+    lua_module_hook: "my_hook"
+```
+
+The `example/my_hook.lua` will be loaded when APISIX starts, and you can use this hook to replace a method in APISIX.
+The example of [my_hook.lua](https://github.com/apache/apisix/blob/master/example/my_hook.lua) can be found under the `example` directory of this project.
+
+## Check external dependencies
+
+If you have dependencies on external libraries, check the dependent items. if your plugin needs to use shared memory, it

Review Comment:
   ```suggestion
   If you have dependencies on external libraries, check the dependent items. If your plugin needs to use shared memory, it
   ```



##########
docs/en/latest/plugin-develop.md:
##########
@@ -437,7 +246,119 @@ function _M.access(conf, ctx)
 end
 ```
 
-## register public API
+### Others
+
+If your plugin has a new code directory of its own, and you need to redistribute it with the APISIX source code, you will need to modify the `Makefile` to create directory, such as:
+
+```
+$(INSTALL) -d $(INST_LUADIR)/apisix/plugins/skywalking
+$(INSTALL) apisix/plugins/skywalking/*.lua $(INST_LUADIR)/apisix/plugins/skywalking/
+```
+
+There are other fields in the `_M` which affect the plugin's behavior.
+
+```lua
+local _M = {
+    ...
+    type = 'auth',
+    run_policy = 'prefer_route',
+}
+```
+
+`run_policy` field can be used to control the behavior of the plugin execution.
+When this field set to `prefer_route`, and the plugin has been configured both
+in the global and at the route level, only the route level one will take effect.
+
+`type` field is required to be set to `auth` if your plugin needs to work with consumer.
+
+## Load plugin and replace plugin
+
+Using `require "apisix.plugins.3rd-party"` will load your plugin, just like `require "apisix.plugins.jwt-auth"` will load the `jwt-auth` plugin.
+
+Sometimes you may want to override a method instead of a whole file. In this case, you can configure `lua_module_hook` in `conf/config.yaml`
+to introduce your hook.
+
+Assumed your configuration is:
+
+```yaml
+apisix:
+    ...
+    extra_lua_path: "/path/to/example/?.lua"
+    lua_module_hook: "my_hook"
+```
+
+The `example/my_hook.lua` will be loaded when APISIX starts, and you can use this hook to replace a method in APISIX.
+The example of [my_hook.lua](https://github.com/apache/apisix/blob/master/example/my_hook.lua) can be found under the `example` directory of this project.
+
+## Check external dependencies
+
+If you have dependencies on external libraries, check the dependent items. if your plugin needs to use shared memory, it
+needs to declare via [customizing Nginx configuration](./customize-nginx-configuration.md), for example :
+
+```yaml
+# put this in config.yaml:
+nginx_config:
+    http_configuration_snippet: |
+        # for openid-connect plugin
+        lua_shared_dict discovery             1m; # cache for discovery metadata documents
+        lua_shared_dict jwks                  1m; # cache for JWKs
+        lua_shared_dict introspection        10m; # cache for JWT verification results
+```
+
+The plugin itself provides the init method. It is convenient for plugins to perform some initialization after
+the plugin is loaded. If you need to clean up the initialization, you can put it in the corresponding destroy method.
+
+Note : if the dependency of some plugin needs to be initialized when Nginx start, you may need to add logic to the initialization
+method "http_init" in the file __apisix/init.lua__, and you may need to add some processing on generated part of Nginx
+configuration file in __apisix/cli/ngx_tpl.lua__ file. But it is easy to have an impact on the overall situation according to the

Review Comment:
   Put the paths above in inline code, instead of bolding them?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@apisix.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] docs: improve `plugin-develop` docs [apisix]

Posted by "slow-groovin (via GitHub)" <gi...@apache.org>.
slow-groovin commented on code in PR #12242:
URL: https://github.com/apache/apisix/pull/12242#discussion_r2134579294


##########
docs/en/latest/plugin-develop.md:
##########
@@ -228,55 +159,28 @@ local metadata_schema = {
     required = {"ikey", "skey"},
 }
 
-local plugin_name = "example-plugin"
-
-local _M = {
-    version = 0.1,
-    priority = 0,        -- TODO: add a type field, may be a good idea
-    name = plugin_name,
-    schema = schema,
-    metadata_schema = metadata_schema,
-}
-```
-
-You might have noticed the key-auth plugin has `type = 'auth'` in its definition.
-When we set the type of plugin to `auth`, it means that this plugin is an authentication plugin.
-
-An authentication plugin needs to choose a consumer after execution. For example, in key-auth plugin, it calls the `consumer.attach_consumer` to attach a consumer, which is chosen via the `apikey` header.
-
-To interact with the `consumer` resource, this type of plugin needs to provide a `consumer_schema` to check the `plugins` configuration in the `consumer`.
-
-Here is the consumer configuration for key-auth plugin:
-
-```json
-{
-  "username": "Joe",
-  "plugins": {
-    "key-auth": {
-      "key": "Joe's key"
-    }
-  }
-}
+function _M.check_schema(conf, schema_type)
+    --- check schema for metadata
+    if schema_type == core.schema.TYPE_METADATA then
+        return core.schema.check(metadata_schema, conf)
+    end
+    return core.schema.check(schema, conf)
+end
 ```
 
-It will be used when you try to create a [Consumer](./admin-api.md#consumer)
-
-To validate the configuration, the plugin uses a schema like this:
+Another example, the [key-auth](https://github.com/apache/apisix/blob/master/apisix/plugins/key-auth.lua) plugin needs to provide a `consumer_schema` to check the configuration of the `plugins` attribute of the `consumer` resource in order to be used with the [Consumer](./admin-api.md#consumer) resource.
 
 ```lua

Review Comment:
   The missing parts have been adddressed.
   
   Except for the stream plugin part(including the descriptions of L4 and L7). Since I can only find related content in the [blogs](https://apisix.apache.org/search/?q=L4), I thought it's better that the maintainers provide detailed content for this part.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@apisix.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] docs: improve `plugin-develop` docs [apisix]

Posted by "kayx23 (via GitHub)" <gi...@apache.org>.
kayx23 commented on code in PR #12242:
URL: https://github.com/apache/apisix/pull/12242#discussion_r2122635738


##########
docs/en/latest/plugin-develop.md:
##########
@@ -205,18 +129,25 @@ local schema = {
 
 The schema defines a non-negative number `i`, a string `s`, a non-empty array of `t`, and `ip` / `port`. Only `i` is required.
 
-At the same time, we need to implement the __check_schema(conf)__ method to complete the specification verification.
+At the same time, we need to implement the __check_schema(conf, schema_type)__ method to complete the specification verification.
 
 ```lua
 function _M.check_schema(conf, schema_type)
+    if schema_type == core.schema.TYPE_METADATA then
+        return core.schema.check(metadata_schema, conf)
+    end
     return core.schema.check(schema, conf)
 end
 ```
 
+:::note
+
 Note: the project has provided the public method "__core.schema.check__", which can be used directly to complete JSON
 verification.
 
-In addition, if the plugin needs to use some metadata, we can define the plugin `metadata_schema`, and then we can dynamically manage these metadata through the `Admin API`. Example:
+:::
+
+The input parameter **schema_type** is used to distinguish between different schemas types. For example, many plugins need to use some [metadata](./terminology/plugin-metadata.md), so they define the plugin's `metadata_schema`. Another example, the [key-auth](https://github.com/apache/apisix/blob/master/apisix/plugins/key-auth.lua) plugin needs to provide a `consumer_schema` to check the configuration of the `plugins` attribute of the `consumer` resource in order to be used with the [Consumer](./admin-api.md#consumer) resource.

Review Comment:
   A couple issues regarding this rearrangement:
   
   1. it is easier to read if this info is moved down to its corresponding content:
   
   <img width="894" alt="image" src="https://github.com/user-attachments/assets/5e5ec305-2ca8-4cda-bf59-281af20ea9f2" />
   
   2. Missing information - `consumer_schema` was removed in this PR. Why?
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@apisix.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] docs: improve `plugin-develop` docs [apisix]

Posted by "slow-groovin (via GitHub)" <gi...@apache.org>.
slow-groovin commented on code in PR #12242:
URL: https://github.com/apache/apisix/pull/12242#discussion_r2123237839


##########
docs/en/latest/plugin-develop.md:
##########
@@ -205,18 +129,25 @@ local schema = {
 
 The schema defines a non-negative number `i`, a string `s`, a non-empty array of `t`, and `ip` / `port`. Only `i` is required.
 
-At the same time, we need to implement the __check_schema(conf)__ method to complete the specification verification.
+At the same time, we need to implement the __check_schema(conf, schema_type)__ method to complete the specification verification.
 
 ```lua
 function _M.check_schema(conf, schema_type)
+    if schema_type == core.schema.TYPE_METADATA then
+        return core.schema.check(metadata_schema, conf)
+    end
     return core.schema.check(schema, conf)
 end
 ```
 
+:::note
+
 Note: the project has provided the public method "__core.schema.check__", which can be used directly to complete JSON
 verification.
 
-In addition, if the plugin needs to use some metadata, we can define the plugin `metadata_schema`, and then we can dynamically manage these metadata through the `Admin API`. Example:
+:::
+
+The input parameter **schema_type** is used to distinguish between different schemas types. For example, many plugins need to use some [metadata](./terminology/plugin-metadata.md), so they define the plugin's `metadata_schema`. Another example, the [key-auth](https://github.com/apache/apisix/blob/master/apisix/plugins/key-auth.lua) plugin needs to provide a `consumer_schema` to check the configuration of the `plugins` attribute of the `consumer` resource in order to be used with the [Consumer](./admin-api.md#consumer) resource.

Review Comment:
   For the reader, the purpose of this paragraph is simply to indicate that the function can be used to check different schemas, so I removed the excessive content, including `consumer_schema`. However, `consumer_schema` might still be worth keeping.
   I have reorganized this paragraph.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@apisix.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] docs: improve `plugin-develop` docs [apisix]

Posted by "Baoyuantop (via GitHub)" <gi...@apache.org>.
Baoyuantop merged PR #12242:
URL: https://github.com/apache/apisix/pull/12242


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@apisix.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org