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/27 07:57:18 UTC
[apisix-java-plugin-runner] branch main updated: test: add test
case about codec (#14)
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 aeda437 test: add test case about codec (#14)
aeda437 is described below
commit aeda437a7597302049f2b5c4f73bcf2dde80d68d
Author: tzssangglass <tz...@gmail.com>
AuthorDate: Thu May 27 15:57:10 2021 +0800
test: add test case about codec (#14)
Co-authored-by: 罗泽轩 <sp...@gmail.com>
---
.../plugin/runner/codec/frame/FrameCodec.java | 68 --------
.../runner/codec/impl/FlatBuffersDecoder.java | 55 ++++++-
.../runner/codec/impl/FlatBuffersEncoder.java | 27 +++-
.../runner/codec/impl/FlatBuffersDecoderTest.java | 161 +++++++++++++++++++
.../runner/codec/impl/FlatBuffersEncoderTest.java | 172 +++++++++++++++++++++
.../runner/server/ApplicationRunnerTest.java | 77 ---------
.../apache/apisix/plugin/runner/HttpResponse.java | 27 ++--
.../apisix/plugin/runner/HttpRewriteResponse.java | 43 ------
.../apisix/plugin/runner/HttpStopResponse.java | 42 -----
runner-starter/pom.xml | 11 ++
.../plugin/runner/PluginRunnerApplicationTest.java | 47 ++++++
11 files changed, 474 insertions(+), 256 deletions(-)
diff --git a/runner-core/src/main/java/org/apache/apisix/plugin/runner/codec/frame/FrameCodec.java b/runner-core/src/main/java/org/apache/apisix/plugin/runner/codec/frame/FrameCodec.java
deleted file mode 100644
index 8cc6f7b..0000000
--- a/runner-core/src/main/java/org/apache/apisix/plugin/runner/codec/frame/FrameCodec.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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.codec.frame;
-
-import java.nio.ByteBuffer;
-
-public class FrameCodec {
-
- public static int getDataLength(ByteBuffer payload) {
- byte[] bytes = new byte[3];
- for (int i = 0; i < 3; i++) {
- bytes[i] = payload.get();
- }
- return byte3ToInt(bytes);
- }
-
- public static ByteBuffer getBody(ByteBuffer payload) {
- int length = getDataLength(payload);
- ByteBuffer buffer = payload.slice();
- byte[] dst = new byte[length];
- buffer.get(dst, 0, length);
- buffer.flip();
- return buffer;
- }
-
- public static ByteBuffer setBody(ByteBuffer payload, byte type) {
- byte[] data = new byte[payload.remaining()];
- payload.get(data);
- ByteBuffer buffer = ByteBuffer.allocate(data.length + 4);
- buffer.put(type);
- // data length
- byte[] length = intToByte3(data.length);
- buffer.put(length);
- // data
- buffer.put(data);
- buffer.flip();
- return buffer;
- }
-
- private static byte[] intToByte3(int i) {
- byte[] targets = new byte[3];
- targets[2] = (byte) (i & 0xFF);
- targets[1] = (byte) (i >> 8 & 0xFF);
- targets[0] = (byte) ((i >> 16 & 0xFF));
- return targets;
- }
-
- private static int byte3ToInt(byte[] bytes) {
- return bytes[2] & 0xFF |
- (bytes[1] & 0xFF << 8) |
- (bytes[0] & 0xFF << 16);
- }
-}
diff --git a/runner-core/src/main/java/org/apache/apisix/plugin/runner/codec/impl/FlatBuffersDecoder.java b/runner-core/src/main/java/org/apache/apisix/plugin/runner/codec/impl/FlatBuffersDecoder.java
index 560897a..8b199e8 100644
--- a/runner-core/src/main/java/org/apache/apisix/plugin/runner/codec/impl/FlatBuffersDecoder.java
+++ b/runner-core/src/main/java/org/apache/apisix/plugin/runner/codec/impl/FlatBuffersDecoder.java
@@ -23,10 +23,10 @@ import org.apache.apisix.plugin.runner.A6ErrRequest;
import org.apache.apisix.plugin.runner.A6Request;
import org.apache.apisix.plugin.runner.HttpRequest;
import org.apache.apisix.plugin.runner.codec.PluginRunnerDecoder;
-import org.apache.apisix.plugin.runner.codec.frame.FrameCodec;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
public class FlatBuffersDecoder implements PluginRunnerDecoder {
@@ -35,13 +35,35 @@ public class FlatBuffersDecoder implements PluginRunnerDecoder {
@Override
public A6Request decode(ByteBuffer buffer) {
- byte type = buffer.get();
- ByteBuffer body = FrameCodec.getBody(buffer);
+ byte type;
+ try {
+ type = buffer.get();
+ } catch (BufferUnderflowException e) {
+ logger.error("receive empty data");
+ return new A6ErrRequest(Code.BAD_REQUEST);
+ }
+
+ ByteBuffer body;
switch (type) {
case 1:
- return A6ConfigRequest.from(body);
+ A6ConfigRequest a6ConfigRequest;
+ try {
+ body = getBody(buffer);
+ a6ConfigRequest = A6ConfigRequest.from(body);
+ } catch (BufferUnderflowException | IndexOutOfBoundsException e) {
+ logger.error("receive error data length");
+ return new A6ErrRequest(Code.BAD_REQUEST);
+ }
+ return a6ConfigRequest;
case 2:
- return HttpRequest.from(body);
+ HttpRequest httpRequest;
+ try {
+ body = getBody(buffer);
+ httpRequest = HttpRequest.from(body);
+ } catch (BufferUnderflowException | IndexOutOfBoundsException e) {
+ return new A6ErrRequest(Code.BAD_REQUEST);
+ }
+ return httpRequest;
default:
break;
}
@@ -49,4 +71,27 @@ public class FlatBuffersDecoder implements PluginRunnerDecoder {
logger.error("receive unsupported type: {}", type);
return new A6ErrRequest(Code.BAD_REQUEST);
}
+
+ private int getDataLength(ByteBuffer payload) {
+ byte[] bytes = new byte[3];
+ for (int i = 0; i < 3; i++) {
+ bytes[i] = payload.get();
+ }
+ return byte3ToInt(bytes);
+ }
+
+ private ByteBuffer getBody(ByteBuffer payload) throws BufferUnderflowException, IndexOutOfBoundsException {
+ int length = getDataLength(payload);
+ ByteBuffer buffer = payload.slice();
+ byte[] dst = new byte[length];
+ buffer.get(dst, 0, length);
+ buffer.flip();
+ return buffer;
+ }
+
+ private int byte3ToInt(byte[] bytes) {
+ return bytes[2] & 0xFF |
+ (bytes[1] & 0xFF << 8) |
+ (bytes[0] & 0xFF << 16);
+ }
}
diff --git a/runner-core/src/main/java/org/apache/apisix/plugin/runner/codec/impl/FlatBuffersEncoder.java b/runner-core/src/main/java/org/apache/apisix/plugin/runner/codec/impl/FlatBuffersEncoder.java
index 973074b..5abde30 100644
--- a/runner-core/src/main/java/org/apache/apisix/plugin/runner/codec/impl/FlatBuffersEncoder.java
+++ b/runner-core/src/main/java/org/apache/apisix/plugin/runner/codec/impl/FlatBuffersEncoder.java
@@ -19,7 +19,6 @@ package org.apache.apisix.plugin.runner.codec.impl;
import org.apache.apisix.plugin.runner.A6Response;
import org.apache.apisix.plugin.runner.codec.PluginRunnerEncoder;
-import org.apache.apisix.plugin.runner.codec.frame.FrameCodec;
import java.nio.ByteBuffer;
@@ -29,8 +28,30 @@ public class FlatBuffersEncoder implements PluginRunnerEncoder {
public ByteBuffer encode(A6Response response) {
ByteBuffer buffer = response.encode();
if (null != response.getErrResponse()) {
- return FrameCodec.setBody(buffer, (byte) 0);
+ return setBody(buffer, (byte) 0);
}
- return FrameCodec.setBody(buffer, response.getType());
+ return setBody(buffer, response.getType());
+ }
+
+ private ByteBuffer setBody(ByteBuffer payload, byte type) {
+ byte[] data = new byte[payload.remaining()];
+ payload.get(data);
+ ByteBuffer buffer = ByteBuffer.allocate(data.length + 4);
+ buffer.put(type);
+ // data length
+ byte[] length = intToByte3(data.length);
+ buffer.put(length);
+ // data
+ buffer.put(data);
+ buffer.flip();
+ return buffer;
+ }
+
+ private byte[] intToByte3(int i) {
+ byte[] targets = new byte[3];
+ targets[2] = (byte) (i & 0xFF);
+ targets[1] = (byte) (i >> 8 & 0xFF);
+ targets[0] = (byte) ((i >> 16 & 0xFF));
+ return targets;
}
}
diff --git a/runner-core/src/test/java/org/apache/apisix/plugin/runner/codec/impl/FlatBuffersDecoderTest.java b/runner-core/src/test/java/org/apache/apisix/plugin/runner/codec/impl/FlatBuffersDecoderTest.java
new file mode 100644
index 0000000..ba6708d
--- /dev/null
+++ b/runner-core/src/test/java/org/apache/apisix/plugin/runner/codec/impl/FlatBuffersDecoderTest.java
@@ -0,0 +1,161 @@
+/*
+ * 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.codec.impl;
+
+import com.google.flatbuffers.FlatBufferBuilder;
+import io.github.api7.A6.Err.Code;
+import io.github.api7.A6.TextEntry;
+import org.apache.apisix.plugin.runner.A6ConfigRequest;
+import org.apache.apisix.plugin.runner.A6ErrRequest;
+import org.apache.apisix.plugin.runner.A6Request;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.MockitoAnnotations;
+import org.springframework.boot.test.system.CapturedOutput;
+import org.springframework.boot.test.system.OutputCaptureExtension;
+
+import java.nio.ByteBuffer;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+@ExtendWith(OutputCaptureExtension.class)
+@DisplayName("test decode data")
+class FlatBuffersDecoderTest {
+
+ @InjectMocks
+ FlatBuffersDecoder flatBuffersDecoder;
+
+ @BeforeEach
+ void setUp() {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ @Test
+ @DisplayName("test empty data")
+ void testEmptyData(CapturedOutput capturedOutput) {
+ byte[] bytes = new byte[]{};
+ ByteBuffer buffer = ByteBuffer.wrap(bytes);
+ A6Request result = flatBuffersDecoder.decode(buffer);
+ Assertions.assertEquals(Code.BAD_REQUEST, ((A6ErrRequest) result).getCode());
+ Assertions.assertTrue(capturedOutput.getOut().contains("receive empty data"));
+ }
+
+ @Test
+ @DisplayName("test unsupported type")
+ void testUnsupportedType(CapturedOutput capturedOutput) {
+ byte[] bytes = new byte[]{4};
+ ByteBuffer buffer = ByteBuffer.wrap(bytes);
+ A6Request result = flatBuffersDecoder.decode(buffer);
+ Assertions.assertEquals(Code.BAD_REQUEST, ((A6ErrRequest) result).getCode());
+ Assertions.assertTrue(capturedOutput.getOut().contains("receive unsupported type: 4"));
+ }
+
+ @Test
+ @DisplayName("test error data length(1)")
+ void testErrorDataLength1(CapturedOutput capturedOutput) {
+ // data length is greater than actual length
+ byte[] bytes = new byte[]{1, 0, 0, 3, 0};
+ ByteBuffer buffer = ByteBuffer.wrap(bytes);
+ A6Request result = flatBuffersDecoder.decode(buffer);
+ Assertions.assertEquals(Code.BAD_REQUEST, ((A6ErrRequest) result).getCode());
+ Assertions.assertTrue(capturedOutput.getOut().contains("receive error data length"));
+ }
+
+ @Test
+ @DisplayName("test error data length(2)")
+ void testErrorDataLength2(CapturedOutput capturedOutput) {
+ // data length equal to 0
+ byte[] bytes = new byte[]{1, 0, 0, 0, 0};
+ ByteBuffer buffer = ByteBuffer.wrap(bytes);
+ A6Request result = flatBuffersDecoder.decode(buffer);
+ Assertions.assertEquals(Code.BAD_REQUEST, ((A6ErrRequest) result).getCode());
+ Assertions.assertTrue(capturedOutput.getOut().contains("receive error data length"));
+ }
+
+ @Test
+ @DisplayName("test error data length(3)")
+ void testErrorDataLength3(CapturedOutput capturedOutput) {
+ // wrong data content
+ byte[] bytes = new byte[]{1, 0, 0, 1, 0, 1};
+ ByteBuffer buffer = ByteBuffer.wrap(bytes);
+ A6Request result = flatBuffersDecoder.decode(buffer);
+ Assertions.assertEquals(Code.BAD_REQUEST, ((A6ErrRequest) result).getCode());
+ Assertions.assertTrue(capturedOutput.getOut().contains("receive error data length"));
+ }
+
+ @Test
+ @DisplayName("test get body")
+ void testGetBody() {
+ // mock client assembly data
+ FlatBufferBuilder builder = new FlatBufferBuilder();
+ int foo = builder.createString("foo");
+ int bar = builder.createString("bar");
+ int confIndex = TextEntry.createTextEntry(builder, foo, bar);
+ int vector = io.github.api7.A6.PrepareConf.Req.createConfVector(builder, new int[]{confIndex});
+ io.github.api7.A6.PrepareConf.Req.startReq(builder);
+ io.github.api7.A6.PrepareConf.Req.addConf(builder, vector);
+ builder.finish(io.github.api7.A6.PrepareConf.Req.endReq(builder));
+ byte[] data = new byte[builder.dataBuffer().remaining()];
+ builder.dataBuffer().get(data, 0, data.length);
+ // use the correct data length
+ byte[] header = new byte[]{1, 0, 0, (byte) data.length};
+ byte[] bytes = new byte[header.length + data.length];
+ // assembly data format
+ System.arraycopy(header, 0, bytes, 0, header.length);
+ System.arraycopy(data, 0, bytes, header.length, data.length);
+
+ ByteBuffer buffer = ByteBuffer.wrap(bytes);
+ A6ConfigRequest configReq = (A6ConfigRequest) flatBuffersDecoder.decode(buffer);
+ for (int i = 0; i < configReq.getReq().confLength(); i++) {
+ TextEntry conf = configReq.getReq().conf(i);
+ Assertions.assertEquals("foo", conf.name());
+ Assertions.assertEquals("bar", conf.value());
+ }
+ }
+
+ @Test
+ @DisplayName("test get body with error data length")
+ void testGetBody2() {
+ // {"name":"foo", "value":"bar"}
+ FlatBufferBuilder builder = new FlatBufferBuilder();
+ int foo = builder.createString("foo");
+ int bar = builder.createString("bar");
+ int confIndex = TextEntry.createTextEntry(builder, foo, bar);
+ int vector = io.github.api7.A6.PrepareConf.Req.createConfVector(builder, new int[]{confIndex});
+ io.github.api7.A6.PrepareConf.Req.startReq(builder);
+ io.github.api7.A6.PrepareConf.Req.addConf(builder, vector);
+ builder.finish(io.github.api7.A6.PrepareConf.Req.endReq(builder));
+ byte[] data = new byte[builder.dataBuffer().remaining()];
+ builder.dataBuffer().get(data, 0, data.length);
+ // se the error data length
+ byte errDateLength = (byte) (data.length / 2);
+ byte[] header = new byte[]{1, 0, 0, errDateLength};
+ byte[] bytes = new byte[header.length + data.length];
+ // assembly data format
+ System.arraycopy(header, 0, bytes, 0, header.length);
+ System.arraycopy(data, 0, bytes, header.length, data.length);
+
+ ByteBuffer buffer = ByteBuffer.wrap(bytes);
+ A6ConfigRequest configReq = (A6ConfigRequest) flatBuffersDecoder.decode(buffer);
+ assertThrows(IndexOutOfBoundsException.class, () -> configReq.getReq().conf(0));
+ }
+}
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
new file mode 100644
index 0000000..76e5175
--- /dev/null
+++ b/runner-core/src/test/java/org/apache/apisix/plugin/runner/codec/impl/FlatBuffersEncoderTest.java
@@ -0,0 +1,172 @@
+/*
+ * 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.codec.impl;
+
+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;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import java.nio.ByteBuffer;
+
+@DisplayName("test encode data")
+class FlatBuffersEncoderTest {
+ FlatBuffersEncoder flatBuffersEncoder = new FlatBuffersEncoder();
+
+ @Test
+ @DisplayName("test encode error response(1)")
+ void testErrResponseEncode1() {
+ A6ErrResponse errResponse = new A6ErrResponse(Code.BAD_REQUEST);
+ ByteBuffer result = flatBuffersEncoder.encode(errResponse);
+ byte[] res = new byte[result.remaining()];
+ result.get(res);
+
+ //example
+ byte[] example = new byte[]{0, 0, 0, 12, 8, 0, 0, 0, 4, 0, 4, 0, 4, 0, 0, 0};
+ Assertions.assertArrayEquals(res, example);
+ }
+
+ @Test
+ @DisplayName("test encode error response(2)")
+ void testErrResponseEncode2() {
+ A6ErrResponse errResponse = new A6ErrResponse(Code.BAD_REQUEST);
+ ByteBuffer result = flatBuffersEncoder.encode(errResponse);
+ result.position(4);
+ io.github.api7.A6.Err.Resp resp = io.github.api7.A6.Err.Resp.getRootAsResp(result);
+ Assertions.assertEquals(Code.BAD_REQUEST, resp.code());
+ }
+
+ @Test
+ @DisplayName("test prepare conf response(1)")
+ void testPrepareConfResponseEncode1() {
+ A6ConfigResponse configResponse = new A6ConfigResponse(0L);
+ ByteBuffer result = flatBuffersEncoder.encode(configResponse);
+ byte[] res = new byte[result.remaining()];
+ result.get(res);
+
+ //example
+ byte[] example = new byte[]{1, 0, 0, 12, 8, 0, 0, 0, 4, 0, 4, 0, 4, 0, 0, 0};
+ Assertions.assertArrayEquals(res, example);
+ }
+
+ @Test
+ @DisplayName("test prepare conf response(2)")
+ void testPrepareConfResponseEncode2() {
+ A6ConfigResponse configResponse = new A6ConfigResponse(0L);
+ ByteBuffer result = flatBuffersEncoder.encode(configResponse);
+ result.position(4);
+ io.github.api7.A6.PrepareConf.Resp resp = io.github.api7.A6.PrepareConf.Resp.getRootAsResp(result);
+ Assertions.assertEquals(resp.confToken(), 0L);
+ }
+
+ @Test
+ @DisplayName("test http call response")
+ void testHTTPCallResponseEncode1() {
+ HttpResponse errResponse = new HttpResponse(0L);
+ ByteBuffer result = flatBuffersEncoder.encode(errResponse);
+ byte[] res = new byte[result.remaining()];
+ result.get(res);
+
+ //example
+ byte[] example = new byte[]{2, 0, 0, 12, 8, 0, 0, 0, 4, 0, 4, 0, 4, 0, 0, 0};
+ Assertions.assertArrayEquals(res, example);
+ }
+
+ @Test
+ @DisplayName("test http call response, action: none")
+ void testHTTPCallResponseEncode2() {
+ HttpResponse httpResponse = new HttpResponse(0L);
+ ByteBuffer result = flatBuffersEncoder.encode(httpResponse);
+ result.position(4);
+ io.github.api7.A6.HTTPReqCall.Resp resp = io.github.api7.A6.HTTPReqCall.Resp.getRootAsResp(result);
+ Assertions.assertEquals(resp.id(), 0L);
+ // default action is none
+ Assertions.assertEquals(resp.actionType(), Action.NONE);
+ }
+
+ @Test
+ @DisplayName("test http call response, action: rewrite")
+ void testRewriteResponseEncode() {
+ HttpResponse httpResponse = new HttpResponse(0L);
+ // set path, args, req header means rewrite request
+ httpResponse.setPath("/hello");
+ httpResponse.setArgs("foo", "bar");
+ httpResponse.setReqHeader("Server", "APISIX");
+ ByteBuffer result = flatBuffersEncoder.encode(httpResponse);
+ result.position(4);
+ io.github.api7.A6.HTTPReqCall.Resp resp = io.github.api7.A6.HTTPReqCall.Resp.getRootAsResp(result);
+ Assertions.assertEquals(resp.actionType(), Action.Rewrite);
+ Rewrite rewrite = (Rewrite) resp.action(new Rewrite());
+
+ Assertions.assertEquals(rewrite.path(), "/hello");
+ Assertions.assertEquals(rewrite.args(0).name(), "foo");
+ Assertions.assertEquals(rewrite.args(0).value(), "bar");
+ Assertions.assertEquals(rewrite.headers(0).name(), "Server");
+ Assertions.assertEquals(rewrite.headers(0).value(), "APISIX");
+ }
+
+ @Test
+ @DisplayName("test http call response, action: stop")
+ void testStopResponseEncode() {
+ HttpResponse httpResponse = new HttpResponse(0L);
+ // set status, body, resp header means stop request
+ httpResponse.setStatus(HttpResponseStatus.UNAUTHORIZED);
+ httpResponse.setRespHeaders("code", "401");
+ httpResponse.setBody("Unauthorized");
+ ByteBuffer result = flatBuffersEncoder.encode(httpResponse);
+ result.position(4);
+ io.github.api7.A6.HTTPReqCall.Resp resp = io.github.api7.A6.HTTPReqCall.Resp.getRootAsResp(result);
+ Assertions.assertEquals(resp.actionType(), Action.Stop);
+ Stop stop = (Stop) resp.action(new Stop());
+
+ Assertions.assertEquals(stop.status(), 401);
+ StringBuilder body = new StringBuilder();
+ for (int i = 0; i < stop.bodyLength(); i++) {
+ body.append((char) stop.body(i));
+ }
+ Assertions.assertEquals(body.toString(), "Unauthorized");
+ Assertions.assertEquals(stop.headers(0).name(), "code");
+ Assertions.assertEquals(stop.headers(0).value(), "401");
+ }
+
+ @Test
+ @DisplayName("test mix stop and rewrite response, will use stop response")
+ void testMixStopAndRewriteResponseEncode() {
+ HttpResponse httpResponse = new HttpResponse(0L);
+ // set path, args, req header means rewrite request
+ httpResponse.setPath("/hello");
+ httpResponse.setArgs("foo", "bar");
+ httpResponse.setReqHeader("Server", "APISIX");
+
+ // set status, body, resp header means stop request
+ httpResponse.setStatus(HttpResponseStatus.UNAUTHORIZED);
+ httpResponse.setRespHeaders("code", "401");
+ httpResponse.setBody("Unauthorized");
+ ByteBuffer result = flatBuffersEncoder.encode(httpResponse);
+ result.position(4);
+ io.github.api7.A6.HTTPReqCall.Resp resp = io.github.api7.A6.HTTPReqCall.Resp.getRootAsResp(result);
+ Assertions.assertEquals(resp.actionType(), Action.Stop);
+ }
+}
diff --git a/runner-core/src/test/java/org/apache/apisix/plugin/runner/server/ApplicationRunnerTest.java b/runner-core/src/test/java/org/apache/apisix/plugin/runner/server/ApplicationRunnerTest.java
deleted file mode 100644
index a7018c1..0000000
--- a/runner-core/src/test/java/org/apache/apisix/plugin/runner/server/ApplicationRunnerTest.java
+++ /dev/null
@@ -1,77 +0,0 @@
-package org.apache.apisix.plugin.runner.server;
-
-import io.netty.channel.unix.DomainSocketAddress;
-import io.netty.channel.unix.DomainSocketChannel;
-import org.apache.apisix.plugin.runner.codec.PluginRunnerConfiguration;
-import org.apache.apisix.plugin.runner.handler.A6HandlerConfiguration;
-import org.apache.apisix.plugin.runner.handler.IOHandlerConfiguration;
-import org.apache.apisix.plugin.runner.server.config.TcpServerConfiguration;
-import org.apache.apisix.plugin.runner.service.CacheConfiguration;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Disabled;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.springframework.boot.WebApplicationType;
-import org.springframework.boot.builder.SpringApplicationBuilder;
-import org.springframework.context.ConfigurableApplicationContext;
-import org.springframework.test.context.junit.jupiter.SpringExtension;
-import reactor.netty.Connection;
-import reactor.netty.tcp.TcpClient;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-
-@DisplayName("Unix Domain Socket Listen Test")
-@ExtendWith(SpringExtension.class)
-class ApplicationRunnerTest {
-
- protected ConfigurableApplicationContext context;
-
- @BeforeEach
- @DisplayName("start java plugin runner")
- void setup() {
- context = new SpringApplicationBuilder(ApplicationRunner.class,
- IOHandlerConfiguration.class,
- TcpServerConfiguration.class,
- CacheConfiguration.class,
- A6HandlerConfiguration.class,
- PluginRunnerConfiguration.class)
- .web(WebApplicationType.NONE)
- .run();
- }
-
- @Test
- @DisplayName("test listen on socket file success")
- @Disabled
- void testUDSConnectSuccess() {
- Connection client =
- TcpClient.create()
- .remoteAddress(() -> new DomainSocketAddress("/tmp/runner.sock"))
- .connectNow();
- assertThat(client.channel().isOpen()).isTrue();
- assertThat(client.channel().isActive()).isTrue();
- assertThat(client.channel().isRegistered()).isTrue();
- assertThat(client.channel() instanceof DomainSocketChannel).isTrue();
- assertThat(client.channel().remoteAddress().toString()).isEqualTo("/tmp/runner.sock");
- client.disposeNow();
- }
-
- @Test
- @DisplayName("test listen on error socket file")
- void testUDSConnectFail() {
- Throwable exception = assertThrows(RuntimeException.class, () -> {
- TcpClient.create()
- .remoteAddress(() -> new DomainSocketAddress("/tmp/error.sock"))
- .connectNow();
- });
- assertThat(exception.getMessage()).isEqualTo("java.io.FileNotFoundException");
- }
-
- @AfterEach
- @DisplayName("shutdown java plugin runner")
- void down() {
- context.close();
- }
-}
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 a1ee383..bee6636 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
@@ -18,15 +18,16 @@
package org.apache.apisix.plugin.runner;
import com.google.flatbuffers.FlatBufferBuilder;
-import io.github.api7.A6.DataEntry;
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;
import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
@@ -51,7 +52,7 @@ public class HttpResponse implements A6Response {
private String path;
- private Map<String, String> body;
+ private String body;
private HttpResponseStatus status;
@@ -94,12 +95,9 @@ public class HttpResponse implements A6Response {
respHeaders.put(headerKey, headerValue);
}
- public void setBody(String bodyKey, String bodyValue) {
+ public void setBody(String body) {
actionType = ActionType.Stop;
- if (Objects.isNull(body)) {
- body = new HashMap<>();
- }
- body.put(bodyKey, bodyValue);
+ this.body = body;
}
public void setStatus(HttpResponseStatus status) {
@@ -154,16 +152,9 @@ public class HttpResponse implements A6Response {
}
int bodyIndex = -1;
- if (!CollectionUtils.isEmpty(body)) {
- byte[] bodyTexts = new byte[body.size()];
- for (Map.Entry<String, String> arg : body.entrySet()) {
- int i = -1;
- int key = builder.createString(arg.getKey());
- int value = builder.createString(arg.getValue());
- int text = DataEntry.createDataEntry(builder, key, value);
- bodyTexts[++i] = (byte) text;
- }
- bodyIndex = Stop.createBodyVector(builder, bodyTexts);
+ if (StringUtils.hasText(body)) {
+ byte[] bodyBytes = body.getBytes(StandardCharsets.US_ASCII);
+ bodyIndex = Stop.createBodyVector(builder, bodyBytes);
}
Stop.startStop(builder);
@@ -181,7 +172,7 @@ public class HttpResponse implements A6Response {
private int buildRewriteResp(FlatBufferBuilder builder) {
int pathIndex = -1;
- if (Objects.isNull(path)) {
+ if (!Objects.isNull(path)) {
pathIndex = builder.createString(path);
}
diff --git a/runner-plugin-sdk/src/main/java/org/apache/apisix/plugin/runner/HttpRewriteResponse.java b/runner-plugin-sdk/src/main/java/org/apache/apisix/plugin/runner/HttpRewriteResponse.java
deleted file mode 100644
index 820aed8..0000000
--- a/runner-plugin-sdk/src/main/java/org/apache/apisix/plugin/runner/HttpRewriteResponse.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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;
-
-import java.util.Map;
-
-/**
- * table Rewrite {
- * path:string;
- * // To delete a request header, use a TextEntry without Value
- * // To change the upstream host, use a TextEntry with Name equals to `host`
- * headers:[TextEntry];
- * // To delete an argument, use a TextEntry without Value
- * args:[TextEntry];
- * }
- */
-@Deprecated
-public class HttpRewriteResponse extends HttpResponse {
-
- private String path;
-
- private Map<String, String> args;
-
- public HttpRewriteResponse(int requestId) {
- super(requestId);
- }
-
-}
diff --git a/runner-plugin-sdk/src/main/java/org/apache/apisix/plugin/runner/HttpStopResponse.java b/runner-plugin-sdk/src/main/java/org/apache/apisix/plugin/runner/HttpStopResponse.java
deleted file mode 100644
index bc5dbcb..0000000
--- a/runner-plugin-sdk/src/main/java/org/apache/apisix/plugin/runner/HttpStopResponse.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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;
-
-/**
- * table Stop {
- * status:uint16;
- * headers:[TextEntry];
- * body:[ubyte];
- * }
- */
-@Deprecated
-public class HttpStopResponse extends HttpResponse {
-
- private int status;
-
- private byte[] body;
-
- public HttpStopResponse(int requestId) {
- super(requestId);
- }
-
- public void setBody(String body) {
- this.body = body.getBytes();
- }
-
-}
diff --git a/runner-starter/pom.xml b/runner-starter/pom.xml
index be46e1f..72ce898 100644
--- a/runner-starter/pom.xml
+++ b/runner-starter/pom.xml
@@ -47,6 +47,17 @@
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-test</artifactId>
+ <scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>org.junit.vintage</groupId>
+ <artifactId>junit-vintage-engine</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
</dependencies>
<build>
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
new file mode 100644
index 0000000..0262ba1
--- /dev/null
+++ b/runner-starter/src/test/java/org/apache/apisix/plugin/runner/PluginRunnerApplicationTest.java
@@ -0,0 +1,47 @@
+package org.apache.apisix.plugin.runner;
+
+import io.netty.channel.unix.DomainSocketAddress;
+import io.netty.channel.unix.DomainSocketChannel;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import reactor.netty.Connection;
+import reactor.netty.tcp.TcpClient;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+@DisplayName("Unix Domain Socket Listen Test")
+class PluginRunnerApplicationTest {
+
+ @Test
+ void testMain() {
+ PluginRunnerApplication.main(new String[]{"args"});
+ }
+
+ @Test
+ @DisplayName("test listen on socket file success")
+ void testUDSConnectSuccess() {
+ Connection client =
+ TcpClient.create()
+ .remoteAddress(() -> new DomainSocketAddress("/tmp/runner.sock"))
+ .connectNow();
+ assertThat(client.channel().isOpen()).isTrue();
+ assertThat(client.channel().isActive()).isTrue();
+ assertThat(client.channel().isRegistered()).isTrue();
+ assertThat(client.channel() instanceof DomainSocketChannel).isTrue();
+ assertThat(client.channel().remoteAddress().toString()).isEqualTo("/tmp/runner.sock");
+ client.disposeNow();
+ }
+
+ @Test
+ @DisplayName("test listen on error socket file")
+ void testUDSConnectFail() {
+ Throwable exception = assertThrows(RuntimeException.class, () -> {
+ Connection client = TcpClient.create()
+ .remoteAddress(() -> new DomainSocketAddress("/tmp/error.sock"))
+ .connectNow();
+ client.disposeNow();
+ });
+ assertThat(exception.getMessage()).isEqualTo("java.io.FileNotFoundException");
+ }
+}