You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by GitBox <gi...@apache.org> on 2021/06/21 12:39:15 UTC

[GitHub] [apisix-website] Serendipity96 opened a new pull request #372: docs:added use Java to write Apache APISIX plugins blog

Serendipity96 opened a new pull request #372:
URL: https://github.com/apache/apisix-website/pull/372


   Changes:
   
   docs: added use Java to write Apache APISIX plugins blog
   
   tips:iframe load video failed


-- 
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.

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



[GitHub] [apisix-website] juzhiyuan commented on a change in pull request #372: docs:added use Java to write Apache APISIX plugins blog

Posted by GitBox <gi...@apache.org>.
juzhiyuan commented on a change in pull request #372:
URL: https://github.com/apache/apisix-website/pull/372#discussion_r655804191



##########
File path: website/blog/2021-06-21-use-Java-to-write-Apache-APISIX-plugins.md
##########
@@ -0,0 +1,233 @@
+---
+title: "使用 Java 编写 Apache APISIX 插件"
+author: Zhengsong Tu
+authorURL: "https://github.com/tzssangglass"
+authorImageURL: "https://avatars.githubusercontent.com/u/30819887?v=4"
+---
+> [@tzssangglass](https://github.com/tzssangglass), Apache APISIX contributor from [Shenzhen Zhiliu Technology Co.](https://www.apiseven.com/)
+>
+
+<!--truncate-->
+Apache APISIX 支持多语言编写插件了!不会 Lua 也没关系,现在可以用你熟悉的语言编写插件,文末还有**视频教程**。
+
+## 1. 简介
+
+### 1.1 为什么 Apache APISIX 要支持多语言编写插件
+
+在支持多语言编程插件前,Apache APISIX 只支持使用 Lua 语言编写插件,需要开发者掌握 Lua 和 OpenResty 相关的开发能力。然而相对于主流开发语言 Java、Go 来说,Lua 和 OpenResty 属于相对小众的技术,开发者很少。如果从头开始学习 Lua 和 OpenResty,需要付出相当多的时间和精力。
+
+开发团队在进行技术选型的时候,最重要的考量就是所选技术是否与本团队技术栈相匹配,然而小众的技术栈就限制了 Apache APISIX 在更广阔的场景下进行技术落地。
+
+现在 Apache APISIX 支持多语言开发插件,**更重要的是支持语言所在的开发生态圈,使用者可以使用自己熟悉的技术栈来开发 Apache APISIX**。以支持 Java 为例,使用者不仅可以使用 Java 语言编写插件,还可以融入 Spring Cloud 生态圈,广泛使用生态圈内的各种技术组件。
+
+### 1.2 Apache APISIX 多语言支持架构图
+
+![2021-06-21-1](../static/img/blog_img/2021-06-21-1.png)
+
+上图左边是 Apache APISIX 的工作流程,右边的 plugin runner 是指插件运行器,泛指多语言支持的项目。本文档下面提到的 apisix-java-plugin-runner 项目就是支持 Java 语言的 plugin runner。
+
+当你在 Apache APISIX 中配置一个 plugin runner 时,Apache APISIX 会启动一个子进程运行 plugin runner,该子进程与 Apache APISIX 进程属于同一个用户。当我们重启或重新加载 Apache APISIX 时,plugin runner 也将被重启。
+
+如果你为一个给定的路由配置了 ext-plugin-* 插件,击中该路由的请求将触发  Apache APISIX,通过 unix socket 向 plugin runner 执行 RPC 调用。调用细分为两个阶段:
+
+- ext-plugin-pre-req: 在执行 Apache APISIX 内置插件(Lua 语言插件)之前
+- ext-plugin-post-req: 在执行 Apache APISIX 内置插件(Lua 语言插件)之后
+
+根据需要配置 plugin runner 的执行时机。
+
+plugin runner 会处理 RPC 调用,在其内部创建一个模拟请求,然后运行多语言编写的插件,并将结果返回给 Apache APISIX。
+
+多语言插件的执行顺序是在 ext-plugin-* 插件配置项中定义的。像其他插件一样,它们可以被启用并在运行中重新定义。
+
+## 2. 搭建开发环境
+
+首先需要搭建 Apache APISIX 的运行环境或者开发环境,参考 [构建 Apache APISIX](https://github.com/apache/apisix/blob/master/docs/zh/latest/how-to-build.md),以及 Java 项目的开发环境,参考 [构建 apisix-java-plugin-runner](https://github.com/apache/apisix-java-plugin-runner/blob/main/docs/development.md)。
+
+**注意**:Apache APISIX 和 apisix-java-plugin-runner 需要位于同一实例上。
+
+## 3. 进入调试模式
+
+### 3.1 设置 Apache APISIX 进入调试模式
+
+这里是指让 Apache APISIX 以调试的方式运行外部插件,在 `config.yaml` 中增加以下配置
+
+```text
+ext-plugin:
+  path_for_test: /tmp/runner.sock
+```
+
+这个配置的意思是,Apache APISIX  相当于 client 端,会监听位于 `/tmp/runner.sock` 位置上的 Unxi Domain Socket 链接。
+
+### 3.2 设置 apisix-java-plugin-runner 进入调试模式
+
+在启动 `Main class(org.apache.apisix.plugin.runner.PluginRunnerApplication)`之前,需要配置用户级的环境变量 `APISIX_LISTEN_ADDRESS=unix:/tmp/runner.sock` 和 `APISIX_CONF_EXPIRE_TIME=3600`。
+
+如果你是使用 IDEA 进行开发,那么配置好的环境变量示意如下:
+
+![2021-06-21-2](../static/img/blog_img/2021-06-21-2.png)
+
+apisix-java-plugin-runner 相当于 server 端,在启动时会主动创建 `/tmp/runner.sock` 文件,并在这个文件上与 Apache APISIX 进行 Unix Domain Socket 通信。
+
+## 4. 开发
+
+### 4.1 场景
+
+我们以一个场景来代入开发过程:需要验证请求 header 中 token 的有效性,验证 token 的方式是用请求中携带 token 作为参数,访问 SSO 固定的接口,如果 token 验证通过则放行请求,验证失败则阻止请求。
+
+### 4.2 配置 Apache APISIX
+
+先给插件命名为 `TokenValidator`,然后设计属性,为了尽可能做到动态配置,属性设计如下
+
+```text
+{
+  "validate_header": "token",
+  "validate_url": "https://www.sso.foo.com/token/validate",
+  "rejected_code": "403"
+}
+```
+
+启动 Apache APISIX,然后新增一条路由配置,指定该路由需要调用 apisix-java-plugin-runner 的 `TokenValidator` 插件,示例如下
+
+```text
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
+{
+    "uri":"/get",
+    "plugins":{
+        "ext-plugin-pre-req":{
+            "conf":[
+                {
+                    "name":"TokenValidator",
+                    "value":"{\"validate_header\":\"token\",\"validate_url\":\"https://www.sso.foo.com/token/validate\",\"rejected_code\":\"403\"}"
+                }
+            ]
+        }
+    },
+    "upstream":{
+        "nodes":{
+            "httpbin.org:80":1
+        },
+        "type":"roundrobin"
+    }
+}
+```
+
+需要注意的是,`TokenValidator` 的属性需要经过 json 转义,作为 string 类型进行配置。
+
+(这里上游地址配置为 httpbin.org,方便调试)
+
+### 4.3 开发 Java 插件
+
+在 runner-plugin/src/main/java/org/apache/apisix/plugin/runner/filter 目录下,新增 `TokenValidatr.java`,代码初始骨架如下
+
+```Java
+package org.apache.apisix.plugin.runner.filter;
+
+import org.apache.apisix.plugin.runner.HttpRequest;
+import org.apache.apisix.plugin.runner.HttpResponse;
+import org.springframework.stereotype.Component;
+import reactor.core.publisher.Mono;
+
+
+@Component
+public class TokenValidator implements PluginFilter {
+
+    @Override
+    public String name() {
+        return "TokenValidator";
+    }
+
+    @Override
+    public Mono<Void> filter(HttpRequest request, HttpResponse response, PluginFilterChain chain) {
+        return chain.filter(request, response);
+    }
+}
+```
+
+需要继承 `PluginFilter`接口,重写 `name` 和 `filter`函数。
+
+重写 `name` 的返回值,和前面配置 APISIX 的路由属性中 "name" 保持一致。
+
+完整代码如下:
+
+```Java
+package org.apache.apisix.plugin.runner.filter;
+
+import com.google.gson.Gson;
+import org.apache.apisix.plugin.runner.HttpRequest;
+import org.apache.apisix.plugin.runner.HttpResponse;
+import org.springframework.stereotype.Component;
+import reactor.core.publisher.Mono;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Component
+public class TokenValidator implements PluginFilter {
+
+    @Override
+    public String name() {
+        return "TokenValidator";
+    }
+
+    @Override
+    public Mono<Void> filter(HttpRequest request, HttpResponse response, PluginFilterChain chain) {
+        // parse `conf` to json
+        String configStr = request.getConfig(this);
+        Gson gson = new Gson();
+        Map<String, Object> conf = new HashMap<>();
+        conf = gson.fromJson(configStr, conf.getClass());
+
+        // get configuration parameters
+        String token = request.getHeader((String) conf.get("validate_header"));
+        String validate_url = (String) conf.get("validate_url");
+        boolean flag = validate(token, validate_url);
+
+        // token verification results
+        if (!flag) {
+            String rejected_code = (String) conf.get("rejected_code");
+            response.setStatusCode(Integer.parseInt(rejected_code));
+            return chain.filter(request, response);
+        }
+
+        return chain.filter(request, response);
+    }
+
+    private Boolean validate(String token, String validate_url) {
+        //TODO: improve the validation process
+        return true;
+    }
+}
+```
+
+### 4.4 测试
+
+在 Apache APISIX 上配置的上游服务是 httpbin.org,可以访问 Apache APISIX,触发路由,让 Apache APISIX 调用 apisix-java-plugin-runner 去执行 TokenValidator 插件,测试一下 Java 插件效果。
+
+```text
+curl -H 'token: 123456' 127.0.0.1:9080/get 
+{
+ "args": {}, 
+ "headers": {
+ "Accept": "/", 
+ "Host": "127.0.0.1", 
+ "Token": "123456", 
+ "User-Agent": "curl/7.71.1", 
+ "X-Amzn-Trace-Id": "Root=1-60cb0424-02b5bf804cfeab5252392f96", 
+ "X-Forwarded-Host": "127.0.0.1"
+ }, 
+ "origin": "127.0.0.1", 
+ "url": "http://127.0.0.1/get"
+}
+```
+
+## 5. 部署
+
+插件开发完成后,部署操作可以参考 [部署 apisix-java-plugin-runner](https://github.com/apache/apisix-java-plugin-runner/blob/main/docs/how-it-works.md#run)。
+
+## 6. 视频教程
+<iframe 
+    height="350" 
+    width="600" 
+    src="../static/video/2021-06-21-use-Java-to-write-Apache-APISIX-plugins.mp4" 

Review comment:
       Use this one instead:
   
   https://api7-website-1301662268.file.myqcloud.com/2021-06-21-use-Java-to-write-Apache-APISIX-plugins.mp4




-- 
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.

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



[GitHub] [apisix-website] juzhiyuan commented on a change in pull request #372: docs:added use Java to write Apache APISIX plugins blog

Posted by GitBox <gi...@apache.org>.
juzhiyuan commented on a change in pull request #372:
URL: https://github.com/apache/apisix-website/pull/372#discussion_r655803454



##########
File path: website/blog/2021-06-21-use-Java-to-write-Apache-APISIX-plugins.md
##########
@@ -0,0 +1,233 @@
+---
+title: "使用 Java 编写 Apache APISIX 插件"
+author: Zhengsong Tu
+authorURL: "https://github.com/tzssangglass"
+authorImageURL: "https://avatars.githubusercontent.com/u/30819887?v=4"
+---
+> [@tzssangglass](https://github.com/tzssangglass), Apache APISIX contributor from [Shenzhen Zhiliu Technology Co.](https://www.apiseven.com/)
+>
+
+<!--truncate-->
+Apache APISIX 支持多语言编写插件了!不会 Lua 也没关系,现在可以用你熟悉的语言编写插件,文末还有**视频教程**。
+
+## 1. 简介
+
+### 1.1 为什么 Apache APISIX 要支持多语言编写插件
+
+在支持多语言编程插件前,Apache APISIX 只支持使用 Lua 语言编写插件,需要开发者掌握 Lua 和 OpenResty 相关的开发能力。然而相对于主流开发语言 Java、Go 来说,Lua 和 OpenResty 属于相对小众的技术,开发者很少。如果从头开始学习 Lua 和 OpenResty,需要付出相当多的时间和精力。
+
+开发团队在进行技术选型的时候,最重要的考量就是所选技术是否与本团队技术栈相匹配,然而小众的技术栈就限制了 Apache APISIX 在更广阔的场景下进行技术落地。
+
+现在 Apache APISIX 支持多语言开发插件,**更重要的是支持语言所在的开发生态圈,使用者可以使用自己熟悉的技术栈来开发 Apache APISIX**。以支持 Java 为例,使用者不仅可以使用 Java 语言编写插件,还可以融入 Spring Cloud 生态圈,广泛使用生态圈内的各种技术组件。
+
+### 1.2 Apache APISIX 多语言支持架构图
+
+![2021-06-21-1](../static/img/blog_img/2021-06-21-1.png)
+
+上图左边是 Apache APISIX 的工作流程,右边的 plugin runner 是指插件运行器,泛指多语言支持的项目。本文档下面提到的 apisix-java-plugin-runner 项目就是支持 Java 语言的 plugin runner。
+
+当你在 Apache APISIX 中配置一个 plugin runner 时,Apache APISIX 会启动一个子进程运行 plugin runner,该子进程与 Apache APISIX 进程属于同一个用户。当我们重启或重新加载 Apache APISIX 时,plugin runner 也将被重启。
+
+如果你为一个给定的路由配置了 ext-plugin-* 插件,击中该路由的请求将触发  Apache APISIX,通过 unix socket 向 plugin runner 执行 RPC 调用。调用细分为两个阶段:
+
+- ext-plugin-pre-req: 在执行 Apache APISIX 内置插件(Lua 语言插件)之前
+- ext-plugin-post-req: 在执行 Apache APISIX 内置插件(Lua 语言插件)之后
+
+根据需要配置 plugin runner 的执行时机。
+
+plugin runner 会处理 RPC 调用,在其内部创建一个模拟请求,然后运行多语言编写的插件,并将结果返回给 Apache APISIX。
+
+多语言插件的执行顺序是在 ext-plugin-* 插件配置项中定义的。像其他插件一样,它们可以被启用并在运行中重新定义。
+
+## 2. 搭建开发环境
+
+首先需要搭建 Apache APISIX 的运行环境或者开发环境,参考 [构建 Apache APISIX](https://github.com/apache/apisix/blob/master/docs/zh/latest/how-to-build.md),以及 Java 项目的开发环境,参考 [构建 apisix-java-plugin-runner](https://github.com/apache/apisix-java-plugin-runner/blob/main/docs/development.md)。
+
+**注意**:Apache APISIX 和 apisix-java-plugin-runner 需要位于同一实例上。
+
+## 3. 进入调试模式
+
+### 3.1 设置 Apache APISIX 进入调试模式
+
+这里是指让 Apache APISIX 以调试的方式运行外部插件,在 `config.yaml` 中增加以下配置
+
+```text
+ext-plugin:
+  path_for_test: /tmp/runner.sock
+```
+
+这个配置的意思是,Apache APISIX  相当于 client 端,会监听位于 `/tmp/runner.sock` 位置上的 Unxi Domain Socket 链接。
+
+### 3.2 设置 apisix-java-plugin-runner 进入调试模式
+
+在启动 `Main class(org.apache.apisix.plugin.runner.PluginRunnerApplication)`之前,需要配置用户级的环境变量 `APISIX_LISTEN_ADDRESS=unix:/tmp/runner.sock` 和 `APISIX_CONF_EXPIRE_TIME=3600`。
+
+如果你是使用 IDEA 进行开发,那么配置好的环境变量示意如下:
+
+![2021-06-21-2](../static/img/blog_img/2021-06-21-2.png)
+
+apisix-java-plugin-runner 相当于 server 端,在启动时会主动创建 `/tmp/runner.sock` 文件,并在这个文件上与 Apache APISIX 进行 Unix Domain Socket 通信。
+
+## 4. 开发
+
+### 4.1 场景
+
+我们以一个场景来代入开发过程:需要验证请求 header 中 token 的有效性,验证 token 的方式是用请求中携带 token 作为参数,访问 SSO 固定的接口,如果 token 验证通过则放行请求,验证失败则阻止请求。
+
+### 4.2 配置 Apache APISIX
+
+先给插件命名为 `TokenValidator`,然后设计属性,为了尽可能做到动态配置,属性设计如下
+
+```text
+{
+  "validate_header": "token",
+  "validate_url": "https://www.sso.foo.com/token/validate",
+  "rejected_code": "403"
+}
+```
+
+启动 Apache APISIX,然后新增一条路由配置,指定该路由需要调用 apisix-java-plugin-runner 的 `TokenValidator` 插件,示例如下
+
+```text
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
+{
+    "uri":"/get",
+    "plugins":{
+        "ext-plugin-pre-req":{
+            "conf":[
+                {
+                    "name":"TokenValidator",
+                    "value":"{\"validate_header\":\"token\",\"validate_url\":\"https://www.sso.foo.com/token/validate\",\"rejected_code\":\"403\"}"
+                }
+            ]
+        }
+    },
+    "upstream":{
+        "nodes":{
+            "httpbin.org:80":1
+        },
+        "type":"roundrobin"
+    }
+}
+```
+
+需要注意的是,`TokenValidator` 的属性需要经过 json 转义,作为 string 类型进行配置。
+
+(这里上游地址配置为 httpbin.org,方便调试)
+
+### 4.3 开发 Java 插件
+
+在 runner-plugin/src/main/java/org/apache/apisix/plugin/runner/filter 目录下,新增 `TokenValidatr.java`,代码初始骨架如下
+
+```Java
+package org.apache.apisix.plugin.runner.filter;
+
+import org.apache.apisix.plugin.runner.HttpRequest;
+import org.apache.apisix.plugin.runner.HttpResponse;
+import org.springframework.stereotype.Component;
+import reactor.core.publisher.Mono;
+
+
+@Component
+public class TokenValidator implements PluginFilter {
+
+    @Override
+    public String name() {
+        return "TokenValidator";
+    }
+
+    @Override
+    public Mono<Void> filter(HttpRequest request, HttpResponse response, PluginFilterChain chain) {
+        return chain.filter(request, response);
+    }
+}
+```
+
+需要继承 `PluginFilter`接口,重写 `name` 和 `filter`函数。
+
+重写 `name` 的返回值,和前面配置 APISIX 的路由属性中 "name" 保持一致。
+
+完整代码如下:
+
+```Java
+package org.apache.apisix.plugin.runner.filter;
+
+import com.google.gson.Gson;
+import org.apache.apisix.plugin.runner.HttpRequest;
+import org.apache.apisix.plugin.runner.HttpResponse;
+import org.springframework.stereotype.Component;
+import reactor.core.publisher.Mono;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Component
+public class TokenValidator implements PluginFilter {
+
+    @Override
+    public String name() {
+        return "TokenValidator";
+    }
+
+    @Override
+    public Mono<Void> filter(HttpRequest request, HttpResponse response, PluginFilterChain chain) {
+        // parse `conf` to json
+        String configStr = request.getConfig(this);
+        Gson gson = new Gson();
+        Map<String, Object> conf = new HashMap<>();
+        conf = gson.fromJson(configStr, conf.getClass());
+
+        // get configuration parameters
+        String token = request.getHeader((String) conf.get("validate_header"));
+        String validate_url = (String) conf.get("validate_url");
+        boolean flag = validate(token, validate_url);
+
+        // token verification results
+        if (!flag) {
+            String rejected_code = (String) conf.get("rejected_code");
+            response.setStatusCode(Integer.parseInt(rejected_code));
+            return chain.filter(request, response);
+        }
+
+        return chain.filter(request, response);
+    }
+
+    private Boolean validate(String token, String validate_url) {
+        //TODO: improve the validation process
+        return true;
+    }
+}
+```
+
+### 4.4 测试
+
+在 Apache APISIX 上配置的上游服务是 httpbin.org,可以访问 Apache APISIX,触发路由,让 Apache APISIX 调用 apisix-java-plugin-runner 去执行 TokenValidator 插件,测试一下 Java 插件效果。
+
+```text
+curl -H 'token: 123456' 127.0.0.1:9080/get 
+{
+ "args": {}, 
+ "headers": {
+ "Accept": "/", 
+ "Host": "127.0.0.1", 
+ "Token": "123456", 
+ "User-Agent": "curl/7.71.1", 
+ "X-Amzn-Trace-Id": "Root=1-60cb0424-02b5bf804cfeab5252392f96", 
+ "X-Forwarded-Host": "127.0.0.1"
+ }, 
+ "origin": "127.0.0.1", 
+ "url": "http://127.0.0.1/get"
+}
+```
+
+## 5. 部署
+
+插件开发完成后,部署操作可以参考 [部署 apisix-java-plugin-runner](https://github.com/apache/apisix-java-plugin-runner/blob/main/docs/how-it-works.md#run)。
+
+## 6. 视频教程
+<iframe 
+    height="350" 
+    width="600" 
+    src="../static/video/2021-06-21-use-Java-to-write-Apache-APISIX-plugins.mp4" 

Review comment:
       Not a good idea IMO, because people in China couldn't watch this video, let me help to upload it to CDN.




-- 
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.

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



[GitHub] [apisix-website] netlify[bot] commented on pull request #372: docs:added use Java to write Apache APISIX plugins blog

Posted by GitBox <gi...@apache.org>.
netlify[bot] commented on pull request #372:
URL: https://github.com/apache/apisix-website/pull/372#issuecomment-864999758


   :construction_worker: Deploy Preview for *apisix* processing.
   
   
   :hammer: Explore the source changes: b6d42d2d56c5088e5a8b43ff73b3a3b061acaa03
   
   :mag: Inspect the deploy log: [https://app.netlify.com/sites/apisix/deploys/60d0886bd6b4ac0008efdd90](https://app.netlify.com/sites/apisix/deploys/60d0886bd6b4ac0008efdd90?utm_source=github&utm_campaign=bot_dl)
   


-- 
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.

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



[GitHub] [apisix-website] netlify[bot] edited a comment on pull request #372: docs: added use Java to write Apache APISIX plugins blog

Posted by GitBox <gi...@apache.org>.
netlify[bot] edited a comment on pull request #372:
URL: https://github.com/apache/apisix-website/pull/372#issuecomment-864999758


   :heavy_check_mark: Deploy Preview for *apisix* ready!
   
   
   :hammer: Explore the source changes: 4cb07f89a812212ff0f019cdee4be20c67af61f2
   
   :mag: Inspect the deploy log: [https://app.netlify.com/sites/apisix/deploys/60d15eb47881b10008a2d41c](https://app.netlify.com/sites/apisix/deploys/60d15eb47881b10008a2d41c?utm_source=github&utm_campaign=bot_dl)
   
   :sunglasses: Browse the preview: [https://deploy-preview-372--apisix.netlify.app](https://deploy-preview-372--apisix.netlify.app?utm_source=github&utm_campaign=bot_dp)
   


-- 
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.

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



[GitHub] [apisix-website] netlify[bot] commented on pull request #372: docs:added use Java to write Apache APISIX plugins blog

Posted by GitBox <gi...@apache.org>.
netlify[bot] commented on pull request #372:
URL: https://github.com/apache/apisix-website/pull/372#issuecomment-864999758


   :construction_worker: Deploy Preview for *apisix* processing.
   
   
   :hammer: Explore the source changes: b6d42d2d56c5088e5a8b43ff73b3a3b061acaa03
   
   :mag: Inspect the deploy log: [https://app.netlify.com/sites/apisix/deploys/60d0886bd6b4ac0008efdd90](https://app.netlify.com/sites/apisix/deploys/60d0886bd6b4ac0008efdd90?utm_source=github&utm_campaign=bot_dl)
   


-- 
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.

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



[GitHub] [apisix-website] juzhiyuan commented on a change in pull request #372: docs:added use Java to write Apache APISIX plugins blog

Posted by GitBox <gi...@apache.org>.
juzhiyuan commented on a change in pull request #372:
URL: https://github.com/apache/apisix-website/pull/372#discussion_r655425415



##########
File path: website/blog/2021-06-21-use-Java-to-write-Apache-APISIX-plugins.md
##########
@@ -0,0 +1,233 @@
+---
+title: "使用 Java 编写 Apache APISIX 插件"
+author: Zhengsong Tu
+authorURL: "https://github.com/tzssangglass"
+authorImageURL: "https://avatars.githubusercontent.com/u/30819887?v=4"
+---
+> [@tzssangglass](https://github.com/tzssangglass), Apache APISIX contributor from [Shenzhen Zhiliu Technology Co.](https://www.apiseven.com/)
+>
+
+<!--truncate-->
+Apache APISIX 支持多语言编写插件了!不会 Lua 也没关系,现在可以用你熟悉的语言编写插件,文末还有**视频教程**。
+
+## 1. 简介
+
+### 1.1 为什么 Apache APISIX 要支持多语言编写插件
+
+在支持多语言编程插件前,Apache APISIX 只支持使用 Lua 语言编写插件,需要开发者掌握 Lua 和 OpenResty 相关的开发能力。然而相对于主流开发语言 Java、Go 来说,Lua 和 OpenResty 属于相对小众的技术,开发者很少。如果从头开始学习 Lua 和 OpenResty,需要付出相当多的时间和精力。
+
+开发团队在进行技术选型的时候,最重要的考量就是所选技术是否与本团队技术栈相匹配,然而小众的技术栈就限制了 Apache APISIX 在更广阔的场景下进行技术落地。
+
+现在 Apache APISIX 支持多语言开发插件,**更重要的是支持语言所在的开发生态圈,使用者可以使用自己熟悉的技术栈来开发 Apache APISIX**。以支持 Java 为例,使用者不仅可以使用 Java 语言编写插件,还可以融入 Spring Cloud 生态圈,广泛使用生态圈内的各种技术组件。
+
+### 1.2 Apache APISIX 多语言支持架构图
+
+![2021-06-21-1](../static/img/blog_img/2021-06-21-1.png)
+
+上图左边是 Apache APISIX 的工作流程,右边的 plugin runner 是指插件运行器,泛指多语言支持的项目。本文档下面提到的 apisix-java-plugin-runner 项目就是支持 Java 语言的 plugin runner。
+
+当你在 Apache APISIX 中配置一个 plugin runner 时,Apache APISIX 会启动一个子进程运行 plugin runner,该子进程与 Apache APISIX 进程属于同一个用户。当我们重启或重新加载 Apache APISIX 时,plugin runner 也将被重启。
+
+如果你为一个给定的路由配置了 ext-plugin-* 插件,击中该路由的请求将触发  Apache APISIX,通过 unix socket 向 plugin runner 执行 RPC 调用。调用细分为两个阶段:
+
+- ext-plugin-pre-req: 在执行 Apache APISIX 内置插件(Lua 语言插件)之前
+- ext-plugin-post-req: 在执行 Apache APISIX 内置插件(Lua 语言插件)之后
+
+根据需要配置 plugin runner 的执行时机。
+
+plugin runner 会处理 RPC 调用,在其内部创建一个模拟请求,然后运行多语言编写的插件,并将结果返回给 Apache APISIX。
+
+多语言插件的执行顺序是在 ext-plugin-* 插件配置项中定义的。像其他插件一样,它们可以被启用并在运行中重新定义。
+
+## 2. 搭建开发环境
+
+首先需要搭建 Apache APISIX 的运行环境或者开发环境,参考 [构建 Apache APISIX](https://github.com/apache/apisix/blob/master/docs/zh/latest/how-to-build.md),以及 Java 项目的开发环境,参考 [构建 apisix-java-plugin-runner](https://github.com/apache/apisix-java-plugin-runner/blob/main/docs/development.md)。
+
+**注意**:Apache APISIX 和 apisix-java-plugin-runner 需要位于同一实例上。
+
+## 3. 进入调试模式
+
+### 3.1 设置 Apache APISIX 进入调试模式
+
+这里是指让 Apache APISIX 以调试的方式运行外部插件,在 `config.yaml` 中增加以下配置
+
+```text
+ext-plugin:
+  path_for_test: /tmp/runner.sock
+```
+
+这个配置的意思是,Apache APISIX  相当于 client 端,会监听位于 `/tmp/runner.sock` 位置上的 Unxi Domain Socket 链接。
+
+### 3.2 设置 apisix-java-plugin-runner 进入调试模式
+
+在启动 `Main class(org.apache.apisix.plugin.runner.PluginRunnerApplication)`之前,需要配置用户级的环境变量 `APISIX_LISTEN_ADDRESS=unix:/tmp/runner.sock` 和 `APISIX_CONF_EXPIRE_TIME=3600`。
+
+如果你是使用 IDEA 进行开发,那么配置好的环境变量示意如下:
+
+![2021-06-21-2](../static/img/blog_img/2021-06-21-2.png)
+
+apisix-java-plugin-runner 相当于 server 端,在启动时会主动创建 `/tmp/runner.sock` 文件,并在这个文件上与 Apache APISIX 进行 Unix Domain Socket 通信。
+
+## 4. 开发
+
+### 4.1 场景
+
+我们以一个场景来代入开发过程:需要验证请求 header 中 token 的有效性,验证 token 的方式是用请求中携带 token 作为参数,访问 SSO 固定的接口,如果 token 验证通过则放行请求,验证失败则阻止请求。
+
+### 4.2 配置 Apache APISIX
+
+先给插件命名为 `TokenValidator`,然后设计属性,为了尽可能做到动态配置,属性设计如下
+
+```text
+{
+  "validate_header": "token",
+  "validate_url": "https://www.sso.foo.com/token/validate",
+  "rejected_code": "403"
+}
+```
+
+启动 Apache APISIX,然后新增一条路由配置,指定该路由需要调用 apisix-java-plugin-runner 的 `TokenValidator` 插件,示例如下
+
+```text
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
+{
+    "uri":"/get",
+    "plugins":{
+        "ext-plugin-pre-req":{
+            "conf":[
+                {
+                    "name":"TokenValidator",
+                    "value":"{\"validate_header\":\"token\",\"validate_url\":\"https://www.sso.foo.com/token/validate\",\"rejected_code\":\"403\"}"
+                }
+            ]
+        }
+    },
+    "upstream":{
+        "nodes":{
+            "httpbin.org:80":1
+        },
+        "type":"roundrobin"
+    }
+}
+```
+
+需要注意的是,`TokenValidator` 的属性需要经过 json 转义,作为 string 类型进行配置。
+
+(这里上游地址配置为 httpbin.org,方便调试)
+
+### 4.3 开发 Java 插件
+
+在 runner-plugin/src/main/java/org/apache/apisix/plugin/runner/filter 目录下,新增 `TokenValidatr.java`,代码初始骨架如下
+
+```Java
+package org.apache.apisix.plugin.runner.filter;
+
+import org.apache.apisix.plugin.runner.HttpRequest;
+import org.apache.apisix.plugin.runner.HttpResponse;
+import org.springframework.stereotype.Component;
+import reactor.core.publisher.Mono;
+
+
+@Component
+public class TokenValidator implements PluginFilter {
+
+    @Override
+    public String name() {
+        return "TokenValidator";
+    }
+
+    @Override
+    public Mono<Void> filter(HttpRequest request, HttpResponse response, PluginFilterChain chain) {
+        return chain.filter(request, response);
+    }
+}
+```
+
+需要继承 `PluginFilter`接口,重写 `name` 和 `filter`函数。
+
+重写 `name` 的返回值,和前面配置 APISIX 的路由属性中 "name" 保持一致。
+
+完整代码如下:
+
+```Java
+package org.apache.apisix.plugin.runner.filter;
+
+import com.google.gson.Gson;
+import org.apache.apisix.plugin.runner.HttpRequest;
+import org.apache.apisix.plugin.runner.HttpResponse;
+import org.springframework.stereotype.Component;
+import reactor.core.publisher.Mono;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Component
+public class TokenValidator implements PluginFilter {
+
+    @Override
+    public String name() {
+        return "TokenValidator";
+    }
+
+    @Override
+    public Mono<Void> filter(HttpRequest request, HttpResponse response, PluginFilterChain chain) {
+        // parse `conf` to json
+        String configStr = request.getConfig(this);
+        Gson gson = new Gson();
+        Map<String, Object> conf = new HashMap<>();
+        conf = gson.fromJson(configStr, conf.getClass());
+
+        // get configuration parameters
+        String token = request.getHeader((String) conf.get("validate_header"));
+        String validate_url = (String) conf.get("validate_url");
+        boolean flag = validate(token, validate_url);
+
+        // token verification results
+        if (!flag) {
+            String rejected_code = (String) conf.get("rejected_code");
+            response.setStatusCode(Integer.parseInt(rejected_code));
+            return chain.filter(request, response);
+        }
+
+        return chain.filter(request, response);
+    }
+
+    private Boolean validate(String token, String validate_url) {
+        //TODO: improve the validation process
+        return true;
+    }
+}
+```
+
+### 4.4 测试
+
+在 Apache APISIX 上配置的上游服务是 httpbin.org,可以访问 Apache APISIX,触发路由,让 Apache APISIX 调用 apisix-java-plugin-runner 去执行 TokenValidator 插件,测试一下 Java 插件效果。
+
+```text
+curl -H 'token: 123456' 127.0.0.1:9080/get 
+{
+ "args": {}, 
+ "headers": {
+ "Accept": "/", 
+ "Host": "127.0.0.1", 
+ "Token": "123456", 
+ "User-Agent": "curl/7.71.1", 
+ "X-Amzn-Trace-Id": "Root=1-60cb0424-02b5bf804cfeab5252392f96", 
+ "X-Forwarded-Host": "127.0.0.1"
+ }, 
+ "origin": "127.0.0.1", 
+ "url": "http://127.0.0.1/get"
+}
+```
+
+## 5. 部署
+
+插件开发完成后,部署操作可以参考 [部署 apisix-java-plugin-runner](https://github.com/apache/apisix-java-plugin-runner/blob/main/docs/how-it-works.md#run)。
+
+## 6. 视频教程
+<iframe 
+    height="350" 
+    width="600" 
+    src="../static/video/2021-06-21-use-Java-to-write-Apache-APISIX-plugins.mp4" 

Review comment:
       Please upload this video to somewhere else, not to this repo.




-- 
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.

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



[GitHub] [apisix-website] netlify[bot] edited a comment on pull request #372: docs:added use Java to write Apache APISIX plugins blog

Posted by GitBox <gi...@apache.org>.
netlify[bot] edited a comment on pull request #372:
URL: https://github.com/apache/apisix-website/pull/372#issuecomment-864999758






-- 
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.

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



[GitHub] [apisix-website] netlify[bot] edited a comment on pull request #372: docs:added use Java to write Apache APISIX plugins blog

Posted by GitBox <gi...@apache.org>.
netlify[bot] edited a comment on pull request #372:
URL: https://github.com/apache/apisix-website/pull/372#issuecomment-864999758


   :heavy_check_mark: Deploy Preview for *apisix* ready!
   
   
   :hammer: Explore the source changes: da6d32542dfdbfe17674c20b76371960c8f69015
   
   :mag: Inspect the deploy log: [https://app.netlify.com/sites/apisix/deploys/60d1415975d50c000887e550](https://app.netlify.com/sites/apisix/deploys/60d1415975d50c000887e550?utm_source=github&utm_campaign=bot_dl)
   
   :sunglasses: Browse the preview: [https://deploy-preview-372--apisix.netlify.app](https://deploy-preview-372--apisix.netlify.app?utm_source=github&utm_campaign=bot_dp)
   


-- 
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.

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



[GitHub] [apisix-website] 1502shivam-singh commented on a change in pull request #372: docs:added use Java to write Apache APISIX plugins blog

Posted by GitBox <gi...@apache.org>.
1502shivam-singh commented on a change in pull request #372:
URL: https://github.com/apache/apisix-website/pull/372#discussion_r655616956



##########
File path: website/blog/2021-06-21-use-Java-to-write-Apache-APISIX-plugins.md
##########
@@ -0,0 +1,233 @@
+---
+title: "使用 Java 编写 Apache APISIX 插件"
+author: Zhengsong Tu
+authorURL: "https://github.com/tzssangglass"
+authorImageURL: "https://avatars.githubusercontent.com/u/30819887?v=4"
+---
+> [@tzssangglass](https://github.com/tzssangglass), Apache APISIX contributor from [Shenzhen Zhiliu Technology Co.](https://www.apiseven.com/)
+>
+
+<!--truncate-->
+Apache APISIX 支持多语言编写插件了!不会 Lua 也没关系,现在可以用你熟悉的语言编写插件,文末还有**视频教程**。
+
+## 1. 简介
+
+### 1.1 为什么 Apache APISIX 要支持多语言编写插件
+
+在支持多语言编程插件前,Apache APISIX 只支持使用 Lua 语言编写插件,需要开发者掌握 Lua 和 OpenResty 相关的开发能力。然而相对于主流开发语言 Java、Go 来说,Lua 和 OpenResty 属于相对小众的技术,开发者很少。如果从头开始学习 Lua 和 OpenResty,需要付出相当多的时间和精力。
+
+开发团队在进行技术选型的时候,最重要的考量就是所选技术是否与本团队技术栈相匹配,然而小众的技术栈就限制了 Apache APISIX 在更广阔的场景下进行技术落地。
+
+现在 Apache APISIX 支持多语言开发插件,**更重要的是支持语言所在的开发生态圈,使用者可以使用自己熟悉的技术栈来开发 Apache APISIX**。以支持 Java 为例,使用者不仅可以使用 Java 语言编写插件,还可以融入 Spring Cloud 生态圈,广泛使用生态圈内的各种技术组件。
+
+### 1.2 Apache APISIX 多语言支持架构图
+
+![2021-06-21-1](../static/img/blog_img/2021-06-21-1.png)
+
+上图左边是 Apache APISIX 的工作流程,右边的 plugin runner 是指插件运行器,泛指多语言支持的项目。本文档下面提到的 apisix-java-plugin-runner 项目就是支持 Java 语言的 plugin runner。
+
+当你在 Apache APISIX 中配置一个 plugin runner 时,Apache APISIX 会启动一个子进程运行 plugin runner,该子进程与 Apache APISIX 进程属于同一个用户。当我们重启或重新加载 Apache APISIX 时,plugin runner 也将被重启。
+
+如果你为一个给定的路由配置了 ext-plugin-* 插件,击中该路由的请求将触发  Apache APISIX,通过 unix socket 向 plugin runner 执行 RPC 调用。调用细分为两个阶段:
+
+- ext-plugin-pre-req: 在执行 Apache APISIX 内置插件(Lua 语言插件)之前
+- ext-plugin-post-req: 在执行 Apache APISIX 内置插件(Lua 语言插件)之后
+
+根据需要配置 plugin runner 的执行时机。
+
+plugin runner 会处理 RPC 调用,在其内部创建一个模拟请求,然后运行多语言编写的插件,并将结果返回给 Apache APISIX。
+
+多语言插件的执行顺序是在 ext-plugin-* 插件配置项中定义的。像其他插件一样,它们可以被启用并在运行中重新定义。
+
+## 2. 搭建开发环境
+
+首先需要搭建 Apache APISIX 的运行环境或者开发环境,参考 [构建 Apache APISIX](https://github.com/apache/apisix/blob/master/docs/zh/latest/how-to-build.md),以及 Java 项目的开发环境,参考 [构建 apisix-java-plugin-runner](https://github.com/apache/apisix-java-plugin-runner/blob/main/docs/development.md)。
+
+**注意**:Apache APISIX 和 apisix-java-plugin-runner 需要位于同一实例上。
+
+## 3. 进入调试模式
+
+### 3.1 设置 Apache APISIX 进入调试模式
+
+这里是指让 Apache APISIX 以调试的方式运行外部插件,在 `config.yaml` 中增加以下配置
+
+```text
+ext-plugin:
+  path_for_test: /tmp/runner.sock
+```
+
+这个配置的意思是,Apache APISIX  相当于 client 端,会监听位于 `/tmp/runner.sock` 位置上的 Unxi Domain Socket 链接。
+
+### 3.2 设置 apisix-java-plugin-runner 进入调试模式
+
+在启动 `Main class(org.apache.apisix.plugin.runner.PluginRunnerApplication)`之前,需要配置用户级的环境变量 `APISIX_LISTEN_ADDRESS=unix:/tmp/runner.sock` 和 `APISIX_CONF_EXPIRE_TIME=3600`。
+
+如果你是使用 IDEA 进行开发,那么配置好的环境变量示意如下:
+
+![2021-06-21-2](../static/img/blog_img/2021-06-21-2.png)
+
+apisix-java-plugin-runner 相当于 server 端,在启动时会主动创建 `/tmp/runner.sock` 文件,并在这个文件上与 Apache APISIX 进行 Unix Domain Socket 通信。
+
+## 4. 开发
+
+### 4.1 场景
+
+我们以一个场景来代入开发过程:需要验证请求 header 中 token 的有效性,验证 token 的方式是用请求中携带 token 作为参数,访问 SSO 固定的接口,如果 token 验证通过则放行请求,验证失败则阻止请求。
+
+### 4.2 配置 Apache APISIX
+
+先给插件命名为 `TokenValidator`,然后设计属性,为了尽可能做到动态配置,属性设计如下
+
+```text
+{
+  "validate_header": "token",
+  "validate_url": "https://www.sso.foo.com/token/validate",
+  "rejected_code": "403"
+}
+```
+
+启动 Apache APISIX,然后新增一条路由配置,指定该路由需要调用 apisix-java-plugin-runner 的 `TokenValidator` 插件,示例如下
+
+```text
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
+{
+    "uri":"/get",
+    "plugins":{
+        "ext-plugin-pre-req":{
+            "conf":[
+                {
+                    "name":"TokenValidator",
+                    "value":"{\"validate_header\":\"token\",\"validate_url\":\"https://www.sso.foo.com/token/validate\",\"rejected_code\":\"403\"}"
+                }
+            ]
+        }
+    },
+    "upstream":{
+        "nodes":{
+            "httpbin.org:80":1
+        },
+        "type":"roundrobin"
+    }
+}
+```
+
+需要注意的是,`TokenValidator` 的属性需要经过 json 转义,作为 string 类型进行配置。
+
+(这里上游地址配置为 httpbin.org,方便调试)
+
+### 4.3 开发 Java 插件
+
+在 runner-plugin/src/main/java/org/apache/apisix/plugin/runner/filter 目录下,新增 `TokenValidatr.java`,代码初始骨架如下
+
+```Java
+package org.apache.apisix.plugin.runner.filter;
+
+import org.apache.apisix.plugin.runner.HttpRequest;
+import org.apache.apisix.plugin.runner.HttpResponse;
+import org.springframework.stereotype.Component;
+import reactor.core.publisher.Mono;
+
+
+@Component
+public class TokenValidator implements PluginFilter {
+
+    @Override
+    public String name() {
+        return "TokenValidator";
+    }
+
+    @Override
+    public Mono<Void> filter(HttpRequest request, HttpResponse response, PluginFilterChain chain) {
+        return chain.filter(request, response);
+    }
+}
+```
+
+需要继承 `PluginFilter`接口,重写 `name` 和 `filter`函数。
+
+重写 `name` 的返回值,和前面配置 APISIX 的路由属性中 "name" 保持一致。
+
+完整代码如下:
+
+```Java
+package org.apache.apisix.plugin.runner.filter;
+
+import com.google.gson.Gson;
+import org.apache.apisix.plugin.runner.HttpRequest;
+import org.apache.apisix.plugin.runner.HttpResponse;
+import org.springframework.stereotype.Component;
+import reactor.core.publisher.Mono;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Component
+public class TokenValidator implements PluginFilter {
+
+    @Override
+    public String name() {
+        return "TokenValidator";
+    }
+
+    @Override
+    public Mono<Void> filter(HttpRequest request, HttpResponse response, PluginFilterChain chain) {
+        // parse `conf` to json
+        String configStr = request.getConfig(this);
+        Gson gson = new Gson();
+        Map<String, Object> conf = new HashMap<>();
+        conf = gson.fromJson(configStr, conf.getClass());
+
+        // get configuration parameters
+        String token = request.getHeader((String) conf.get("validate_header"));
+        String validate_url = (String) conf.get("validate_url");
+        boolean flag = validate(token, validate_url);
+
+        // token verification results
+        if (!flag) {
+            String rejected_code = (String) conf.get("rejected_code");
+            response.setStatusCode(Integer.parseInt(rejected_code));
+            return chain.filter(request, response);
+        }
+
+        return chain.filter(request, response);
+    }
+
+    private Boolean validate(String token, String validate_url) {
+        //TODO: improve the validation process
+        return true;
+    }
+}
+```
+
+### 4.4 测试
+
+在 Apache APISIX 上配置的上游服务是 httpbin.org,可以访问 Apache APISIX,触发路由,让 Apache APISIX 调用 apisix-java-plugin-runner 去执行 TokenValidator 插件,测试一下 Java 插件效果。
+
+```text
+curl -H 'token: 123456' 127.0.0.1:9080/get 
+{
+ "args": {}, 
+ "headers": {
+ "Accept": "/", 
+ "Host": "127.0.0.1", 
+ "Token": "123456", 
+ "User-Agent": "curl/7.71.1", 
+ "X-Amzn-Trace-Id": "Root=1-60cb0424-02b5bf804cfeab5252392f96", 
+ "X-Forwarded-Host": "127.0.0.1"
+ }, 
+ "origin": "127.0.0.1", 
+ "url": "http://127.0.0.1/get"
+}
+```
+
+## 5. 部署
+
+插件开发完成后,部署操作可以参考 [部署 apisix-java-plugin-runner](https://github.com/apache/apisix-java-plugin-runner/blob/main/docs/how-it-works.md#run)。
+
+## 6. 视频教程
+<iframe 
+    height="350" 
+    width="600" 
+    src="../static/video/2021-06-21-use-Java-to-write-Apache-APISIX-plugins.mp4" 

Review comment:
       Chiming in. How about uploading this video to APISIX youtube and then making a plug of that here, what do you think ?




-- 
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.

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



[GitHub] [apisix-website] netlify[bot] edited a comment on pull request #372: docs:added use Java to write Apache APISIX plugins blog

Posted by GitBox <gi...@apache.org>.
netlify[bot] edited a comment on pull request #372:
URL: https://github.com/apache/apisix-website/pull/372#issuecomment-864999758


   :construction_worker: Deploy Preview for *apisix* processing.
   
   
   :hammer: Explore the source changes: da6d32542dfdbfe17674c20b76371960c8f69015
   
   :mag: Inspect the deploy log: [https://app.netlify.com/sites/apisix/deploys/60d1415975d50c000887e550](https://app.netlify.com/sites/apisix/deploys/60d1415975d50c000887e550?utm_source=github&utm_campaign=bot_dl)
   


-- 
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.

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



[GitHub] [apisix-website] 1502shivam-singh commented on a change in pull request #372: docs:added use Java to write Apache APISIX plugins blog

Posted by GitBox <gi...@apache.org>.
1502shivam-singh commented on a change in pull request #372:
URL: https://github.com/apache/apisix-website/pull/372#discussion_r655616956



##########
File path: website/blog/2021-06-21-use-Java-to-write-Apache-APISIX-plugins.md
##########
@@ -0,0 +1,233 @@
+---
+title: "使用 Java 编写 Apache APISIX 插件"
+author: Zhengsong Tu
+authorURL: "https://github.com/tzssangglass"
+authorImageURL: "https://avatars.githubusercontent.com/u/30819887?v=4"
+---
+> [@tzssangglass](https://github.com/tzssangglass), Apache APISIX contributor from [Shenzhen Zhiliu Technology Co.](https://www.apiseven.com/)
+>
+
+<!--truncate-->
+Apache APISIX 支持多语言编写插件了!不会 Lua 也没关系,现在可以用你熟悉的语言编写插件,文末还有**视频教程**。
+
+## 1. 简介
+
+### 1.1 为什么 Apache APISIX 要支持多语言编写插件
+
+在支持多语言编程插件前,Apache APISIX 只支持使用 Lua 语言编写插件,需要开发者掌握 Lua 和 OpenResty 相关的开发能力。然而相对于主流开发语言 Java、Go 来说,Lua 和 OpenResty 属于相对小众的技术,开发者很少。如果从头开始学习 Lua 和 OpenResty,需要付出相当多的时间和精力。
+
+开发团队在进行技术选型的时候,最重要的考量就是所选技术是否与本团队技术栈相匹配,然而小众的技术栈就限制了 Apache APISIX 在更广阔的场景下进行技术落地。
+
+现在 Apache APISIX 支持多语言开发插件,**更重要的是支持语言所在的开发生态圈,使用者可以使用自己熟悉的技术栈来开发 Apache APISIX**。以支持 Java 为例,使用者不仅可以使用 Java 语言编写插件,还可以融入 Spring Cloud 生态圈,广泛使用生态圈内的各种技术组件。
+
+### 1.2 Apache APISIX 多语言支持架构图
+
+![2021-06-21-1](../static/img/blog_img/2021-06-21-1.png)
+
+上图左边是 Apache APISIX 的工作流程,右边的 plugin runner 是指插件运行器,泛指多语言支持的项目。本文档下面提到的 apisix-java-plugin-runner 项目就是支持 Java 语言的 plugin runner。
+
+当你在 Apache APISIX 中配置一个 plugin runner 时,Apache APISIX 会启动一个子进程运行 plugin runner,该子进程与 Apache APISIX 进程属于同一个用户。当我们重启或重新加载 Apache APISIX 时,plugin runner 也将被重启。
+
+如果你为一个给定的路由配置了 ext-plugin-* 插件,击中该路由的请求将触发  Apache APISIX,通过 unix socket 向 plugin runner 执行 RPC 调用。调用细分为两个阶段:
+
+- ext-plugin-pre-req: 在执行 Apache APISIX 内置插件(Lua 语言插件)之前
+- ext-plugin-post-req: 在执行 Apache APISIX 内置插件(Lua 语言插件)之后
+
+根据需要配置 plugin runner 的执行时机。
+
+plugin runner 会处理 RPC 调用,在其内部创建一个模拟请求,然后运行多语言编写的插件,并将结果返回给 Apache APISIX。
+
+多语言插件的执行顺序是在 ext-plugin-* 插件配置项中定义的。像其他插件一样,它们可以被启用并在运行中重新定义。
+
+## 2. 搭建开发环境
+
+首先需要搭建 Apache APISIX 的运行环境或者开发环境,参考 [构建 Apache APISIX](https://github.com/apache/apisix/blob/master/docs/zh/latest/how-to-build.md),以及 Java 项目的开发环境,参考 [构建 apisix-java-plugin-runner](https://github.com/apache/apisix-java-plugin-runner/blob/main/docs/development.md)。
+
+**注意**:Apache APISIX 和 apisix-java-plugin-runner 需要位于同一实例上。
+
+## 3. 进入调试模式
+
+### 3.1 设置 Apache APISIX 进入调试模式
+
+这里是指让 Apache APISIX 以调试的方式运行外部插件,在 `config.yaml` 中增加以下配置
+
+```text
+ext-plugin:
+  path_for_test: /tmp/runner.sock
+```
+
+这个配置的意思是,Apache APISIX  相当于 client 端,会监听位于 `/tmp/runner.sock` 位置上的 Unxi Domain Socket 链接。
+
+### 3.2 设置 apisix-java-plugin-runner 进入调试模式
+
+在启动 `Main class(org.apache.apisix.plugin.runner.PluginRunnerApplication)`之前,需要配置用户级的环境变量 `APISIX_LISTEN_ADDRESS=unix:/tmp/runner.sock` 和 `APISIX_CONF_EXPIRE_TIME=3600`。
+
+如果你是使用 IDEA 进行开发,那么配置好的环境变量示意如下:
+
+![2021-06-21-2](../static/img/blog_img/2021-06-21-2.png)
+
+apisix-java-plugin-runner 相当于 server 端,在启动时会主动创建 `/tmp/runner.sock` 文件,并在这个文件上与 Apache APISIX 进行 Unix Domain Socket 通信。
+
+## 4. 开发
+
+### 4.1 场景
+
+我们以一个场景来代入开发过程:需要验证请求 header 中 token 的有效性,验证 token 的方式是用请求中携带 token 作为参数,访问 SSO 固定的接口,如果 token 验证通过则放行请求,验证失败则阻止请求。
+
+### 4.2 配置 Apache APISIX
+
+先给插件命名为 `TokenValidator`,然后设计属性,为了尽可能做到动态配置,属性设计如下
+
+```text
+{
+  "validate_header": "token",
+  "validate_url": "https://www.sso.foo.com/token/validate",
+  "rejected_code": "403"
+}
+```
+
+启动 Apache APISIX,然后新增一条路由配置,指定该路由需要调用 apisix-java-plugin-runner 的 `TokenValidator` 插件,示例如下
+
+```text
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
+{
+    "uri":"/get",
+    "plugins":{
+        "ext-plugin-pre-req":{
+            "conf":[
+                {
+                    "name":"TokenValidator",
+                    "value":"{\"validate_header\":\"token\",\"validate_url\":\"https://www.sso.foo.com/token/validate\",\"rejected_code\":\"403\"}"
+                }
+            ]
+        }
+    },
+    "upstream":{
+        "nodes":{
+            "httpbin.org:80":1
+        },
+        "type":"roundrobin"
+    }
+}
+```
+
+需要注意的是,`TokenValidator` 的属性需要经过 json 转义,作为 string 类型进行配置。
+
+(这里上游地址配置为 httpbin.org,方便调试)
+
+### 4.3 开发 Java 插件
+
+在 runner-plugin/src/main/java/org/apache/apisix/plugin/runner/filter 目录下,新增 `TokenValidatr.java`,代码初始骨架如下
+
+```Java
+package org.apache.apisix.plugin.runner.filter;
+
+import org.apache.apisix.plugin.runner.HttpRequest;
+import org.apache.apisix.plugin.runner.HttpResponse;
+import org.springframework.stereotype.Component;
+import reactor.core.publisher.Mono;
+
+
+@Component
+public class TokenValidator implements PluginFilter {
+
+    @Override
+    public String name() {
+        return "TokenValidator";
+    }
+
+    @Override
+    public Mono<Void> filter(HttpRequest request, HttpResponse response, PluginFilterChain chain) {
+        return chain.filter(request, response);
+    }
+}
+```
+
+需要继承 `PluginFilter`接口,重写 `name` 和 `filter`函数。
+
+重写 `name` 的返回值,和前面配置 APISIX 的路由属性中 "name" 保持一致。
+
+完整代码如下:
+
+```Java
+package org.apache.apisix.plugin.runner.filter;
+
+import com.google.gson.Gson;
+import org.apache.apisix.plugin.runner.HttpRequest;
+import org.apache.apisix.plugin.runner.HttpResponse;
+import org.springframework.stereotype.Component;
+import reactor.core.publisher.Mono;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Component
+public class TokenValidator implements PluginFilter {
+
+    @Override
+    public String name() {
+        return "TokenValidator";
+    }
+
+    @Override
+    public Mono<Void> filter(HttpRequest request, HttpResponse response, PluginFilterChain chain) {
+        // parse `conf` to json
+        String configStr = request.getConfig(this);
+        Gson gson = new Gson();
+        Map<String, Object> conf = new HashMap<>();
+        conf = gson.fromJson(configStr, conf.getClass());
+
+        // get configuration parameters
+        String token = request.getHeader((String) conf.get("validate_header"));
+        String validate_url = (String) conf.get("validate_url");
+        boolean flag = validate(token, validate_url);
+
+        // token verification results
+        if (!flag) {
+            String rejected_code = (String) conf.get("rejected_code");
+            response.setStatusCode(Integer.parseInt(rejected_code));
+            return chain.filter(request, response);
+        }
+
+        return chain.filter(request, response);
+    }
+
+    private Boolean validate(String token, String validate_url) {
+        //TODO: improve the validation process
+        return true;
+    }
+}
+```
+
+### 4.4 测试
+
+在 Apache APISIX 上配置的上游服务是 httpbin.org,可以访问 Apache APISIX,触发路由,让 Apache APISIX 调用 apisix-java-plugin-runner 去执行 TokenValidator 插件,测试一下 Java 插件效果。
+
+```text
+curl -H 'token: 123456' 127.0.0.1:9080/get 
+{
+ "args": {}, 
+ "headers": {
+ "Accept": "/", 
+ "Host": "127.0.0.1", 
+ "Token": "123456", 
+ "User-Agent": "curl/7.71.1", 
+ "X-Amzn-Trace-Id": "Root=1-60cb0424-02b5bf804cfeab5252392f96", 
+ "X-Forwarded-Host": "127.0.0.1"
+ }, 
+ "origin": "127.0.0.1", 
+ "url": "http://127.0.0.1/get"
+}
+```
+
+## 5. 部署
+
+插件开发完成后,部署操作可以参考 [部署 apisix-java-plugin-runner](https://github.com/apache/apisix-java-plugin-runner/blob/main/docs/how-it-works.md#run)。
+
+## 6. 视频教程
+<iframe 
+    height="350" 
+    width="600" 
+    src="../static/video/2021-06-21-use-Java-to-write-Apache-APISIX-plugins.mp4" 

Review comment:
       Chiming in. How about uploading this video to APISIX youtube and then making a plug of that here, what do you think ?

##########
File path: website/blog/2021-06-21-use-Java-to-write-Apache-APISIX-plugins.md
##########
@@ -0,0 +1,233 @@
+---
+title: "使用 Java 编写 Apache APISIX 插件"
+author: Zhengsong Tu
+authorURL: "https://github.com/tzssangglass"
+authorImageURL: "https://avatars.githubusercontent.com/u/30819887?v=4"
+---
+> [@tzssangglass](https://github.com/tzssangglass), Apache APISIX contributor from [Shenzhen Zhiliu Technology Co.](https://www.apiseven.com/)
+>
+
+<!--truncate-->
+Apache APISIX 支持多语言编写插件了!不会 Lua 也没关系,现在可以用你熟悉的语言编写插件,文末还有**视频教程**。
+
+## 1. 简介
+
+### 1.1 为什么 Apache APISIX 要支持多语言编写插件
+
+在支持多语言编程插件前,Apache APISIX 只支持使用 Lua 语言编写插件,需要开发者掌握 Lua 和 OpenResty 相关的开发能力。然而相对于主流开发语言 Java、Go 来说,Lua 和 OpenResty 属于相对小众的技术,开发者很少。如果从头开始学习 Lua 和 OpenResty,需要付出相当多的时间和精力。
+
+开发团队在进行技术选型的时候,最重要的考量就是所选技术是否与本团队技术栈相匹配,然而小众的技术栈就限制了 Apache APISIX 在更广阔的场景下进行技术落地。
+
+现在 Apache APISIX 支持多语言开发插件,**更重要的是支持语言所在的开发生态圈,使用者可以使用自己熟悉的技术栈来开发 Apache APISIX**。以支持 Java 为例,使用者不仅可以使用 Java 语言编写插件,还可以融入 Spring Cloud 生态圈,广泛使用生态圈内的各种技术组件。
+
+### 1.2 Apache APISIX 多语言支持架构图
+
+![2021-06-21-1](../static/img/blog_img/2021-06-21-1.png)
+
+上图左边是 Apache APISIX 的工作流程,右边的 plugin runner 是指插件运行器,泛指多语言支持的项目。本文档下面提到的 apisix-java-plugin-runner 项目就是支持 Java 语言的 plugin runner。
+
+当你在 Apache APISIX 中配置一个 plugin runner 时,Apache APISIX 会启动一个子进程运行 plugin runner,该子进程与 Apache APISIX 进程属于同一个用户。当我们重启或重新加载 Apache APISIX 时,plugin runner 也将被重启。
+
+如果你为一个给定的路由配置了 ext-plugin-* 插件,击中该路由的请求将触发  Apache APISIX,通过 unix socket 向 plugin runner 执行 RPC 调用。调用细分为两个阶段:
+
+- ext-plugin-pre-req: 在执行 Apache APISIX 内置插件(Lua 语言插件)之前
+- ext-plugin-post-req: 在执行 Apache APISIX 内置插件(Lua 语言插件)之后
+
+根据需要配置 plugin runner 的执行时机。
+
+plugin runner 会处理 RPC 调用,在其内部创建一个模拟请求,然后运行多语言编写的插件,并将结果返回给 Apache APISIX。
+
+多语言插件的执行顺序是在 ext-plugin-* 插件配置项中定义的。像其他插件一样,它们可以被启用并在运行中重新定义。
+
+## 2. 搭建开发环境
+
+首先需要搭建 Apache APISIX 的运行环境或者开发环境,参考 [构建 Apache APISIX](https://github.com/apache/apisix/blob/master/docs/zh/latest/how-to-build.md),以及 Java 项目的开发环境,参考 [构建 apisix-java-plugin-runner](https://github.com/apache/apisix-java-plugin-runner/blob/main/docs/development.md)。
+
+**注意**:Apache APISIX 和 apisix-java-plugin-runner 需要位于同一实例上。
+
+## 3. 进入调试模式
+
+### 3.1 设置 Apache APISIX 进入调试模式
+
+这里是指让 Apache APISIX 以调试的方式运行外部插件,在 `config.yaml` 中增加以下配置
+
+```text
+ext-plugin:
+  path_for_test: /tmp/runner.sock
+```
+
+这个配置的意思是,Apache APISIX  相当于 client 端,会监听位于 `/tmp/runner.sock` 位置上的 Unxi Domain Socket 链接。
+
+### 3.2 设置 apisix-java-plugin-runner 进入调试模式
+
+在启动 `Main class(org.apache.apisix.plugin.runner.PluginRunnerApplication)`之前,需要配置用户级的环境变量 `APISIX_LISTEN_ADDRESS=unix:/tmp/runner.sock` 和 `APISIX_CONF_EXPIRE_TIME=3600`。
+
+如果你是使用 IDEA 进行开发,那么配置好的环境变量示意如下:
+
+![2021-06-21-2](../static/img/blog_img/2021-06-21-2.png)
+
+apisix-java-plugin-runner 相当于 server 端,在启动时会主动创建 `/tmp/runner.sock` 文件,并在这个文件上与 Apache APISIX 进行 Unix Domain Socket 通信。
+
+## 4. 开发
+
+### 4.1 场景
+
+我们以一个场景来代入开发过程:需要验证请求 header 中 token 的有效性,验证 token 的方式是用请求中携带 token 作为参数,访问 SSO 固定的接口,如果 token 验证通过则放行请求,验证失败则阻止请求。
+
+### 4.2 配置 Apache APISIX
+
+先给插件命名为 `TokenValidator`,然后设计属性,为了尽可能做到动态配置,属性设计如下
+
+```text
+{
+  "validate_header": "token",
+  "validate_url": "https://www.sso.foo.com/token/validate",
+  "rejected_code": "403"
+}
+```
+
+启动 Apache APISIX,然后新增一条路由配置,指定该路由需要调用 apisix-java-plugin-runner 的 `TokenValidator` 插件,示例如下
+
+```text
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
+{
+    "uri":"/get",
+    "plugins":{
+        "ext-plugin-pre-req":{
+            "conf":[
+                {
+                    "name":"TokenValidator",
+                    "value":"{\"validate_header\":\"token\",\"validate_url\":\"https://www.sso.foo.com/token/validate\",\"rejected_code\":\"403\"}"
+                }
+            ]
+        }
+    },
+    "upstream":{
+        "nodes":{
+            "httpbin.org:80":1
+        },
+        "type":"roundrobin"
+    }
+}
+```
+
+需要注意的是,`TokenValidator` 的属性需要经过 json 转义,作为 string 类型进行配置。
+
+(这里上游地址配置为 httpbin.org,方便调试)
+
+### 4.3 开发 Java 插件
+
+在 runner-plugin/src/main/java/org/apache/apisix/plugin/runner/filter 目录下,新增 `TokenValidatr.java`,代码初始骨架如下
+
+```Java
+package org.apache.apisix.plugin.runner.filter;
+
+import org.apache.apisix.plugin.runner.HttpRequest;
+import org.apache.apisix.plugin.runner.HttpResponse;
+import org.springframework.stereotype.Component;
+import reactor.core.publisher.Mono;
+
+
+@Component
+public class TokenValidator implements PluginFilter {
+
+    @Override
+    public String name() {
+        return "TokenValidator";
+    }
+
+    @Override
+    public Mono<Void> filter(HttpRequest request, HttpResponse response, PluginFilterChain chain) {
+        return chain.filter(request, response);
+    }
+}
+```
+
+需要继承 `PluginFilter`接口,重写 `name` 和 `filter`函数。
+
+重写 `name` 的返回值,和前面配置 APISIX 的路由属性中 "name" 保持一致。
+
+完整代码如下:
+
+```Java
+package org.apache.apisix.plugin.runner.filter;
+
+import com.google.gson.Gson;
+import org.apache.apisix.plugin.runner.HttpRequest;
+import org.apache.apisix.plugin.runner.HttpResponse;
+import org.springframework.stereotype.Component;
+import reactor.core.publisher.Mono;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Component
+public class TokenValidator implements PluginFilter {
+
+    @Override
+    public String name() {
+        return "TokenValidator";
+    }
+
+    @Override
+    public Mono<Void> filter(HttpRequest request, HttpResponse response, PluginFilterChain chain) {
+        // parse `conf` to json
+        String configStr = request.getConfig(this);
+        Gson gson = new Gson();
+        Map<String, Object> conf = new HashMap<>();
+        conf = gson.fromJson(configStr, conf.getClass());
+
+        // get configuration parameters
+        String token = request.getHeader((String) conf.get("validate_header"));
+        String validate_url = (String) conf.get("validate_url");
+        boolean flag = validate(token, validate_url);
+
+        // token verification results
+        if (!flag) {
+            String rejected_code = (String) conf.get("rejected_code");
+            response.setStatusCode(Integer.parseInt(rejected_code));
+            return chain.filter(request, response);
+        }
+
+        return chain.filter(request, response);
+    }
+
+    private Boolean validate(String token, String validate_url) {
+        //TODO: improve the validation process
+        return true;
+    }
+}
+```
+
+### 4.4 测试
+
+在 Apache APISIX 上配置的上游服务是 httpbin.org,可以访问 Apache APISIX,触发路由,让 Apache APISIX 调用 apisix-java-plugin-runner 去执行 TokenValidator 插件,测试一下 Java 插件效果。
+
+```text
+curl -H 'token: 123456' 127.0.0.1:9080/get 
+{
+ "args": {}, 
+ "headers": {
+ "Accept": "/", 
+ "Host": "127.0.0.1", 
+ "Token": "123456", 
+ "User-Agent": "curl/7.71.1", 
+ "X-Amzn-Trace-Id": "Root=1-60cb0424-02b5bf804cfeab5252392f96", 
+ "X-Forwarded-Host": "127.0.0.1"
+ }, 
+ "origin": "127.0.0.1", 
+ "url": "http://127.0.0.1/get"
+}
+```
+
+## 5. 部署
+
+插件开发完成后,部署操作可以参考 [部署 apisix-java-plugin-runner](https://github.com/apache/apisix-java-plugin-runner/blob/main/docs/how-it-works.md#run)。
+
+## 6. 视频教程
+<iframe 
+    height="350" 
+    width="600" 
+    src="../static/video/2021-06-21-use-Java-to-write-Apache-APISIX-plugins.mp4" 

Review comment:
       Chiming in. How about uploading this video to APISIX youtube or vimeo and then making a plug of that here, what do you think ?




-- 
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.

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



[GitHub] [apisix-website] Serendipity96 commented on a change in pull request #372: docs: added use Java to write Apache APISIX plugins blog

Posted by GitBox <gi...@apache.org>.
Serendipity96 commented on a change in pull request #372:
URL: https://github.com/apache/apisix-website/pull/372#discussion_r655822722



##########
File path: website/blog/2021-06-21-use-Java-to-write-Apache-APISIX-plugins.md
##########
@@ -0,0 +1,233 @@
+---
+title: "使用 Java 编写 Apache APISIX 插件"
+author: Zhengsong Tu
+authorURL: "https://github.com/tzssangglass"
+authorImageURL: "https://avatars.githubusercontent.com/u/30819887?v=4"
+---
+> [@tzssangglass](https://github.com/tzssangglass), Apache APISIX contributor from [Shenzhen Zhiliu Technology Co.](https://www.apiseven.com/)
+>
+
+<!--truncate-->
+Apache APISIX 支持多语言编写插件了!不会 Lua 也没关系,现在可以用你熟悉的语言编写插件,文末还有**视频教程**。
+
+## 1. 简介
+
+### 1.1 为什么 Apache APISIX 要支持多语言编写插件
+
+在支持多语言编程插件前,Apache APISIX 只支持使用 Lua 语言编写插件,需要开发者掌握 Lua 和 OpenResty 相关的开发能力。然而相对于主流开发语言 Java、Go 来说,Lua 和 OpenResty 属于相对小众的技术,开发者很少。如果从头开始学习 Lua 和 OpenResty,需要付出相当多的时间和精力。
+
+开发团队在进行技术选型的时候,最重要的考量就是所选技术是否与本团队技术栈相匹配,然而小众的技术栈就限制了 Apache APISIX 在更广阔的场景下进行技术落地。
+
+现在 Apache APISIX 支持多语言开发插件,**更重要的是支持语言所在的开发生态圈,使用者可以使用自己熟悉的技术栈来开发 Apache APISIX**。以支持 Java 为例,使用者不仅可以使用 Java 语言编写插件,还可以融入 Spring Cloud 生态圈,广泛使用生态圈内的各种技术组件。
+
+### 1.2 Apache APISIX 多语言支持架构图
+
+![2021-06-21-1](../static/img/blog_img/2021-06-21-1.png)
+
+上图左边是 Apache APISIX 的工作流程,右边的 plugin runner 是指插件运行器,泛指多语言支持的项目。本文档下面提到的 apisix-java-plugin-runner 项目就是支持 Java 语言的 plugin runner。
+
+当你在 Apache APISIX 中配置一个 plugin runner 时,Apache APISIX 会启动一个子进程运行 plugin runner,该子进程与 Apache APISIX 进程属于同一个用户。当我们重启或重新加载 Apache APISIX 时,plugin runner 也将被重启。
+
+如果你为一个给定的路由配置了 ext-plugin-* 插件,击中该路由的请求将触发  Apache APISIX,通过 unix socket 向 plugin runner 执行 RPC 调用。调用细分为两个阶段:
+
+- ext-plugin-pre-req: 在执行 Apache APISIX 内置插件(Lua 语言插件)之前
+- ext-plugin-post-req: 在执行 Apache APISIX 内置插件(Lua 语言插件)之后
+
+根据需要配置 plugin runner 的执行时机。
+
+plugin runner 会处理 RPC 调用,在其内部创建一个模拟请求,然后运行多语言编写的插件,并将结果返回给 Apache APISIX。
+
+多语言插件的执行顺序是在 ext-plugin-* 插件配置项中定义的。像其他插件一样,它们可以被启用并在运行中重新定义。
+
+## 2. 搭建开发环境
+
+首先需要搭建 Apache APISIX 的运行环境或者开发环境,参考 [构建 Apache APISIX](https://github.com/apache/apisix/blob/master/docs/zh/latest/how-to-build.md),以及 Java 项目的开发环境,参考 [构建 apisix-java-plugin-runner](https://github.com/apache/apisix-java-plugin-runner/blob/main/docs/development.md)。
+
+**注意**:Apache APISIX 和 apisix-java-plugin-runner 需要位于同一实例上。
+
+## 3. 进入调试模式
+
+### 3.1 设置 Apache APISIX 进入调试模式
+
+这里是指让 Apache APISIX 以调试的方式运行外部插件,在 `config.yaml` 中增加以下配置
+
+```text
+ext-plugin:
+  path_for_test: /tmp/runner.sock
+```
+
+这个配置的意思是,Apache APISIX  相当于 client 端,会监听位于 `/tmp/runner.sock` 位置上的 Unxi Domain Socket 链接。
+
+### 3.2 设置 apisix-java-plugin-runner 进入调试模式
+
+在启动 `Main class(org.apache.apisix.plugin.runner.PluginRunnerApplication)`之前,需要配置用户级的环境变量 `APISIX_LISTEN_ADDRESS=unix:/tmp/runner.sock` 和 `APISIX_CONF_EXPIRE_TIME=3600`。
+
+如果你是使用 IDEA 进行开发,那么配置好的环境变量示意如下:
+
+![2021-06-21-2](../static/img/blog_img/2021-06-21-2.png)
+
+apisix-java-plugin-runner 相当于 server 端,在启动时会主动创建 `/tmp/runner.sock` 文件,并在这个文件上与 Apache APISIX 进行 Unix Domain Socket 通信。
+
+## 4. 开发
+
+### 4.1 场景
+
+我们以一个场景来代入开发过程:需要验证请求 header 中 token 的有效性,验证 token 的方式是用请求中携带 token 作为参数,访问 SSO 固定的接口,如果 token 验证通过则放行请求,验证失败则阻止请求。
+
+### 4.2 配置 Apache APISIX
+
+先给插件命名为 `TokenValidator`,然后设计属性,为了尽可能做到动态配置,属性设计如下
+
+```text
+{
+  "validate_header": "token",
+  "validate_url": "https://www.sso.foo.com/token/validate",
+  "rejected_code": "403"
+}
+```
+
+启动 Apache APISIX,然后新增一条路由配置,指定该路由需要调用 apisix-java-plugin-runner 的 `TokenValidator` 插件,示例如下
+
+```text
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
+{
+    "uri":"/get",
+    "plugins":{
+        "ext-plugin-pre-req":{
+            "conf":[
+                {
+                    "name":"TokenValidator",
+                    "value":"{\"validate_header\":\"token\",\"validate_url\":\"https://www.sso.foo.com/token/validate\",\"rejected_code\":\"403\"}"
+                }
+            ]
+        }
+    },
+    "upstream":{
+        "nodes":{
+            "httpbin.org:80":1
+        },
+        "type":"roundrobin"
+    }
+}
+```
+
+需要注意的是,`TokenValidator` 的属性需要经过 json 转义,作为 string 类型进行配置。
+
+(这里上游地址配置为 httpbin.org,方便调试)
+
+### 4.3 开发 Java 插件
+
+在 runner-plugin/src/main/java/org/apache/apisix/plugin/runner/filter 目录下,新增 `TokenValidatr.java`,代码初始骨架如下
+
+```Java
+package org.apache.apisix.plugin.runner.filter;
+
+import org.apache.apisix.plugin.runner.HttpRequest;
+import org.apache.apisix.plugin.runner.HttpResponse;
+import org.springframework.stereotype.Component;
+import reactor.core.publisher.Mono;
+
+
+@Component
+public class TokenValidator implements PluginFilter {
+
+    @Override
+    public String name() {
+        return "TokenValidator";
+    }
+
+    @Override
+    public Mono<Void> filter(HttpRequest request, HttpResponse response, PluginFilterChain chain) {
+        return chain.filter(request, response);
+    }
+}
+```
+
+需要继承 `PluginFilter`接口,重写 `name` 和 `filter`函数。
+
+重写 `name` 的返回值,和前面配置 APISIX 的路由属性中 "name" 保持一致。
+
+完整代码如下:
+
+```Java
+package org.apache.apisix.plugin.runner.filter;
+
+import com.google.gson.Gson;
+import org.apache.apisix.plugin.runner.HttpRequest;
+import org.apache.apisix.plugin.runner.HttpResponse;
+import org.springframework.stereotype.Component;
+import reactor.core.publisher.Mono;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Component
+public class TokenValidator implements PluginFilter {
+
+    @Override
+    public String name() {
+        return "TokenValidator";
+    }
+
+    @Override
+    public Mono<Void> filter(HttpRequest request, HttpResponse response, PluginFilterChain chain) {
+        // parse `conf` to json
+        String configStr = request.getConfig(this);
+        Gson gson = new Gson();
+        Map<String, Object> conf = new HashMap<>();
+        conf = gson.fromJson(configStr, conf.getClass());
+
+        // get configuration parameters
+        String token = request.getHeader((String) conf.get("validate_header"));
+        String validate_url = (String) conf.get("validate_url");
+        boolean flag = validate(token, validate_url);
+
+        // token verification results
+        if (!flag) {
+            String rejected_code = (String) conf.get("rejected_code");
+            response.setStatusCode(Integer.parseInt(rejected_code));
+            return chain.filter(request, response);
+        }
+
+        return chain.filter(request, response);
+    }
+
+    private Boolean validate(String token, String validate_url) {
+        //TODO: improve the validation process
+        return true;
+    }
+}
+```
+
+### 4.4 测试
+
+在 Apache APISIX 上配置的上游服务是 httpbin.org,可以访问 Apache APISIX,触发路由,让 Apache APISIX 调用 apisix-java-plugin-runner 去执行 TokenValidator 插件,测试一下 Java 插件效果。
+
+```text
+curl -H 'token: 123456' 127.0.0.1:9080/get 
+{
+ "args": {}, 
+ "headers": {
+ "Accept": "/", 
+ "Host": "127.0.0.1", 
+ "Token": "123456", 
+ "User-Agent": "curl/7.71.1", 
+ "X-Amzn-Trace-Id": "Root=1-60cb0424-02b5bf804cfeab5252392f96", 
+ "X-Forwarded-Host": "127.0.0.1"
+ }, 
+ "origin": "127.0.0.1", 
+ "url": "http://127.0.0.1/get"
+}
+```
+
+## 5. 部署
+
+插件开发完成后,部署操作可以参考 [部署 apisix-java-plugin-runner](https://github.com/apache/apisix-java-plugin-runner/blob/main/docs/how-it-works.md#run)。
+
+## 6. 视频教程
+<iframe 
+    height="350" 
+    width="600" 
+    src="../static/video/2021-06-21-use-Java-to-write-Apache-APISIX-plugins.mp4" 

Review comment:
       thanks




-- 
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.

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



[GitHub] [apisix-website] netlify[bot] edited a comment on pull request #372: docs: added use Java to write Apache APISIX plugins blog

Posted by GitBox <gi...@apache.org>.
netlify[bot] edited a comment on pull request #372:
URL: https://github.com/apache/apisix-website/pull/372#issuecomment-864999758


   :construction_worker: Deploy Preview for *apisix* processing.
   
   
   :hammer: Explore the source changes: 4cb07f89a812212ff0f019cdee4be20c67af61f2
   
   :mag: Inspect the deploy log: [https://app.netlify.com/sites/apisix/deploys/60d15eb47881b10008a2d41c](https://app.netlify.com/sites/apisix/deploys/60d15eb47881b10008a2d41c?utm_source=github&utm_campaign=bot_dl)
   


-- 
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.

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



[GitHub] [apisix-website] 1502shivam-singh commented on a change in pull request #372: docs:added use Java to write Apache APISIX plugins blog

Posted by GitBox <gi...@apache.org>.
1502shivam-singh commented on a change in pull request #372:
URL: https://github.com/apache/apisix-website/pull/372#discussion_r655616956



##########
File path: website/blog/2021-06-21-use-Java-to-write-Apache-APISIX-plugins.md
##########
@@ -0,0 +1,233 @@
+---
+title: "使用 Java 编写 Apache APISIX 插件"
+author: Zhengsong Tu
+authorURL: "https://github.com/tzssangglass"
+authorImageURL: "https://avatars.githubusercontent.com/u/30819887?v=4"
+---
+> [@tzssangglass](https://github.com/tzssangglass), Apache APISIX contributor from [Shenzhen Zhiliu Technology Co.](https://www.apiseven.com/)
+>
+
+<!--truncate-->
+Apache APISIX 支持多语言编写插件了!不会 Lua 也没关系,现在可以用你熟悉的语言编写插件,文末还有**视频教程**。
+
+## 1. 简介
+
+### 1.1 为什么 Apache APISIX 要支持多语言编写插件
+
+在支持多语言编程插件前,Apache APISIX 只支持使用 Lua 语言编写插件,需要开发者掌握 Lua 和 OpenResty 相关的开发能力。然而相对于主流开发语言 Java、Go 来说,Lua 和 OpenResty 属于相对小众的技术,开发者很少。如果从头开始学习 Lua 和 OpenResty,需要付出相当多的时间和精力。
+
+开发团队在进行技术选型的时候,最重要的考量就是所选技术是否与本团队技术栈相匹配,然而小众的技术栈就限制了 Apache APISIX 在更广阔的场景下进行技术落地。
+
+现在 Apache APISIX 支持多语言开发插件,**更重要的是支持语言所在的开发生态圈,使用者可以使用自己熟悉的技术栈来开发 Apache APISIX**。以支持 Java 为例,使用者不仅可以使用 Java 语言编写插件,还可以融入 Spring Cloud 生态圈,广泛使用生态圈内的各种技术组件。
+
+### 1.2 Apache APISIX 多语言支持架构图
+
+![2021-06-21-1](../static/img/blog_img/2021-06-21-1.png)
+
+上图左边是 Apache APISIX 的工作流程,右边的 plugin runner 是指插件运行器,泛指多语言支持的项目。本文档下面提到的 apisix-java-plugin-runner 项目就是支持 Java 语言的 plugin runner。
+
+当你在 Apache APISIX 中配置一个 plugin runner 时,Apache APISIX 会启动一个子进程运行 plugin runner,该子进程与 Apache APISIX 进程属于同一个用户。当我们重启或重新加载 Apache APISIX 时,plugin runner 也将被重启。
+
+如果你为一个给定的路由配置了 ext-plugin-* 插件,击中该路由的请求将触发  Apache APISIX,通过 unix socket 向 plugin runner 执行 RPC 调用。调用细分为两个阶段:
+
+- ext-plugin-pre-req: 在执行 Apache APISIX 内置插件(Lua 语言插件)之前
+- ext-plugin-post-req: 在执行 Apache APISIX 内置插件(Lua 语言插件)之后
+
+根据需要配置 plugin runner 的执行时机。
+
+plugin runner 会处理 RPC 调用,在其内部创建一个模拟请求,然后运行多语言编写的插件,并将结果返回给 Apache APISIX。
+
+多语言插件的执行顺序是在 ext-plugin-* 插件配置项中定义的。像其他插件一样,它们可以被启用并在运行中重新定义。
+
+## 2. 搭建开发环境
+
+首先需要搭建 Apache APISIX 的运行环境或者开发环境,参考 [构建 Apache APISIX](https://github.com/apache/apisix/blob/master/docs/zh/latest/how-to-build.md),以及 Java 项目的开发环境,参考 [构建 apisix-java-plugin-runner](https://github.com/apache/apisix-java-plugin-runner/blob/main/docs/development.md)。
+
+**注意**:Apache APISIX 和 apisix-java-plugin-runner 需要位于同一实例上。
+
+## 3. 进入调试模式
+
+### 3.1 设置 Apache APISIX 进入调试模式
+
+这里是指让 Apache APISIX 以调试的方式运行外部插件,在 `config.yaml` 中增加以下配置
+
+```text
+ext-plugin:
+  path_for_test: /tmp/runner.sock
+```
+
+这个配置的意思是,Apache APISIX  相当于 client 端,会监听位于 `/tmp/runner.sock` 位置上的 Unxi Domain Socket 链接。
+
+### 3.2 设置 apisix-java-plugin-runner 进入调试模式
+
+在启动 `Main class(org.apache.apisix.plugin.runner.PluginRunnerApplication)`之前,需要配置用户级的环境变量 `APISIX_LISTEN_ADDRESS=unix:/tmp/runner.sock` 和 `APISIX_CONF_EXPIRE_TIME=3600`。
+
+如果你是使用 IDEA 进行开发,那么配置好的环境变量示意如下:
+
+![2021-06-21-2](../static/img/blog_img/2021-06-21-2.png)
+
+apisix-java-plugin-runner 相当于 server 端,在启动时会主动创建 `/tmp/runner.sock` 文件,并在这个文件上与 Apache APISIX 进行 Unix Domain Socket 通信。
+
+## 4. 开发
+
+### 4.1 场景
+
+我们以一个场景来代入开发过程:需要验证请求 header 中 token 的有效性,验证 token 的方式是用请求中携带 token 作为参数,访问 SSO 固定的接口,如果 token 验证通过则放行请求,验证失败则阻止请求。
+
+### 4.2 配置 Apache APISIX
+
+先给插件命名为 `TokenValidator`,然后设计属性,为了尽可能做到动态配置,属性设计如下
+
+```text
+{
+  "validate_header": "token",
+  "validate_url": "https://www.sso.foo.com/token/validate",
+  "rejected_code": "403"
+}
+```
+
+启动 Apache APISIX,然后新增一条路由配置,指定该路由需要调用 apisix-java-plugin-runner 的 `TokenValidator` 插件,示例如下
+
+```text
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
+{
+    "uri":"/get",
+    "plugins":{
+        "ext-plugin-pre-req":{
+            "conf":[
+                {
+                    "name":"TokenValidator",
+                    "value":"{\"validate_header\":\"token\",\"validate_url\":\"https://www.sso.foo.com/token/validate\",\"rejected_code\":\"403\"}"
+                }
+            ]
+        }
+    },
+    "upstream":{
+        "nodes":{
+            "httpbin.org:80":1
+        },
+        "type":"roundrobin"
+    }
+}
+```
+
+需要注意的是,`TokenValidator` 的属性需要经过 json 转义,作为 string 类型进行配置。
+
+(这里上游地址配置为 httpbin.org,方便调试)
+
+### 4.3 开发 Java 插件
+
+在 runner-plugin/src/main/java/org/apache/apisix/plugin/runner/filter 目录下,新增 `TokenValidatr.java`,代码初始骨架如下
+
+```Java
+package org.apache.apisix.plugin.runner.filter;
+
+import org.apache.apisix.plugin.runner.HttpRequest;
+import org.apache.apisix.plugin.runner.HttpResponse;
+import org.springframework.stereotype.Component;
+import reactor.core.publisher.Mono;
+
+
+@Component
+public class TokenValidator implements PluginFilter {
+
+    @Override
+    public String name() {
+        return "TokenValidator";
+    }
+
+    @Override
+    public Mono<Void> filter(HttpRequest request, HttpResponse response, PluginFilterChain chain) {
+        return chain.filter(request, response);
+    }
+}
+```
+
+需要继承 `PluginFilter`接口,重写 `name` 和 `filter`函数。
+
+重写 `name` 的返回值,和前面配置 APISIX 的路由属性中 "name" 保持一致。
+
+完整代码如下:
+
+```Java
+package org.apache.apisix.plugin.runner.filter;
+
+import com.google.gson.Gson;
+import org.apache.apisix.plugin.runner.HttpRequest;
+import org.apache.apisix.plugin.runner.HttpResponse;
+import org.springframework.stereotype.Component;
+import reactor.core.publisher.Mono;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Component
+public class TokenValidator implements PluginFilter {
+
+    @Override
+    public String name() {
+        return "TokenValidator";
+    }
+
+    @Override
+    public Mono<Void> filter(HttpRequest request, HttpResponse response, PluginFilterChain chain) {
+        // parse `conf` to json
+        String configStr = request.getConfig(this);
+        Gson gson = new Gson();
+        Map<String, Object> conf = new HashMap<>();
+        conf = gson.fromJson(configStr, conf.getClass());
+
+        // get configuration parameters
+        String token = request.getHeader((String) conf.get("validate_header"));
+        String validate_url = (String) conf.get("validate_url");
+        boolean flag = validate(token, validate_url);
+
+        // token verification results
+        if (!flag) {
+            String rejected_code = (String) conf.get("rejected_code");
+            response.setStatusCode(Integer.parseInt(rejected_code));
+            return chain.filter(request, response);
+        }
+
+        return chain.filter(request, response);
+    }
+
+    private Boolean validate(String token, String validate_url) {
+        //TODO: improve the validation process
+        return true;
+    }
+}
+```
+
+### 4.4 测试
+
+在 Apache APISIX 上配置的上游服务是 httpbin.org,可以访问 Apache APISIX,触发路由,让 Apache APISIX 调用 apisix-java-plugin-runner 去执行 TokenValidator 插件,测试一下 Java 插件效果。
+
+```text
+curl -H 'token: 123456' 127.0.0.1:9080/get 
+{
+ "args": {}, 
+ "headers": {
+ "Accept": "/", 
+ "Host": "127.0.0.1", 
+ "Token": "123456", 
+ "User-Agent": "curl/7.71.1", 
+ "X-Amzn-Trace-Id": "Root=1-60cb0424-02b5bf804cfeab5252392f96", 
+ "X-Forwarded-Host": "127.0.0.1"
+ }, 
+ "origin": "127.0.0.1", 
+ "url": "http://127.0.0.1/get"
+}
+```
+
+## 5. 部署
+
+插件开发完成后,部署操作可以参考 [部署 apisix-java-plugin-runner](https://github.com/apache/apisix-java-plugin-runner/blob/main/docs/how-it-works.md#run)。
+
+## 6. 视频教程
+<iframe 
+    height="350" 
+    width="600" 
+    src="../static/video/2021-06-21-use-Java-to-write-Apache-APISIX-plugins.mp4" 

Review comment:
       Chiming in. How about uploading this video to APISIX youtube or vimeo and then making a plug of that here, what do you think ?




-- 
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.

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



[GitHub] [apisix-website] Serendipity96 commented on a change in pull request #372: docs: added use Java to write Apache APISIX plugins blog

Posted by GitBox <gi...@apache.org>.
Serendipity96 commented on a change in pull request #372:
URL: https://github.com/apache/apisix-website/pull/372#discussion_r655822722



##########
File path: website/blog/2021-06-21-use-Java-to-write-Apache-APISIX-plugins.md
##########
@@ -0,0 +1,233 @@
+---
+title: "使用 Java 编写 Apache APISIX 插件"
+author: Zhengsong Tu
+authorURL: "https://github.com/tzssangglass"
+authorImageURL: "https://avatars.githubusercontent.com/u/30819887?v=4"
+---
+> [@tzssangglass](https://github.com/tzssangglass), Apache APISIX contributor from [Shenzhen Zhiliu Technology Co.](https://www.apiseven.com/)
+>
+
+<!--truncate-->
+Apache APISIX 支持多语言编写插件了!不会 Lua 也没关系,现在可以用你熟悉的语言编写插件,文末还有**视频教程**。
+
+## 1. 简介
+
+### 1.1 为什么 Apache APISIX 要支持多语言编写插件
+
+在支持多语言编程插件前,Apache APISIX 只支持使用 Lua 语言编写插件,需要开发者掌握 Lua 和 OpenResty 相关的开发能力。然而相对于主流开发语言 Java、Go 来说,Lua 和 OpenResty 属于相对小众的技术,开发者很少。如果从头开始学习 Lua 和 OpenResty,需要付出相当多的时间和精力。
+
+开发团队在进行技术选型的时候,最重要的考量就是所选技术是否与本团队技术栈相匹配,然而小众的技术栈就限制了 Apache APISIX 在更广阔的场景下进行技术落地。
+
+现在 Apache APISIX 支持多语言开发插件,**更重要的是支持语言所在的开发生态圈,使用者可以使用自己熟悉的技术栈来开发 Apache APISIX**。以支持 Java 为例,使用者不仅可以使用 Java 语言编写插件,还可以融入 Spring Cloud 生态圈,广泛使用生态圈内的各种技术组件。
+
+### 1.2 Apache APISIX 多语言支持架构图
+
+![2021-06-21-1](../static/img/blog_img/2021-06-21-1.png)
+
+上图左边是 Apache APISIX 的工作流程,右边的 plugin runner 是指插件运行器,泛指多语言支持的项目。本文档下面提到的 apisix-java-plugin-runner 项目就是支持 Java 语言的 plugin runner。
+
+当你在 Apache APISIX 中配置一个 plugin runner 时,Apache APISIX 会启动一个子进程运行 plugin runner,该子进程与 Apache APISIX 进程属于同一个用户。当我们重启或重新加载 Apache APISIX 时,plugin runner 也将被重启。
+
+如果你为一个给定的路由配置了 ext-plugin-* 插件,击中该路由的请求将触发  Apache APISIX,通过 unix socket 向 plugin runner 执行 RPC 调用。调用细分为两个阶段:
+
+- ext-plugin-pre-req: 在执行 Apache APISIX 内置插件(Lua 语言插件)之前
+- ext-plugin-post-req: 在执行 Apache APISIX 内置插件(Lua 语言插件)之后
+
+根据需要配置 plugin runner 的执行时机。
+
+plugin runner 会处理 RPC 调用,在其内部创建一个模拟请求,然后运行多语言编写的插件,并将结果返回给 Apache APISIX。
+
+多语言插件的执行顺序是在 ext-plugin-* 插件配置项中定义的。像其他插件一样,它们可以被启用并在运行中重新定义。
+
+## 2. 搭建开发环境
+
+首先需要搭建 Apache APISIX 的运行环境或者开发环境,参考 [构建 Apache APISIX](https://github.com/apache/apisix/blob/master/docs/zh/latest/how-to-build.md),以及 Java 项目的开发环境,参考 [构建 apisix-java-plugin-runner](https://github.com/apache/apisix-java-plugin-runner/blob/main/docs/development.md)。
+
+**注意**:Apache APISIX 和 apisix-java-plugin-runner 需要位于同一实例上。
+
+## 3. 进入调试模式
+
+### 3.1 设置 Apache APISIX 进入调试模式
+
+这里是指让 Apache APISIX 以调试的方式运行外部插件,在 `config.yaml` 中增加以下配置
+
+```text
+ext-plugin:
+  path_for_test: /tmp/runner.sock
+```
+
+这个配置的意思是,Apache APISIX  相当于 client 端,会监听位于 `/tmp/runner.sock` 位置上的 Unxi Domain Socket 链接。
+
+### 3.2 设置 apisix-java-plugin-runner 进入调试模式
+
+在启动 `Main class(org.apache.apisix.plugin.runner.PluginRunnerApplication)`之前,需要配置用户级的环境变量 `APISIX_LISTEN_ADDRESS=unix:/tmp/runner.sock` 和 `APISIX_CONF_EXPIRE_TIME=3600`。
+
+如果你是使用 IDEA 进行开发,那么配置好的环境变量示意如下:
+
+![2021-06-21-2](../static/img/blog_img/2021-06-21-2.png)
+
+apisix-java-plugin-runner 相当于 server 端,在启动时会主动创建 `/tmp/runner.sock` 文件,并在这个文件上与 Apache APISIX 进行 Unix Domain Socket 通信。
+
+## 4. 开发
+
+### 4.1 场景
+
+我们以一个场景来代入开发过程:需要验证请求 header 中 token 的有效性,验证 token 的方式是用请求中携带 token 作为参数,访问 SSO 固定的接口,如果 token 验证通过则放行请求,验证失败则阻止请求。
+
+### 4.2 配置 Apache APISIX
+
+先给插件命名为 `TokenValidator`,然后设计属性,为了尽可能做到动态配置,属性设计如下
+
+```text
+{
+  "validate_header": "token",
+  "validate_url": "https://www.sso.foo.com/token/validate",
+  "rejected_code": "403"
+}
+```
+
+启动 Apache APISIX,然后新增一条路由配置,指定该路由需要调用 apisix-java-plugin-runner 的 `TokenValidator` 插件,示例如下
+
+```text
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
+{
+    "uri":"/get",
+    "plugins":{
+        "ext-plugin-pre-req":{
+            "conf":[
+                {
+                    "name":"TokenValidator",
+                    "value":"{\"validate_header\":\"token\",\"validate_url\":\"https://www.sso.foo.com/token/validate\",\"rejected_code\":\"403\"}"
+                }
+            ]
+        }
+    },
+    "upstream":{
+        "nodes":{
+            "httpbin.org:80":1
+        },
+        "type":"roundrobin"
+    }
+}
+```
+
+需要注意的是,`TokenValidator` 的属性需要经过 json 转义,作为 string 类型进行配置。
+
+(这里上游地址配置为 httpbin.org,方便调试)
+
+### 4.3 开发 Java 插件
+
+在 runner-plugin/src/main/java/org/apache/apisix/plugin/runner/filter 目录下,新增 `TokenValidatr.java`,代码初始骨架如下
+
+```Java
+package org.apache.apisix.plugin.runner.filter;
+
+import org.apache.apisix.plugin.runner.HttpRequest;
+import org.apache.apisix.plugin.runner.HttpResponse;
+import org.springframework.stereotype.Component;
+import reactor.core.publisher.Mono;
+
+
+@Component
+public class TokenValidator implements PluginFilter {
+
+    @Override
+    public String name() {
+        return "TokenValidator";
+    }
+
+    @Override
+    public Mono<Void> filter(HttpRequest request, HttpResponse response, PluginFilterChain chain) {
+        return chain.filter(request, response);
+    }
+}
+```
+
+需要继承 `PluginFilter`接口,重写 `name` 和 `filter`函数。
+
+重写 `name` 的返回值,和前面配置 APISIX 的路由属性中 "name" 保持一致。
+
+完整代码如下:
+
+```Java
+package org.apache.apisix.plugin.runner.filter;
+
+import com.google.gson.Gson;
+import org.apache.apisix.plugin.runner.HttpRequest;
+import org.apache.apisix.plugin.runner.HttpResponse;
+import org.springframework.stereotype.Component;
+import reactor.core.publisher.Mono;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Component
+public class TokenValidator implements PluginFilter {
+
+    @Override
+    public String name() {
+        return "TokenValidator";
+    }
+
+    @Override
+    public Mono<Void> filter(HttpRequest request, HttpResponse response, PluginFilterChain chain) {
+        // parse `conf` to json
+        String configStr = request.getConfig(this);
+        Gson gson = new Gson();
+        Map<String, Object> conf = new HashMap<>();
+        conf = gson.fromJson(configStr, conf.getClass());
+
+        // get configuration parameters
+        String token = request.getHeader((String) conf.get("validate_header"));
+        String validate_url = (String) conf.get("validate_url");
+        boolean flag = validate(token, validate_url);
+
+        // token verification results
+        if (!flag) {
+            String rejected_code = (String) conf.get("rejected_code");
+            response.setStatusCode(Integer.parseInt(rejected_code));
+            return chain.filter(request, response);
+        }
+
+        return chain.filter(request, response);
+    }
+
+    private Boolean validate(String token, String validate_url) {
+        //TODO: improve the validation process
+        return true;
+    }
+}
+```
+
+### 4.4 测试
+
+在 Apache APISIX 上配置的上游服务是 httpbin.org,可以访问 Apache APISIX,触发路由,让 Apache APISIX 调用 apisix-java-plugin-runner 去执行 TokenValidator 插件,测试一下 Java 插件效果。
+
+```text
+curl -H 'token: 123456' 127.0.0.1:9080/get 
+{
+ "args": {}, 
+ "headers": {
+ "Accept": "/", 
+ "Host": "127.0.0.1", 
+ "Token": "123456", 
+ "User-Agent": "curl/7.71.1", 
+ "X-Amzn-Trace-Id": "Root=1-60cb0424-02b5bf804cfeab5252392f96", 
+ "X-Forwarded-Host": "127.0.0.1"
+ }, 
+ "origin": "127.0.0.1", 
+ "url": "http://127.0.0.1/get"
+}
+```
+
+## 5. 部署
+
+插件开发完成后,部署操作可以参考 [部署 apisix-java-plugin-runner](https://github.com/apache/apisix-java-plugin-runner/blob/main/docs/how-it-works.md#run)。
+
+## 6. 视频教程
+<iframe 
+    height="350" 
+    width="600" 
+    src="../static/video/2021-06-21-use-Java-to-write-Apache-APISIX-plugins.mp4" 

Review comment:
       thanks




-- 
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.

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



[GitHub] [apisix-website] netlify[bot] edited a comment on pull request #372: docs:added use Java to write Apache APISIX plugins blog

Posted by GitBox <gi...@apache.org>.
netlify[bot] edited a comment on pull request #372:
URL: https://github.com/apache/apisix-website/pull/372#issuecomment-864999758


   :heavy_check_mark: Deploy Preview for *apisix* ready!
   
   
   :hammer: Explore the source changes: b6d42d2d56c5088e5a8b43ff73b3a3b061acaa03
   
   :mag: Inspect the deploy log: [https://app.netlify.com/sites/apisix/deploys/60d0886bd6b4ac0008efdd90](https://app.netlify.com/sites/apisix/deploys/60d0886bd6b4ac0008efdd90?utm_source=github&utm_campaign=bot_dl)
   
   :sunglasses: Browse the preview: [https://deploy-preview-372--apisix.netlify.app](https://deploy-preview-372--apisix.netlify.app?utm_source=github&utm_campaign=bot_dp)
   


-- 
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.

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



[GitHub] [apisix-website] juzhiyuan merged pull request #372: docs: added use Java to write Apache APISIX plugins blog

Posted by GitBox <gi...@apache.org>.
juzhiyuan merged pull request #372:
URL: https://github.com/apache/apisix-website/pull/372


   


-- 
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.

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



[GitHub] [apisix-website] juzhiyuan commented on a change in pull request #372: docs:added use Java to write Apache APISIX plugins blog

Posted by GitBox <gi...@apache.org>.
juzhiyuan commented on a change in pull request #372:
URL: https://github.com/apache/apisix-website/pull/372#discussion_r655425415



##########
File path: website/blog/2021-06-21-use-Java-to-write-Apache-APISIX-plugins.md
##########
@@ -0,0 +1,233 @@
+---
+title: "使用 Java 编写 Apache APISIX 插件"
+author: Zhengsong Tu
+authorURL: "https://github.com/tzssangglass"
+authorImageURL: "https://avatars.githubusercontent.com/u/30819887?v=4"
+---
+> [@tzssangglass](https://github.com/tzssangglass), Apache APISIX contributor from [Shenzhen Zhiliu Technology Co.](https://www.apiseven.com/)
+>
+
+<!--truncate-->
+Apache APISIX 支持多语言编写插件了!不会 Lua 也没关系,现在可以用你熟悉的语言编写插件,文末还有**视频教程**。
+
+## 1. 简介
+
+### 1.1 为什么 Apache APISIX 要支持多语言编写插件
+
+在支持多语言编程插件前,Apache APISIX 只支持使用 Lua 语言编写插件,需要开发者掌握 Lua 和 OpenResty 相关的开发能力。然而相对于主流开发语言 Java、Go 来说,Lua 和 OpenResty 属于相对小众的技术,开发者很少。如果从头开始学习 Lua 和 OpenResty,需要付出相当多的时间和精力。
+
+开发团队在进行技术选型的时候,最重要的考量就是所选技术是否与本团队技术栈相匹配,然而小众的技术栈就限制了 Apache APISIX 在更广阔的场景下进行技术落地。
+
+现在 Apache APISIX 支持多语言开发插件,**更重要的是支持语言所在的开发生态圈,使用者可以使用自己熟悉的技术栈来开发 Apache APISIX**。以支持 Java 为例,使用者不仅可以使用 Java 语言编写插件,还可以融入 Spring Cloud 生态圈,广泛使用生态圈内的各种技术组件。
+
+### 1.2 Apache APISIX 多语言支持架构图
+
+![2021-06-21-1](../static/img/blog_img/2021-06-21-1.png)
+
+上图左边是 Apache APISIX 的工作流程,右边的 plugin runner 是指插件运行器,泛指多语言支持的项目。本文档下面提到的 apisix-java-plugin-runner 项目就是支持 Java 语言的 plugin runner。
+
+当你在 Apache APISIX 中配置一个 plugin runner 时,Apache APISIX 会启动一个子进程运行 plugin runner,该子进程与 Apache APISIX 进程属于同一个用户。当我们重启或重新加载 Apache APISIX 时,plugin runner 也将被重启。
+
+如果你为一个给定的路由配置了 ext-plugin-* 插件,击中该路由的请求将触发  Apache APISIX,通过 unix socket 向 plugin runner 执行 RPC 调用。调用细分为两个阶段:
+
+- ext-plugin-pre-req: 在执行 Apache APISIX 内置插件(Lua 语言插件)之前
+- ext-plugin-post-req: 在执行 Apache APISIX 内置插件(Lua 语言插件)之后
+
+根据需要配置 plugin runner 的执行时机。
+
+plugin runner 会处理 RPC 调用,在其内部创建一个模拟请求,然后运行多语言编写的插件,并将结果返回给 Apache APISIX。
+
+多语言插件的执行顺序是在 ext-plugin-* 插件配置项中定义的。像其他插件一样,它们可以被启用并在运行中重新定义。
+
+## 2. 搭建开发环境
+
+首先需要搭建 Apache APISIX 的运行环境或者开发环境,参考 [构建 Apache APISIX](https://github.com/apache/apisix/blob/master/docs/zh/latest/how-to-build.md),以及 Java 项目的开发环境,参考 [构建 apisix-java-plugin-runner](https://github.com/apache/apisix-java-plugin-runner/blob/main/docs/development.md)。
+
+**注意**:Apache APISIX 和 apisix-java-plugin-runner 需要位于同一实例上。
+
+## 3. 进入调试模式
+
+### 3.1 设置 Apache APISIX 进入调试模式
+
+这里是指让 Apache APISIX 以调试的方式运行外部插件,在 `config.yaml` 中增加以下配置
+
+```text
+ext-plugin:
+  path_for_test: /tmp/runner.sock
+```
+
+这个配置的意思是,Apache APISIX  相当于 client 端,会监听位于 `/tmp/runner.sock` 位置上的 Unxi Domain Socket 链接。
+
+### 3.2 设置 apisix-java-plugin-runner 进入调试模式
+
+在启动 `Main class(org.apache.apisix.plugin.runner.PluginRunnerApplication)`之前,需要配置用户级的环境变量 `APISIX_LISTEN_ADDRESS=unix:/tmp/runner.sock` 和 `APISIX_CONF_EXPIRE_TIME=3600`。
+
+如果你是使用 IDEA 进行开发,那么配置好的环境变量示意如下:
+
+![2021-06-21-2](../static/img/blog_img/2021-06-21-2.png)
+
+apisix-java-plugin-runner 相当于 server 端,在启动时会主动创建 `/tmp/runner.sock` 文件,并在这个文件上与 Apache APISIX 进行 Unix Domain Socket 通信。
+
+## 4. 开发
+
+### 4.1 场景
+
+我们以一个场景来代入开发过程:需要验证请求 header 中 token 的有效性,验证 token 的方式是用请求中携带 token 作为参数,访问 SSO 固定的接口,如果 token 验证通过则放行请求,验证失败则阻止请求。
+
+### 4.2 配置 Apache APISIX
+
+先给插件命名为 `TokenValidator`,然后设计属性,为了尽可能做到动态配置,属性设计如下
+
+```text
+{
+  "validate_header": "token",
+  "validate_url": "https://www.sso.foo.com/token/validate",
+  "rejected_code": "403"
+}
+```
+
+启动 Apache APISIX,然后新增一条路由配置,指定该路由需要调用 apisix-java-plugin-runner 的 `TokenValidator` 插件,示例如下
+
+```text
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
+{
+    "uri":"/get",
+    "plugins":{
+        "ext-plugin-pre-req":{
+            "conf":[
+                {
+                    "name":"TokenValidator",
+                    "value":"{\"validate_header\":\"token\",\"validate_url\":\"https://www.sso.foo.com/token/validate\",\"rejected_code\":\"403\"}"
+                }
+            ]
+        }
+    },
+    "upstream":{
+        "nodes":{
+            "httpbin.org:80":1
+        },
+        "type":"roundrobin"
+    }
+}
+```
+
+需要注意的是,`TokenValidator` 的属性需要经过 json 转义,作为 string 类型进行配置。
+
+(这里上游地址配置为 httpbin.org,方便调试)
+
+### 4.3 开发 Java 插件
+
+在 runner-plugin/src/main/java/org/apache/apisix/plugin/runner/filter 目录下,新增 `TokenValidatr.java`,代码初始骨架如下
+
+```Java
+package org.apache.apisix.plugin.runner.filter;
+
+import org.apache.apisix.plugin.runner.HttpRequest;
+import org.apache.apisix.plugin.runner.HttpResponse;
+import org.springframework.stereotype.Component;
+import reactor.core.publisher.Mono;
+
+
+@Component
+public class TokenValidator implements PluginFilter {
+
+    @Override
+    public String name() {
+        return "TokenValidator";
+    }
+
+    @Override
+    public Mono<Void> filter(HttpRequest request, HttpResponse response, PluginFilterChain chain) {
+        return chain.filter(request, response);
+    }
+}
+```
+
+需要继承 `PluginFilter`接口,重写 `name` 和 `filter`函数。
+
+重写 `name` 的返回值,和前面配置 APISIX 的路由属性中 "name" 保持一致。
+
+完整代码如下:
+
+```Java
+package org.apache.apisix.plugin.runner.filter;
+
+import com.google.gson.Gson;
+import org.apache.apisix.plugin.runner.HttpRequest;
+import org.apache.apisix.plugin.runner.HttpResponse;
+import org.springframework.stereotype.Component;
+import reactor.core.publisher.Mono;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Component
+public class TokenValidator implements PluginFilter {
+
+    @Override
+    public String name() {
+        return "TokenValidator";
+    }
+
+    @Override
+    public Mono<Void> filter(HttpRequest request, HttpResponse response, PluginFilterChain chain) {
+        // parse `conf` to json
+        String configStr = request.getConfig(this);
+        Gson gson = new Gson();
+        Map<String, Object> conf = new HashMap<>();
+        conf = gson.fromJson(configStr, conf.getClass());
+
+        // get configuration parameters
+        String token = request.getHeader((String) conf.get("validate_header"));
+        String validate_url = (String) conf.get("validate_url");
+        boolean flag = validate(token, validate_url);
+
+        // token verification results
+        if (!flag) {
+            String rejected_code = (String) conf.get("rejected_code");
+            response.setStatusCode(Integer.parseInt(rejected_code));
+            return chain.filter(request, response);
+        }
+
+        return chain.filter(request, response);
+    }
+
+    private Boolean validate(String token, String validate_url) {
+        //TODO: improve the validation process
+        return true;
+    }
+}
+```
+
+### 4.4 测试
+
+在 Apache APISIX 上配置的上游服务是 httpbin.org,可以访问 Apache APISIX,触发路由,让 Apache APISIX 调用 apisix-java-plugin-runner 去执行 TokenValidator 插件,测试一下 Java 插件效果。
+
+```text
+curl -H 'token: 123456' 127.0.0.1:9080/get 
+{
+ "args": {}, 
+ "headers": {
+ "Accept": "/", 
+ "Host": "127.0.0.1", 
+ "Token": "123456", 
+ "User-Agent": "curl/7.71.1", 
+ "X-Amzn-Trace-Id": "Root=1-60cb0424-02b5bf804cfeab5252392f96", 
+ "X-Forwarded-Host": "127.0.0.1"
+ }, 
+ "origin": "127.0.0.1", 
+ "url": "http://127.0.0.1/get"
+}
+```
+
+## 5. 部署
+
+插件开发完成后,部署操作可以参考 [部署 apisix-java-plugin-runner](https://github.com/apache/apisix-java-plugin-runner/blob/main/docs/how-it-works.md#run)。
+
+## 6. 视频教程
+<iframe 
+    height="350" 
+    width="600" 
+    src="../static/video/2021-06-21-use-Java-to-write-Apache-APISIX-plugins.mp4" 

Review comment:
       Please upload this video to somewhere else, not to this repo.

##########
File path: website/blog/2021-06-21-use-Java-to-write-Apache-APISIX-plugins.md
##########
@@ -0,0 +1,233 @@
+---
+title: "使用 Java 编写 Apache APISIX 插件"
+author: Zhengsong Tu
+authorURL: "https://github.com/tzssangglass"
+authorImageURL: "https://avatars.githubusercontent.com/u/30819887?v=4"
+---
+> [@tzssangglass](https://github.com/tzssangglass), Apache APISIX contributor from [Shenzhen Zhiliu Technology Co.](https://www.apiseven.com/)
+>
+
+<!--truncate-->
+Apache APISIX 支持多语言编写插件了!不会 Lua 也没关系,现在可以用你熟悉的语言编写插件,文末还有**视频教程**。
+
+## 1. 简介
+
+### 1.1 为什么 Apache APISIX 要支持多语言编写插件
+
+在支持多语言编程插件前,Apache APISIX 只支持使用 Lua 语言编写插件,需要开发者掌握 Lua 和 OpenResty 相关的开发能力。然而相对于主流开发语言 Java、Go 来说,Lua 和 OpenResty 属于相对小众的技术,开发者很少。如果从头开始学习 Lua 和 OpenResty,需要付出相当多的时间和精力。
+
+开发团队在进行技术选型的时候,最重要的考量就是所选技术是否与本团队技术栈相匹配,然而小众的技术栈就限制了 Apache APISIX 在更广阔的场景下进行技术落地。
+
+现在 Apache APISIX 支持多语言开发插件,**更重要的是支持语言所在的开发生态圈,使用者可以使用自己熟悉的技术栈来开发 Apache APISIX**。以支持 Java 为例,使用者不仅可以使用 Java 语言编写插件,还可以融入 Spring Cloud 生态圈,广泛使用生态圈内的各种技术组件。
+
+### 1.2 Apache APISIX 多语言支持架构图
+
+![2021-06-21-1](../static/img/blog_img/2021-06-21-1.png)
+
+上图左边是 Apache APISIX 的工作流程,右边的 plugin runner 是指插件运行器,泛指多语言支持的项目。本文档下面提到的 apisix-java-plugin-runner 项目就是支持 Java 语言的 plugin runner。
+
+当你在 Apache APISIX 中配置一个 plugin runner 时,Apache APISIX 会启动一个子进程运行 plugin runner,该子进程与 Apache APISIX 进程属于同一个用户。当我们重启或重新加载 Apache APISIX 时,plugin runner 也将被重启。
+
+如果你为一个给定的路由配置了 ext-plugin-* 插件,击中该路由的请求将触发  Apache APISIX,通过 unix socket 向 plugin runner 执行 RPC 调用。调用细分为两个阶段:
+
+- ext-plugin-pre-req: 在执行 Apache APISIX 内置插件(Lua 语言插件)之前
+- ext-plugin-post-req: 在执行 Apache APISIX 内置插件(Lua 语言插件)之后
+
+根据需要配置 plugin runner 的执行时机。
+
+plugin runner 会处理 RPC 调用,在其内部创建一个模拟请求,然后运行多语言编写的插件,并将结果返回给 Apache APISIX。
+
+多语言插件的执行顺序是在 ext-plugin-* 插件配置项中定义的。像其他插件一样,它们可以被启用并在运行中重新定义。
+
+## 2. 搭建开发环境
+
+首先需要搭建 Apache APISIX 的运行环境或者开发环境,参考 [构建 Apache APISIX](https://github.com/apache/apisix/blob/master/docs/zh/latest/how-to-build.md),以及 Java 项目的开发环境,参考 [构建 apisix-java-plugin-runner](https://github.com/apache/apisix-java-plugin-runner/blob/main/docs/development.md)。
+
+**注意**:Apache APISIX 和 apisix-java-plugin-runner 需要位于同一实例上。
+
+## 3. 进入调试模式
+
+### 3.1 设置 Apache APISIX 进入调试模式
+
+这里是指让 Apache APISIX 以调试的方式运行外部插件,在 `config.yaml` 中增加以下配置
+
+```text
+ext-plugin:
+  path_for_test: /tmp/runner.sock
+```
+
+这个配置的意思是,Apache APISIX  相当于 client 端,会监听位于 `/tmp/runner.sock` 位置上的 Unxi Domain Socket 链接。
+
+### 3.2 设置 apisix-java-plugin-runner 进入调试模式
+
+在启动 `Main class(org.apache.apisix.plugin.runner.PluginRunnerApplication)`之前,需要配置用户级的环境变量 `APISIX_LISTEN_ADDRESS=unix:/tmp/runner.sock` 和 `APISIX_CONF_EXPIRE_TIME=3600`。
+
+如果你是使用 IDEA 进行开发,那么配置好的环境变量示意如下:
+
+![2021-06-21-2](../static/img/blog_img/2021-06-21-2.png)
+
+apisix-java-plugin-runner 相当于 server 端,在启动时会主动创建 `/tmp/runner.sock` 文件,并在这个文件上与 Apache APISIX 进行 Unix Domain Socket 通信。
+
+## 4. 开发
+
+### 4.1 场景
+
+我们以一个场景来代入开发过程:需要验证请求 header 中 token 的有效性,验证 token 的方式是用请求中携带 token 作为参数,访问 SSO 固定的接口,如果 token 验证通过则放行请求,验证失败则阻止请求。
+
+### 4.2 配置 Apache APISIX
+
+先给插件命名为 `TokenValidator`,然后设计属性,为了尽可能做到动态配置,属性设计如下
+
+```text
+{
+  "validate_header": "token",
+  "validate_url": "https://www.sso.foo.com/token/validate",
+  "rejected_code": "403"
+}
+```
+
+启动 Apache APISIX,然后新增一条路由配置,指定该路由需要调用 apisix-java-plugin-runner 的 `TokenValidator` 插件,示例如下
+
+```text
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
+{
+    "uri":"/get",
+    "plugins":{
+        "ext-plugin-pre-req":{
+            "conf":[
+                {
+                    "name":"TokenValidator",
+                    "value":"{\"validate_header\":\"token\",\"validate_url\":\"https://www.sso.foo.com/token/validate\",\"rejected_code\":\"403\"}"
+                }
+            ]
+        }
+    },
+    "upstream":{
+        "nodes":{
+            "httpbin.org:80":1
+        },
+        "type":"roundrobin"
+    }
+}
+```
+
+需要注意的是,`TokenValidator` 的属性需要经过 json 转义,作为 string 类型进行配置。
+
+(这里上游地址配置为 httpbin.org,方便调试)
+
+### 4.3 开发 Java 插件
+
+在 runner-plugin/src/main/java/org/apache/apisix/plugin/runner/filter 目录下,新增 `TokenValidatr.java`,代码初始骨架如下
+
+```Java
+package org.apache.apisix.plugin.runner.filter;
+
+import org.apache.apisix.plugin.runner.HttpRequest;
+import org.apache.apisix.plugin.runner.HttpResponse;
+import org.springframework.stereotype.Component;
+import reactor.core.publisher.Mono;
+
+
+@Component
+public class TokenValidator implements PluginFilter {
+
+    @Override
+    public String name() {
+        return "TokenValidator";
+    }
+
+    @Override
+    public Mono<Void> filter(HttpRequest request, HttpResponse response, PluginFilterChain chain) {
+        return chain.filter(request, response);
+    }
+}
+```
+
+需要继承 `PluginFilter`接口,重写 `name` 和 `filter`函数。
+
+重写 `name` 的返回值,和前面配置 APISIX 的路由属性中 "name" 保持一致。
+
+完整代码如下:
+
+```Java
+package org.apache.apisix.plugin.runner.filter;
+
+import com.google.gson.Gson;
+import org.apache.apisix.plugin.runner.HttpRequest;
+import org.apache.apisix.plugin.runner.HttpResponse;
+import org.springframework.stereotype.Component;
+import reactor.core.publisher.Mono;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Component
+public class TokenValidator implements PluginFilter {
+
+    @Override
+    public String name() {
+        return "TokenValidator";
+    }
+
+    @Override
+    public Mono<Void> filter(HttpRequest request, HttpResponse response, PluginFilterChain chain) {
+        // parse `conf` to json
+        String configStr = request.getConfig(this);
+        Gson gson = new Gson();
+        Map<String, Object> conf = new HashMap<>();
+        conf = gson.fromJson(configStr, conf.getClass());
+
+        // get configuration parameters
+        String token = request.getHeader((String) conf.get("validate_header"));
+        String validate_url = (String) conf.get("validate_url");
+        boolean flag = validate(token, validate_url);
+
+        // token verification results
+        if (!flag) {
+            String rejected_code = (String) conf.get("rejected_code");
+            response.setStatusCode(Integer.parseInt(rejected_code));
+            return chain.filter(request, response);
+        }
+
+        return chain.filter(request, response);
+    }
+
+    private Boolean validate(String token, String validate_url) {
+        //TODO: improve the validation process
+        return true;
+    }
+}
+```
+
+### 4.4 测试
+
+在 Apache APISIX 上配置的上游服务是 httpbin.org,可以访问 Apache APISIX,触发路由,让 Apache APISIX 调用 apisix-java-plugin-runner 去执行 TokenValidator 插件,测试一下 Java 插件效果。
+
+```text
+curl -H 'token: 123456' 127.0.0.1:9080/get 
+{
+ "args": {}, 
+ "headers": {
+ "Accept": "/", 
+ "Host": "127.0.0.1", 
+ "Token": "123456", 
+ "User-Agent": "curl/7.71.1", 
+ "X-Amzn-Trace-Id": "Root=1-60cb0424-02b5bf804cfeab5252392f96", 
+ "X-Forwarded-Host": "127.0.0.1"
+ }, 
+ "origin": "127.0.0.1", 
+ "url": "http://127.0.0.1/get"
+}
+```
+
+## 5. 部署
+
+插件开发完成后,部署操作可以参考 [部署 apisix-java-plugin-runner](https://github.com/apache/apisix-java-plugin-runner/blob/main/docs/how-it-works.md#run)。
+
+## 6. 视频教程
+<iframe 
+    height="350" 
+    width="600" 
+    src="../static/video/2021-06-21-use-Java-to-write-Apache-APISIX-plugins.mp4" 

Review comment:
       Not a good idea IMO, because people in China couldn't watch this video, let me help to upload it to CDN.

##########
File path: website/blog/2021-06-21-use-Java-to-write-Apache-APISIX-plugins.md
##########
@@ -0,0 +1,233 @@
+---
+title: "使用 Java 编写 Apache APISIX 插件"
+author: Zhengsong Tu
+authorURL: "https://github.com/tzssangglass"
+authorImageURL: "https://avatars.githubusercontent.com/u/30819887?v=4"
+---
+> [@tzssangglass](https://github.com/tzssangglass), Apache APISIX contributor from [Shenzhen Zhiliu Technology Co.](https://www.apiseven.com/)
+>
+
+<!--truncate-->
+Apache APISIX 支持多语言编写插件了!不会 Lua 也没关系,现在可以用你熟悉的语言编写插件,文末还有**视频教程**。
+
+## 1. 简介
+
+### 1.1 为什么 Apache APISIX 要支持多语言编写插件
+
+在支持多语言编程插件前,Apache APISIX 只支持使用 Lua 语言编写插件,需要开发者掌握 Lua 和 OpenResty 相关的开发能力。然而相对于主流开发语言 Java、Go 来说,Lua 和 OpenResty 属于相对小众的技术,开发者很少。如果从头开始学习 Lua 和 OpenResty,需要付出相当多的时间和精力。
+
+开发团队在进行技术选型的时候,最重要的考量就是所选技术是否与本团队技术栈相匹配,然而小众的技术栈就限制了 Apache APISIX 在更广阔的场景下进行技术落地。
+
+现在 Apache APISIX 支持多语言开发插件,**更重要的是支持语言所在的开发生态圈,使用者可以使用自己熟悉的技术栈来开发 Apache APISIX**。以支持 Java 为例,使用者不仅可以使用 Java 语言编写插件,还可以融入 Spring Cloud 生态圈,广泛使用生态圈内的各种技术组件。
+
+### 1.2 Apache APISIX 多语言支持架构图
+
+![2021-06-21-1](../static/img/blog_img/2021-06-21-1.png)
+
+上图左边是 Apache APISIX 的工作流程,右边的 plugin runner 是指插件运行器,泛指多语言支持的项目。本文档下面提到的 apisix-java-plugin-runner 项目就是支持 Java 语言的 plugin runner。
+
+当你在 Apache APISIX 中配置一个 plugin runner 时,Apache APISIX 会启动一个子进程运行 plugin runner,该子进程与 Apache APISIX 进程属于同一个用户。当我们重启或重新加载 Apache APISIX 时,plugin runner 也将被重启。
+
+如果你为一个给定的路由配置了 ext-plugin-* 插件,击中该路由的请求将触发  Apache APISIX,通过 unix socket 向 plugin runner 执行 RPC 调用。调用细分为两个阶段:
+
+- ext-plugin-pre-req: 在执行 Apache APISIX 内置插件(Lua 语言插件)之前
+- ext-plugin-post-req: 在执行 Apache APISIX 内置插件(Lua 语言插件)之后
+
+根据需要配置 plugin runner 的执行时机。
+
+plugin runner 会处理 RPC 调用,在其内部创建一个模拟请求,然后运行多语言编写的插件,并将结果返回给 Apache APISIX。
+
+多语言插件的执行顺序是在 ext-plugin-* 插件配置项中定义的。像其他插件一样,它们可以被启用并在运行中重新定义。
+
+## 2. 搭建开发环境
+
+首先需要搭建 Apache APISIX 的运行环境或者开发环境,参考 [构建 Apache APISIX](https://github.com/apache/apisix/blob/master/docs/zh/latest/how-to-build.md),以及 Java 项目的开发环境,参考 [构建 apisix-java-plugin-runner](https://github.com/apache/apisix-java-plugin-runner/blob/main/docs/development.md)。
+
+**注意**:Apache APISIX 和 apisix-java-plugin-runner 需要位于同一实例上。
+
+## 3. 进入调试模式
+
+### 3.1 设置 Apache APISIX 进入调试模式
+
+这里是指让 Apache APISIX 以调试的方式运行外部插件,在 `config.yaml` 中增加以下配置
+
+```text
+ext-plugin:
+  path_for_test: /tmp/runner.sock
+```
+
+这个配置的意思是,Apache APISIX  相当于 client 端,会监听位于 `/tmp/runner.sock` 位置上的 Unxi Domain Socket 链接。
+
+### 3.2 设置 apisix-java-plugin-runner 进入调试模式
+
+在启动 `Main class(org.apache.apisix.plugin.runner.PluginRunnerApplication)`之前,需要配置用户级的环境变量 `APISIX_LISTEN_ADDRESS=unix:/tmp/runner.sock` 和 `APISIX_CONF_EXPIRE_TIME=3600`。
+
+如果你是使用 IDEA 进行开发,那么配置好的环境变量示意如下:
+
+![2021-06-21-2](../static/img/blog_img/2021-06-21-2.png)
+
+apisix-java-plugin-runner 相当于 server 端,在启动时会主动创建 `/tmp/runner.sock` 文件,并在这个文件上与 Apache APISIX 进行 Unix Domain Socket 通信。
+
+## 4. 开发
+
+### 4.1 场景
+
+我们以一个场景来代入开发过程:需要验证请求 header 中 token 的有效性,验证 token 的方式是用请求中携带 token 作为参数,访问 SSO 固定的接口,如果 token 验证通过则放行请求,验证失败则阻止请求。
+
+### 4.2 配置 Apache APISIX
+
+先给插件命名为 `TokenValidator`,然后设计属性,为了尽可能做到动态配置,属性设计如下
+
+```text
+{
+  "validate_header": "token",
+  "validate_url": "https://www.sso.foo.com/token/validate",
+  "rejected_code": "403"
+}
+```
+
+启动 Apache APISIX,然后新增一条路由配置,指定该路由需要调用 apisix-java-plugin-runner 的 `TokenValidator` 插件,示例如下
+
+```text
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
+{
+    "uri":"/get",
+    "plugins":{
+        "ext-plugin-pre-req":{
+            "conf":[
+                {
+                    "name":"TokenValidator",
+                    "value":"{\"validate_header\":\"token\",\"validate_url\":\"https://www.sso.foo.com/token/validate\",\"rejected_code\":\"403\"}"
+                }
+            ]
+        }
+    },
+    "upstream":{
+        "nodes":{
+            "httpbin.org:80":1
+        },
+        "type":"roundrobin"
+    }
+}
+```
+
+需要注意的是,`TokenValidator` 的属性需要经过 json 转义,作为 string 类型进行配置。
+
+(这里上游地址配置为 httpbin.org,方便调试)
+
+### 4.3 开发 Java 插件
+
+在 runner-plugin/src/main/java/org/apache/apisix/plugin/runner/filter 目录下,新增 `TokenValidatr.java`,代码初始骨架如下
+
+```Java
+package org.apache.apisix.plugin.runner.filter;
+
+import org.apache.apisix.plugin.runner.HttpRequest;
+import org.apache.apisix.plugin.runner.HttpResponse;
+import org.springframework.stereotype.Component;
+import reactor.core.publisher.Mono;
+
+
+@Component
+public class TokenValidator implements PluginFilter {
+
+    @Override
+    public String name() {
+        return "TokenValidator";
+    }
+
+    @Override
+    public Mono<Void> filter(HttpRequest request, HttpResponse response, PluginFilterChain chain) {
+        return chain.filter(request, response);
+    }
+}
+```
+
+需要继承 `PluginFilter`接口,重写 `name` 和 `filter`函数。
+
+重写 `name` 的返回值,和前面配置 APISIX 的路由属性中 "name" 保持一致。
+
+完整代码如下:
+
+```Java
+package org.apache.apisix.plugin.runner.filter;
+
+import com.google.gson.Gson;
+import org.apache.apisix.plugin.runner.HttpRequest;
+import org.apache.apisix.plugin.runner.HttpResponse;
+import org.springframework.stereotype.Component;
+import reactor.core.publisher.Mono;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Component
+public class TokenValidator implements PluginFilter {
+
+    @Override
+    public String name() {
+        return "TokenValidator";
+    }
+
+    @Override
+    public Mono<Void> filter(HttpRequest request, HttpResponse response, PluginFilterChain chain) {
+        // parse `conf` to json
+        String configStr = request.getConfig(this);
+        Gson gson = new Gson();
+        Map<String, Object> conf = new HashMap<>();
+        conf = gson.fromJson(configStr, conf.getClass());
+
+        // get configuration parameters
+        String token = request.getHeader((String) conf.get("validate_header"));
+        String validate_url = (String) conf.get("validate_url");
+        boolean flag = validate(token, validate_url);
+
+        // token verification results
+        if (!flag) {
+            String rejected_code = (String) conf.get("rejected_code");
+            response.setStatusCode(Integer.parseInt(rejected_code));
+            return chain.filter(request, response);
+        }
+
+        return chain.filter(request, response);
+    }
+
+    private Boolean validate(String token, String validate_url) {
+        //TODO: improve the validation process
+        return true;
+    }
+}
+```
+
+### 4.4 测试
+
+在 Apache APISIX 上配置的上游服务是 httpbin.org,可以访问 Apache APISIX,触发路由,让 Apache APISIX 调用 apisix-java-plugin-runner 去执行 TokenValidator 插件,测试一下 Java 插件效果。
+
+```text
+curl -H 'token: 123456' 127.0.0.1:9080/get 
+{
+ "args": {}, 
+ "headers": {
+ "Accept": "/", 
+ "Host": "127.0.0.1", 
+ "Token": "123456", 
+ "User-Agent": "curl/7.71.1", 
+ "X-Amzn-Trace-Id": "Root=1-60cb0424-02b5bf804cfeab5252392f96", 
+ "X-Forwarded-Host": "127.0.0.1"
+ }, 
+ "origin": "127.0.0.1", 
+ "url": "http://127.0.0.1/get"
+}
+```
+
+## 5. 部署
+
+插件开发完成后,部署操作可以参考 [部署 apisix-java-plugin-runner](https://github.com/apache/apisix-java-plugin-runner/blob/main/docs/how-it-works.md#run)。
+
+## 6. 视频教程
+<iframe 
+    height="350" 
+    width="600" 
+    src="../static/video/2021-06-21-use-Java-to-write-Apache-APISIX-plugins.mp4" 

Review comment:
       Use this one instead:
   
   https://api7-website-1301662268.file.myqcloud.com/2021-06-21-use-Java-to-write-Apache-APISIX-plugins.mp4




-- 
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.

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



[GitHub] [apisix-website] tzssangglass commented on a change in pull request #372: docs: added use Java to write Apache APISIX plugins blog

Posted by GitBox <gi...@apache.org>.
tzssangglass commented on a change in pull request #372:
URL: https://github.com/apache/apisix-website/pull/372#discussion_r655855070



##########
File path: website/blog/2021-06-21-use-Java-to-write-Apache-APISIX-plugins.md
##########
@@ -0,0 +1,234 @@
+---
+title: "使用 Java 编写 Apache APISIX 插件"
+author: Zhengsong Tu
+authorURL: "https://github.com/tzssangglass"
+authorImageURL: "https://avatars.githubusercontent.com/u/30819887?v=4"
+---
+> [@tzssangglass](https://github.com/tzssangglass), Apache APISIX contributor from [Shenzhen Zhiliu Technology Co.](https://www.apiseven.com/)
+>
+
+<!--truncate-->
+Apache APISIX 支持多语言编写插件了!不会 Lua 也没关系,现在可以用你熟悉的语言编写插件,文末还有**视频教程**。
+
+## 1. 简介
+
+### 1.1 为什么 Apache APISIX 要支持多语言编写插件
+
+在支持多语言编程插件前,Apache APISIX 只支持使用 Lua 语言编写插件,需要开发者掌握 Lua 和 OpenResty 相关的开发能力。然而相对于主流开发语言 Java、Go 来说,Lua 和 OpenResty 属于相对小众的技术,开发者很少。如果从头开始学习 Lua 和 OpenResty,需要付出相当多的时间和精力。
+
+开发团队在进行技术选型的时候,最重要的考量就是所选技术是否与本团队技术栈相匹配,然而小众的技术栈就限制了 Apache APISIX 在更广阔的场景下进行技术落地。
+
+现在 Apache APISIX 支持多语言开发插件,**更重要的是支持语言所在的开发生态圈,使用者可以使用自己熟悉的技术栈来开发 Apache APISIX**。以支持 Java 为例,使用者不仅可以使用 Java 语言编写插件,还可以融入 Spring Cloud 生态圈,广泛使用生态圈内的各种技术组件。
+
+### 1.2 Apache APISIX 多语言支持架构图
+
+![2021-06-21-1](../static/img/blog_img/2021-06-21-1.png)
+
+上图左边是 Apache APISIX 的工作流程,右边的 plugin runner 是指插件运行器,泛指多语言支持的项目。本文档下面提到的 apisix-java-plugin-runner 项目就是支持 Java 语言的 plugin runner。
+
+当你在 Apache APISIX 中配置一个 plugin runner 时,Apache APISIX 会启动一个子进程运行 plugin runner,该子进程与 Apache APISIX 进程属于同一个用户。当我们重启或重新加载 Apache APISIX 时,plugin runner 也将被重启。
+
+如果你为一个给定的路由配置了 ext-plugin-* 插件,击中该路由的请求将触发  Apache APISIX,通过 unix socket 向 plugin runner 执行 RPC 调用。调用细分为两个阶段:

Review comment:
       `击中` 改成 `命中`




-- 
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.

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



[GitHub] [apisix-website] juzhiyuan merged pull request #372: docs: added use Java to write Apache APISIX plugins blog

Posted by GitBox <gi...@apache.org>.
juzhiyuan merged pull request #372:
URL: https://github.com/apache/apisix-website/pull/372


   


-- 
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.

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



[GitHub] [apisix-website] tzssangglass commented on a change in pull request #372: docs: added use Java to write Apache APISIX plugins blog

Posted by GitBox <gi...@apache.org>.
tzssangglass commented on a change in pull request #372:
URL: https://github.com/apache/apisix-website/pull/372#discussion_r655855070



##########
File path: website/blog/2021-06-21-use-Java-to-write-Apache-APISIX-plugins.md
##########
@@ -0,0 +1,234 @@
+---
+title: "使用 Java 编写 Apache APISIX 插件"
+author: Zhengsong Tu
+authorURL: "https://github.com/tzssangglass"
+authorImageURL: "https://avatars.githubusercontent.com/u/30819887?v=4"
+---
+> [@tzssangglass](https://github.com/tzssangglass), Apache APISIX contributor from [Shenzhen Zhiliu Technology Co.](https://www.apiseven.com/)
+>
+
+<!--truncate-->
+Apache APISIX 支持多语言编写插件了!不会 Lua 也没关系,现在可以用你熟悉的语言编写插件,文末还有**视频教程**。
+
+## 1. 简介
+
+### 1.1 为什么 Apache APISIX 要支持多语言编写插件
+
+在支持多语言编程插件前,Apache APISIX 只支持使用 Lua 语言编写插件,需要开发者掌握 Lua 和 OpenResty 相关的开发能力。然而相对于主流开发语言 Java、Go 来说,Lua 和 OpenResty 属于相对小众的技术,开发者很少。如果从头开始学习 Lua 和 OpenResty,需要付出相当多的时间和精力。
+
+开发团队在进行技术选型的时候,最重要的考量就是所选技术是否与本团队技术栈相匹配,然而小众的技术栈就限制了 Apache APISIX 在更广阔的场景下进行技术落地。
+
+现在 Apache APISIX 支持多语言开发插件,**更重要的是支持语言所在的开发生态圈,使用者可以使用自己熟悉的技术栈来开发 Apache APISIX**。以支持 Java 为例,使用者不仅可以使用 Java 语言编写插件,还可以融入 Spring Cloud 生态圈,广泛使用生态圈内的各种技术组件。
+
+### 1.2 Apache APISIX 多语言支持架构图
+
+![2021-06-21-1](../static/img/blog_img/2021-06-21-1.png)
+
+上图左边是 Apache APISIX 的工作流程,右边的 plugin runner 是指插件运行器,泛指多语言支持的项目。本文档下面提到的 apisix-java-plugin-runner 项目就是支持 Java 语言的 plugin runner。
+
+当你在 Apache APISIX 中配置一个 plugin runner 时,Apache APISIX 会启动一个子进程运行 plugin runner,该子进程与 Apache APISIX 进程属于同一个用户。当我们重启或重新加载 Apache APISIX 时,plugin runner 也将被重启。
+
+如果你为一个给定的路由配置了 ext-plugin-* 插件,击中该路由的请求将触发  Apache APISIX,通过 unix socket 向 plugin runner 执行 RPC 调用。调用细分为两个阶段:

Review comment:
       `击中` 改成 `命中`




-- 
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.

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