You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by sp...@apache.org on 2021/05/30 02:38:12 UTC
[apisix-java-plugin-runner] branch main updated: docs: add
README.md (#17)
This is an automated email from the ASF dual-hosted git repository.
spacewander pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/apisix-java-plugin-runner.git
The following commit(s) were added to refs/heads/main by this push:
new 732cd2d docs: add README.md (#17)
732cd2d is described below
commit 732cd2de2a3b10dc92c417933cc93eda0bd0dad2
Author: tzssangglass <tz...@gmail.com>
AuthorDate: Sun May 30 10:38:05 2021 +0800
docs: add README.md (#17)
---
README.md | 50 +++++++++++++
docs/development.md | 0
docs/how-it-works.md | 0
docs/images/apisix-java-plugin-runner-overview.png | Bin 0 -> 524459 bytes
docs/the-internal-of-apisix-java-plugin-runner.md | 0
.../plugin/runner/server/ApplicationRunner.java | 12 +++-
.../plugin/runner/service/CacheConfiguration.java | 2 +-
.../runner/codec/impl/FlatBuffersEncoderTest.java | 9 ++-
.../runner/handler/A6HttpCallHandlerTest.java | 3 +-
runner-dist/src/main/bin/startup.sh | 15 ++--
.../apache/apisix/plugin/runner/HttpResponse.java | 14 ++--
runner-starter/src/main/resources/application.yaml | 11 ++-
.../plugin/runner/PluginRunnerApplicationTest.java | 7 ++
sample/pom.xml | 8 +++
.../runner/filter/RewriteRequestDemoFilter.java | 80 +++++++++++++++++++++
.../runner/filter/StopRequestDemoFilter.java | 65 +++++++++++++++++
16 files changed, 247 insertions(+), 29 deletions(-)
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..8d12aa1
--- /dev/null
+++ b/README.md
@@ -0,0 +1,50 @@
+apisix-java-plugin-runner
+=================
+
+Runs [Apache APISIX](http://apisix.apache.org/) plugins written in Java.
+Implemented as a sidecar that accompanies APISIX.
+
+![apisix-java-plugin-runner-overview](./docs/images/apisix-java-plugin-runner-overview.png)
+
+Status
+------
+
+This project is currently considered experimental.
+
+Why apisix-java-plugin-runner
+---------------------
+
+APISIX offers many full-featured plugins covering areas such as authentication,
+security, traffic control, serverless, analytics & monitoring, transformations, logging.
+
+It also provides highly extensible API, allowing common phases to be mounted,
+and users can use these api to develop their own plugins.
+
+APISIX supports writing plugins in multiple languages in version [2.6.0](https://github.com/apache/apisix/blob/master/CHANGELOG.md#260),
+this project is APISIX Java side implementation that supports writing plugins in java.
+
+
+How it Works
+-------------
+
+See [How it Works](./docs/how-it-works.md) to learn how apisix-java-plugin-runner collaborate
+with APISIX to run plugins written in java.
+
+The Internal of apisix-java-plugin-runner
+---------------------------------
+
+If you're interested in the internal of apisix-java-plugin-runner, we recommend you
+to read the [the-internal-of-apisix-java-plugin-runner](./docs/the-internal-of-apisix-java-plugin-runner.md),
+it explains the details of communication and protocol conversion with APISIX.
+
+Get Involved in Development
+---------------------------
+
+Welcome to make contributions, but before you start, please check out
+[development.md](./docs/development.md) to learn how to run and debug apisix-java-plugin-runner
+in your own environment.
+
+License
+-------
+
+[Apache 2.0 LICENSE](./LICENSE)
\ No newline at end of file
diff --git a/docs/development.md b/docs/development.md
new file mode 100644
index 0000000..e69de29
diff --git a/docs/how-it-works.md b/docs/how-it-works.md
new file mode 100644
index 0000000..e69de29
diff --git a/docs/images/apisix-java-plugin-runner-overview.png b/docs/images/apisix-java-plugin-runner-overview.png
new file mode 100644
index 0000000..3f6f391
Binary files /dev/null and b/docs/images/apisix-java-plugin-runner-overview.png differ
diff --git a/docs/the-internal-of-apisix-java-plugin-runner.md b/docs/the-internal-of-apisix-java-plugin-runner.md
new file mode 100644
index 0000000..e69de29
diff --git a/runner-core/src/main/java/org/apache/apisix/plugin/runner/server/ApplicationRunner.java b/runner-core/src/main/java/org/apache/apisix/plugin/runner/server/ApplicationRunner.java
index 79df645..ca7e68c 100644
--- a/runner-core/src/main/java/org/apache/apisix/plugin/runner/server/ApplicationRunner.java
+++ b/runner-core/src/main/java/org/apache/apisix/plugin/runner/server/ApplicationRunner.java
@@ -21,6 +21,8 @@ import io.netty.channel.unix.DomainSocketAddress;
import io.netty.handler.logging.LoggingHandler;
import lombok.RequiredArgsConstructor;
import org.apache.apisix.plugin.runner.handler.IOHandler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
@@ -34,9 +36,11 @@ import java.util.Objects;
@RequiredArgsConstructor
public class ApplicationRunner implements CommandLineRunner {
+ private final Logger logger = LoggerFactory.getLogger(ApplicationRunner.class);
+
private final TcpServer tcpServer;
- @Value("${socket.file:/tmp/runner.sock}")
+ @Value("${socket.file}")
private String socketFile;
private final IOHandler handler;
@@ -50,6 +54,11 @@ public class ApplicationRunner implements CommandLineRunner {
if (Objects.isNull(tcpServer)) {
tcpServer = TcpServer.create();
}
+
+ if (socketFile.startsWith("unix:")) {
+ socketFile = socketFile.substring("unix:".length());
+ }
+
tcpServer = tcpServer.bindAddress(() -> new DomainSocketAddress(socketFile));
tcpServer = tcpServer.doOnChannelInit((observer, channel, addr) -> {
// if (Objects.nonNull(channelHandlers)) {
@@ -62,6 +71,7 @@ public class ApplicationRunner implements CommandLineRunner {
tcpServer = tcpServer.handle(handler::handle);
}
this.server = tcpServer.bindNow();
+ logger.warn("java runner is listening on the socket file: {}", socketFile);
// delete socket file when tcp server shutdown
Runtime.getRuntime()
diff --git a/runner-core/src/main/java/org/apache/apisix/plugin/runner/service/CacheConfiguration.java b/runner-core/src/main/java/org/apache/apisix/plugin/runner/service/CacheConfiguration.java
index 029c62d..fbf4873 100644
--- a/runner-core/src/main/java/org/apache/apisix/plugin/runner/service/CacheConfiguration.java
+++ b/runner-core/src/main/java/org/apache/apisix/plugin/runner/service/CacheConfiguration.java
@@ -32,6 +32,6 @@ public class CacheConfiguration {
@Bean
public Cache<Long, A6Conf> configurationCache(@Value("${cache.config.expired:3610}") long expired,
@Value("${cache.config.capacity:1000}") int capacity) {
- return CacheBuilder.newBuilder().expireAfterWrite(expired, TimeUnit.SECONDS).maximumSize(capacity).build();
+ return CacheBuilder.newBuilder().expireAfterWrite(expired + 10, TimeUnit.SECONDS).maximumSize(capacity).build();
}
}
diff --git a/runner-core/src/test/java/org/apache/apisix/plugin/runner/codec/impl/FlatBuffersEncoderTest.java b/runner-core/src/test/java/org/apache/apisix/plugin/runner/codec/impl/FlatBuffersEncoderTest.java
index 76e5175..8a9e38b 100644
--- a/runner-core/src/test/java/org/apache/apisix/plugin/runner/codec/impl/FlatBuffersEncoderTest.java
+++ b/runner-core/src/test/java/org/apache/apisix/plugin/runner/codec/impl/FlatBuffersEncoderTest.java
@@ -21,7 +21,6 @@ import io.github.api7.A6.Err.Code;
import io.github.api7.A6.HTTPReqCall.Action;
import io.github.api7.A6.HTTPReqCall.Rewrite;
import io.github.api7.A6.HTTPReqCall.Stop;
-import io.netty.handler.codec.http.HttpResponseStatus;
import org.apache.apisix.plugin.runner.A6ConfigResponse;
import org.apache.apisix.plugin.runner.A6ErrResponse;
import org.apache.apisix.plugin.runner.HttpResponse;
@@ -132,8 +131,8 @@ class FlatBuffersEncoderTest {
void testStopResponseEncode() {
HttpResponse httpResponse = new HttpResponse(0L);
// set status, body, resp header means stop request
- httpResponse.setStatus(HttpResponseStatus.UNAUTHORIZED);
- httpResponse.setRespHeaders("code", "401");
+ httpResponse.setStatusCode(401);
+ httpResponse.setHeader("code", "401");
httpResponse.setBody("Unauthorized");
ByteBuffer result = flatBuffersEncoder.encode(httpResponse);
result.position(4);
@@ -161,8 +160,8 @@ class FlatBuffersEncoderTest {
httpResponse.setReqHeader("Server", "APISIX");
// set status, body, resp header means stop request
- httpResponse.setStatus(HttpResponseStatus.UNAUTHORIZED);
- httpResponse.setRespHeaders("code", "401");
+ httpResponse.setStatusCode(401);
+ httpResponse.setHeader("code", "401");
httpResponse.setBody("Unauthorized");
ByteBuffer result = flatBuffersEncoder.encode(httpResponse);
result.position(4);
diff --git a/runner-core/src/test/java/org/apache/apisix/plugin/runner/handler/A6HttpCallHandlerTest.java b/runner-core/src/test/java/org/apache/apisix/plugin/runner/handler/A6HttpCallHandlerTest.java
index e9604ec..f55b8d1 100644
--- a/runner-core/src/test/java/org/apache/apisix/plugin/runner/handler/A6HttpCallHandlerTest.java
+++ b/runner-core/src/test/java/org/apache/apisix/plugin/runner/handler/A6HttpCallHandlerTest.java
@@ -23,7 +23,6 @@ import com.google.flatbuffers.FlatBufferBuilder;
import io.github.api7.A6.Err.Code;
import io.github.api7.A6.HTTPReqCall.Action;
import io.github.api7.A6.TextEntry;
-import io.netty.handler.codec.http.HttpResponseStatus;
import org.apache.apisix.plugin.runner.A6Conf;
import org.apache.apisix.plugin.runner.A6ConfigRequest;
import org.apache.apisix.plugin.runner.A6ConfigResponse;
@@ -114,7 +113,7 @@ class A6HttpCallHandlerTest {
logger.info("do filter: CatFilter, order: {}", getOrder());
logger.info("do filter: CatFilter, config: {}", request.getConfig(this));
- response.setStatus(HttpResponseStatus.UNAUTHORIZED);
+ response.setStatusCode(401);
return chain.filter(request, response);
}
diff --git a/runner-dist/src/main/bin/startup.sh b/runner-dist/src/main/bin/startup.sh
index 123ae28..825ae24 100644
--- a/runner-dist/src/main/bin/startup.sh
+++ b/runner-dist/src/main/bin/startup.sh
@@ -17,16 +17,17 @@
# limitations under the License.
RUNNER_HOME=$(dirname "$0")/..
-
-RUNNER_LOGS_DIR=${RUNNER_LOGS_DIR:-${RUNNER_HOME}/logs}
+RUNNER_DIR=${RUNNER_HOME%/bin*}
RUNNER_HEAP=${JAVA_HEAP:-4g}
JAVA_OPS="${JAVA_OPS} -Xmx${RUNNER_HEAP} -Xms${RUNNER_HEAP}"
-[[ -d ${RUNNER_LOGS_DIR} ]] || mkdir -p ${RUNNER_LOGS_DIR}
+APISIX_LISTEN_ADDRESS=${APISIX_LISTEN_ADDRESS}
+APISIX_LISTEN_ADDRESS=${APISIX_LISTEN_ADDRESS#*:}
+APISIX_HOME=${APISIX_LISTEN_ADDRESS%/conf*}
-nohup java -jar ${JAVA_OPS} ${RUNNER_HOME}/apisxi-runner-start-*.jar \
- 1>${RUNNER_LOGS_DIR}/runner.out \
- 2>${RUNNER_LOGS_DIR}/runner.err &
+nohup java -jar ${JAVA_OPS} ${RUNNER_DIR}/apisix-java-plugin-*.jar \
+ 1>${APISIX_HOME}/logs/runner-out.log \
+ 2>${APISIX_HOME}/logs/runner-err.log &
-echo $! > ./logs/runner.pid
+echo $! > ${APISIX_HOME}/logs/runner.pid
diff --git a/runner-plugin-sdk/src/main/java/org/apache/apisix/plugin/runner/HttpResponse.java b/runner-plugin-sdk/src/main/java/org/apache/apisix/plugin/runner/HttpResponse.java
index 651e8e0..2c861be 100644
--- a/runner-plugin-sdk/src/main/java/org/apache/apisix/plugin/runner/HttpResponse.java
+++ b/runner-plugin-sdk/src/main/java/org/apache/apisix/plugin/runner/HttpResponse.java
@@ -22,7 +22,6 @@ import io.github.api7.A6.HTTPReqCall.Resp;
import io.github.api7.A6.HTTPReqCall.Rewrite;
import io.github.api7.A6.HTTPReqCall.Stop;
import io.github.api7.A6.TextEntry;
-import io.netty.handler.codec.http.HttpResponseStatus;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
@@ -54,7 +53,7 @@ public class HttpResponse implements A6Response {
private String body;
- private HttpResponseStatus status;
+ private Integer statusCode;
private A6ErrResponse errResponse;
@@ -87,7 +86,7 @@ public class HttpResponse implements A6Response {
this.path = path;
}
- public void setRespHeaders(String headerKey, String headerValue) {
+ public void setHeader(String headerKey, String headerValue) {
actionType = ActionType.Stop;
if (Objects.isNull(respHeaders)) {
respHeaders = new HashMap<>();
@@ -100,15 +99,16 @@ public class HttpResponse implements A6Response {
this.body = body;
}
- public void setStatus(HttpResponseStatus status) {
+ public void setStatusCode(int statusCode) {
actionType = ActionType.Stop;
- this.status = status;
+ this.statusCode = statusCode;
}
public void setErrResponse(A6ErrResponse errResponse) {
this.errResponse = errResponse;
}
+ @Override
public A6ErrResponse getErrResponse() {
return this.errResponse;
}
@@ -162,8 +162,8 @@ public class HttpResponse implements A6Response {
}
Stop.startStop(builder);
- if (!Objects.isNull(status)) {
- Stop.addStatus(builder, status.code());
+ if (!Objects.isNull(statusCode)) {
+ Stop.addStatus(builder, statusCode);
}
if (-1 != headerIndex) {
Stop.addHeaders(builder, headerIndex);
diff --git a/runner-starter/src/main/resources/application.yaml b/runner-starter/src/main/resources/application.yaml
index d330244..5f4d487 100644
--- a/runner-starter/src/main/resources/application.yaml
+++ b/runner-starter/src/main/resources/application.yaml
@@ -13,10 +13,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-logging:
- level:
- root: debug
-
cache.config:
- expired: 3610
- capacity: 1000
\ No newline at end of file
+ expired: ${APISIX_CONF_EXPIRE_TIME}
+ capacity: 1000
+
+socket:
+ file: ${APISIX_LISTEN_ADDRESS}
\ No newline at end of file
diff --git a/runner-starter/src/test/java/org/apache/apisix/plugin/runner/PluginRunnerApplicationTest.java b/runner-starter/src/test/java/org/apache/apisix/plugin/runner/PluginRunnerApplicationTest.java
index 0262ba1..3b0418d 100644
--- a/runner-starter/src/test/java/org/apache/apisix/plugin/runner/PluginRunnerApplicationTest.java
+++ b/runner-starter/src/test/java/org/apache/apisix/plugin/runner/PluginRunnerApplicationTest.java
@@ -2,6 +2,7 @@ package org.apache.apisix.plugin.runner;
import io.netty.channel.unix.DomainSocketAddress;
import io.netty.channel.unix.DomainSocketChannel;
+import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import reactor.netty.Connection;
@@ -13,6 +14,12 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
@DisplayName("Unix Domain Socket Listen Test")
class PluginRunnerApplicationTest {
+ @BeforeEach
+ void setUp() {
+ System.setProperty("APISIX_LISTEN_ADDRESS", "unix:/tmp/runner.sock");
+ System.setProperty("APISIX_CONF_EXPIRE_TIME", String.valueOf(3600));
+ }
+
@Test
void testMain() {
PluginRunnerApplication.main(new String[]{"args"});
diff --git a/sample/pom.xml b/sample/pom.xml
index db54efc..86bf052 100644
--- a/sample/pom.xml
+++ b/sample/pom.xml
@@ -41,5 +41,13 @@
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-context</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>io.projectreactor</groupId>
+ <artifactId>reactor-core</artifactId>
+ </dependency>
</dependencies>
</project>
\ No newline at end of file
diff --git a/sample/src/main/java/org/apache/apisix/plugin/runner/filter/RewriteRequestDemoFilter.java b/sample/src/main/java/org/apache/apisix/plugin/runner/filter/RewriteRequestDemoFilter.java
new file mode 100644
index 0000000..7ad93da
--- /dev/null
+++ b/sample/src/main/java/org/apache/apisix/plugin/runner/filter/RewriteRequestDemoFilter.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+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 RewriteRequestDemoFilter implements PluginFilter {
+
+ @Override
+ public String name() {
+ /* It is recommended to keep the name of the filter the same as the class name.
+ Configure the filter to be executed on apisix's routes in the following format
+
+ {
+ "uri": "/hello",
+ "plugins": {
+ "ext-plugin-pre-req": {
+ "conf": [{
+ "name": "RewriteRequestDemoFilter",
+ "value": "bar"
+ }]
+ }
+ },
+ "upstream": {
+ "nodes": {
+ "127.0.0.1:1980": 1
+ },
+ "type": "roundrobin"
+ }
+ }
+
+ The value of name in the configuration corresponds to the value of return here.
+ */
+
+ return "RewriteRequestDemoFilter";
+ }
+
+ @Override
+ public Mono<Void> filter(HttpRequest request, HttpResponse response, PluginFilterChain chain) {
+ // note: the path to the rewrite must start with '/'
+ request.setPath("/get");
+ request.setHeader("new-header", "header_by_runner");
+ /* note: The value of the parameter is currently a string type.
+ If you need the json type, you need the upstream service to parse the string value to json.
+ For example, if the arg is set as follows
+ request.setArg("new arg", "{\"key1\":\"value1\",\"key2\":2}");
+
+ The arg received by the upstream service will be as follows
+ "new arg": "{\"key1\":\"value1\",\"key2\":2}"
+ */
+ request.setArg("new arg", "{\"key1\":\"value1\",\"key2\":2}");
+
+ return chain.filter(request, response);
+ }
+
+ @Override
+ public int getOrder() {
+ //The order of filter execution in runner is determined by the order here, the smaller the order number, the higher the execution order.
+ return 0;
+ }
+}
diff --git a/sample/src/main/java/org/apache/apisix/plugin/runner/filter/StopRequestDemoFilter.java b/sample/src/main/java/org/apache/apisix/plugin/runner/filter/StopRequestDemoFilter.java
new file mode 100644
index 0000000..d190d02
--- /dev/null
+++ b/sample/src/main/java/org/apache/apisix/plugin/runner/filter/StopRequestDemoFilter.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+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 StopRequestDemoFilter implements PluginFilter {
+ @Override
+ public String name() {
+ return "StopRequestDemoFilter";
+ }
+
+ @Override
+ public Mono<Void> filter(HttpRequest request, HttpResponse response, PluginFilterChain chain) {
+ response.setStatusCode(401);
+ response.setHeader("new-header", "header_by_runner");
+ /* note: The body is currently a string type.
+ If you need the json type, you need to escape the json content here.
+ For example, if the body is set as follows
+ "{\"key1\":\"value1\",\"key2\":2}"
+
+ The body received by the client will be as follows
+ {"key1":"value1","key2":2}
+ */
+ response.setBody("{\"key1\":\"value1\",\"key2\":2}");
+
+ /* Using the above code, the client side receives the following
+
+ header:
+ HTTP/1.1 401 Unauthorized
+ Content-Type: text/plain; charset=utf-8
+ Connection: keep-alive
+ new-header: header_by_runner
+ Server: APISIX/2.6
+
+ body:
+ {"key1":"value1","key2":2}
+ */
+ return chain.filter(request, response);
+ }
+
+ @Override
+ public int getOrder() {
+ return 1;
+ }
+}