Skip to content

Commit 39bf9fe

Browse files
MentosLmr3
andauthored
feat: compatible with non-standard REST interface request to obtain body logic (#146)
* 兼容不规范REST接口请求获取body逻辑 * 更改判断取值方式 * 增加多类型匹配 * 修改泛型+unitTest * 调整代码逻辑+增加unitTest * 调整方案 * 修复tkmybatis序列化循环引用 * 去除其他task * Update JacksonSerializer.java * Optimize code --------- Co-authored-by: mr3 <[email protected]>
1 parent cf80ae1 commit 39bf9fe

File tree

12 files changed

+413
-6
lines changed

12 files changed

+413
-6
lines changed

arex-instrumentation/servlet/arex-httpservlet/src/main/java/io/arex/inst/httpservlet/ServletExtractor.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
package io.arex.inst.httpservlet;
22

33
import io.arex.agent.bootstrap.model.Mocker;
4-
import io.arex.agent.bootstrap.util.StringUtil;
54
import io.arex.inst.httpservlet.adapter.ServletAdapter;
5+
import io.arex.inst.httpservlet.converter.HttpMessageConvertFactory;
6+
import io.arex.inst.httpservlet.converter.HttpMessageConverter;
67
import io.arex.inst.runtime.context.ArexContext;
78
import io.arex.inst.runtime.context.ContextManager;
89
import io.arex.inst.runtime.model.ArexConstants;
@@ -142,11 +143,9 @@ private Map<String, String> getResponseHeaders() {
142143
}
143144

144145
private String getRequest() {
145-
if ("GET".equals(adapter.getMethod(httpServletRequest))) {
146-
return StringUtil.EMPTY;
147-
}
148-
// Compatible with custom message converters that include compression
149-
return Base64.getEncoder().encodeToString(adapter.getRequestBytes(httpServletRequest));
146+
HttpMessageConverter converter = HttpMessageConvertFactory.getSupportedConverter(
147+
httpServletRequest, adapter);
148+
return Base64.getEncoder().encodeToString(converter.getRequest(httpServletRequest, adapter));
150149
}
151150

152151
private Object getResponse() {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package io.arex.inst.httpservlet.converter;
2+
3+
import io.arex.inst.httpservlet.adapter.ServletAdapter;
4+
import io.arex.inst.httpservlet.converter.impl.DefaultHttpMessageConverter;
5+
6+
import java.util.*;
7+
8+
public class HttpMessageConvertFactory {
9+
10+
private static final List<HttpMessageConverter> HTTP_MESSAGE_CONVERTERS = new ArrayList<>();
11+
12+
static {
13+
ServiceLoader<HttpMessageConverter> loader = ServiceLoader.load(HttpMessageConverter.class);
14+
Iterator<HttpMessageConverter> iterator = loader.iterator();
15+
while (iterator.hasNext()) {
16+
HTTP_MESSAGE_CONVERTERS.add(iterator.next());
17+
}
18+
}
19+
20+
21+
public static <HttpServletRequest, HttpServletResponse> HttpMessageConverter getSupportedConverter(
22+
HttpServletRequest request, ServletAdapter<HttpServletRequest, HttpServletResponse> adapter) {
23+
if (request == null || adapter == null) {
24+
return DefaultHttpMessageConverter.getInstance();
25+
}
26+
27+
for (HttpMessageConverter converter : HTTP_MESSAGE_CONVERTERS) {
28+
if (converter.support(request, adapter)) {
29+
return converter;
30+
}
31+
}
32+
33+
return DefaultHttpMessageConverter.getInstance();
34+
}
35+
36+
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package io.arex.inst.httpservlet.converter;
2+
3+
import io.arex.inst.httpservlet.adapter.ServletAdapter;
4+
5+
public interface HttpMessageConverter<HttpServletRequest, HttpServletResponse> {
6+
7+
boolean support(HttpServletRequest request, ServletAdapter<HttpServletRequest, HttpServletResponse> adapter);
8+
9+
byte[] getRequest(HttpServletRequest request, ServletAdapter<HttpServletRequest, HttpServletResponse> adapter);
10+
11+
byte[] getResponse(HttpServletResponse response, ServletAdapter<HttpServletRequest, HttpServletResponse> adapter);
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package io.arex.inst.httpservlet.converter.impl;
2+
3+
import io.arex.inst.httpservlet.adapter.ServletAdapter;
4+
import io.arex.inst.httpservlet.converter.HttpMessageConverter;
5+
6+
public class DefaultHttpMessageConverter<HttpServletRequest, HttpServletResponse> implements
7+
HttpMessageConverter<HttpServletRequest, HttpServletResponse> {
8+
9+
private DefaultHttpMessageConverter() {
10+
}
11+
12+
private static final HttpMessageConverter INSTANCE = new DefaultHttpMessageConverter<>();
13+
14+
public static HttpMessageConverter getInstance() {
15+
return INSTANCE;
16+
}
17+
18+
19+
@Override
20+
public boolean support(HttpServletRequest request, ServletAdapter<HttpServletRequest, HttpServletResponse> adapter) {
21+
return false;
22+
}
23+
24+
@Override
25+
public byte[] getRequest(HttpServletRequest request, ServletAdapter<HttpServletRequest, HttpServletResponse> adapter) {
26+
return adapter.getRequestBytes(request);
27+
}
28+
29+
@Override
30+
public byte[] getResponse(HttpServletResponse response,
31+
ServletAdapter<HttpServletRequest, HttpServletResponse> adapter) {
32+
return new byte[0];
33+
}
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package io.arex.inst.httpservlet.converter.impl;
2+
3+
import io.arex.agent.bootstrap.util.StringUtil;
4+
import io.arex.inst.httpservlet.adapter.ServletAdapter;
5+
import io.arex.inst.httpservlet.converter.HttpMessageConverter;
6+
7+
public class JsonHttpMessageConverter<HttpServletRequest, HttpServletResponse> implements
8+
HttpMessageConverter<HttpServletRequest, HttpServletResponse> {
9+
10+
private static final String CONTENT_TYPE = "application/json";
11+
12+
@Override
13+
public boolean support(HttpServletRequest request, ServletAdapter<HttpServletRequest, HttpServletResponse> adapter) {
14+
String contentType = adapter.getContentType(request);
15+
return StringUtil.isNotEmpty(contentType) && contentType.contains(CONTENT_TYPE);
16+
}
17+
18+
@Override
19+
public byte[] getRequest(HttpServletRequest request,
20+
ServletAdapter<HttpServletRequest, HttpServletResponse> adapter) {
21+
return adapter.getRequestBytes(request);
22+
}
23+
24+
@Override
25+
public byte[] getResponse(HttpServletResponse response,
26+
ServletAdapter<HttpServletRequest, HttpServletResponse> adapter) {
27+
return new byte[0];
28+
}
29+
}
30+
31+
32+
33+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package io.arex.inst.httpservlet.converter.impl;
2+
3+
import io.arex.agent.bootstrap.util.StringUtil;
4+
import io.arex.inst.httpservlet.adapter.ServletAdapter;
5+
import io.arex.inst.httpservlet.converter.HttpMessageConverter;
6+
7+
8+
public class XmlHttpMessageConverter<HttpServletRequest, HttpServletResponse> implements
9+
HttpMessageConverter<HttpServletRequest, HttpServletResponse> {
10+
11+
private static final String CONTENT_TYPE = "application/xml";
12+
13+
@Override
14+
public boolean support(HttpServletRequest request, ServletAdapter<HttpServletRequest, HttpServletResponse> adapter) {
15+
String contentType = adapter.getContentType(request);
16+
return StringUtil.isNotEmpty(contentType) && contentType.contains(CONTENT_TYPE);
17+
}
18+
19+
@Override
20+
public byte[] getRequest(HttpServletRequest request,
21+
ServletAdapter<HttpServletRequest, HttpServletResponse> adapter) {
22+
return adapter.getRequestBytes(request);
23+
}
24+
25+
@Override
26+
public byte[] getResponse(HttpServletResponse response,
27+
ServletAdapter<HttpServletRequest, HttpServletResponse> adapter) {
28+
return new byte[0];
29+
}
30+
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
io.arex.inst.httpservlet.converter.impl.JsonHttpMessageConverter
2+
io.arex.inst.httpservlet.converter.impl.XmlHttpMessageConverter
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package io.arex.inst.httpservlet.converter;
2+
3+
import static org.junit.jupiter.api.Assertions.*;
4+
import static org.mockito.Mockito.when;
5+
6+
import io.arex.inst.httpservlet.adapter.impl.ServletAdapterImplV3;
7+
import io.arex.inst.httpservlet.adapter.impl.ServletAdapterImplV5;
8+
import io.arex.inst.httpservlet.converter.impl.DefaultHttpMessageConverter;
9+
import io.arex.inst.httpservlet.converter.impl.JsonHttpMessageConverter;
10+
import io.arex.inst.httpservlet.converter.impl.XmlHttpMessageConverter;
11+
import org.junit.jupiter.api.AfterEach;
12+
import org.junit.jupiter.api.BeforeEach;
13+
import org.junit.jupiter.api.Test;
14+
import org.mockito.Mockito;
15+
16+
import javax.servlet.http.HttpServletRequest;
17+
18+
public class HttpMessageConvertFactoryTest {
19+
ServletAdapterImplV3 adapterV3 = ServletAdapterImplV3.getInstance();
20+
ServletAdapterImplV5 adapterV5 = ServletAdapterImplV5.getInstance();
21+
HttpServletRequest mockJsonRequest = Mockito.mock(HttpServletRequest.class);
22+
jakarta.servlet.http.HttpServletRequest mockXmlRequest = Mockito.mock(jakarta.servlet.http.HttpServletRequest.class);
23+
24+
@BeforeEach
25+
void setUp() {
26+
}
27+
28+
@AfterEach
29+
void tearDown() {
30+
}
31+
32+
@Test
33+
void getSupportedConverter() {
34+
when(mockJsonRequest.getContentType()).thenReturn("application/json");
35+
when(mockXmlRequest.getContentType()).thenReturn("application/xml");
36+
assertInstanceOf(JsonHttpMessageConverter.class, HttpMessageConvertFactory.getSupportedConverter(
37+
mockJsonRequest, adapterV3));
38+
assertInstanceOf(XmlHttpMessageConverter.class, HttpMessageConvertFactory.getSupportedConverter(mockXmlRequest,
39+
adapterV5));
40+
}
41+
42+
@Test
43+
void getDefaultConverter() {
44+
when(mockJsonRequest.getContentType()).thenReturn("application/jn");
45+
when(mockXmlRequest.getContentType()).thenReturn("application/jn");
46+
47+
assertInstanceOf(DefaultHttpMessageConverter.class, HttpMessageConvertFactory.getSupportedConverter(null,
48+
adapterV3));
49+
50+
assertInstanceOf(DefaultHttpMessageConverter.class, HttpMessageConvertFactory.getSupportedConverter(mockJsonRequest,
51+
null));
52+
53+
assertInstanceOf(DefaultHttpMessageConverter.class, HttpMessageConvertFactory.getSupportedConverter(mockJsonRequest,
54+
adapterV3));
55+
assertInstanceOf(DefaultHttpMessageConverter.class, HttpMessageConvertFactory.getSupportedConverter(mockXmlRequest,
56+
adapterV5));
57+
}
58+
59+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package io.arex.inst.httpservlet.converter.impl;
2+
3+
import static org.junit.jupiter.api.Assertions.*;
4+
5+
import io.arex.inst.httpservlet.adapter.impl.ServletAdapterImplV3;
6+
import io.arex.inst.httpservlet.adapter.impl.ServletAdapterImplV5;
7+
import io.arex.inst.httpservlet.converter.HttpMessageConverter;
8+
import javax.servlet.http.HttpServletRequest;
9+
import javax.servlet.http.HttpServletResponse;
10+
import org.junit.jupiter.api.AfterAll;
11+
import org.junit.jupiter.api.AfterEach;
12+
import org.junit.jupiter.api.BeforeAll;
13+
import org.junit.jupiter.api.BeforeEach;
14+
import org.junit.jupiter.api.Test;
15+
import org.mockito.Mockito;
16+
17+
class DefaultHttpMessageConverterTest {
18+
static HttpMessageConverter defaultHttpMessageConverter = null;
19+
20+
HttpServletRequest mockRequest = Mockito.mock(HttpServletRequest.class);
21+
HttpServletResponse mockResponse = Mockito.mock(HttpServletResponse.class);
22+
23+
ServletAdapterImplV3 instance3 = ServletAdapterImplV3.getInstance();
24+
ServletAdapterImplV5 instance5 = ServletAdapterImplV5.getInstance();
25+
jakarta.servlet.http.HttpServletRequest mockRequest5 = Mockito.mock(jakarta.servlet.http.HttpServletRequest.class);
26+
jakarta.servlet.http.HttpServletResponse mockResponse5 = Mockito.mock(jakarta.servlet.http.HttpServletResponse.class);
27+
28+
29+
@BeforeAll
30+
static void setUp() {
31+
defaultHttpMessageConverter = DefaultHttpMessageConverter.getInstance();
32+
33+
}
34+
35+
@AfterAll
36+
static void tearDown() {
37+
}
38+
39+
40+
@Test
41+
void support() {
42+
assertFalse(defaultHttpMessageConverter.support(null, null));
43+
}
44+
45+
@Test
46+
void getRequest() {
47+
assertEquals(0, defaultHttpMessageConverter.getRequest(instance3.wrapRequest(mockRequest),instance3).length);
48+
assertEquals(0, defaultHttpMessageConverter.getRequest(instance5.wrapRequest(mockRequest5),instance5).length);
49+
}
50+
51+
52+
@Test
53+
void getResponse() {
54+
assertEquals(0, defaultHttpMessageConverter.getResponse(instance3.wrapResponse(mockResponse),instance3).length);
55+
assertEquals(0, defaultHttpMessageConverter.getResponse(instance5.wrapResponse(mockResponse5),instance5).length);
56+
}
57+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package io.arex.inst.httpservlet.converter.impl;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
import static org.mockito.Mockito.when;
5+
6+
import io.arex.inst.httpservlet.adapter.impl.ServletAdapterImplV3;
7+
import io.arex.inst.httpservlet.adapter.impl.ServletAdapterImplV5;
8+
import javax.servlet.http.HttpServletRequest;
9+
import javax.servlet.http.HttpServletResponse;
10+
import org.junit.jupiter.api.AfterEach;
11+
import org.junit.jupiter.api.BeforeEach;
12+
import org.junit.jupiter.api.Test;
13+
import org.mockito.Mockito;
14+
15+
public class JsonHttpMessageConverterTest {
16+
17+
HttpServletRequest mockRequest = Mockito.mock(HttpServletRequest.class);
18+
HttpServletResponse mockResponse = Mockito.mock(HttpServletResponse.class);
19+
20+
ServletAdapterImplV3 instance3 = ServletAdapterImplV3.getInstance();
21+
ServletAdapterImplV5 instance5 = ServletAdapterImplV5.getInstance();
22+
jakarta.servlet.http.HttpServletRequest mockRequest5 = Mockito.mock(jakarta.servlet.http.HttpServletRequest.class);
23+
jakarta.servlet.http.HttpServletResponse mockResponse5 = Mockito.mock(
24+
jakarta.servlet.http.HttpServletResponse.class);
25+
26+
27+
static JsonHttpMessageConverter jsonHttpMessageConverter = null;
28+
29+
30+
@BeforeEach
31+
void setUp() {
32+
jsonHttpMessageConverter = new JsonHttpMessageConverter();
33+
34+
}
35+
36+
@AfterEach
37+
void tearDown() {
38+
}
39+
40+
@Test
41+
void match() {
42+
when(mockRequest.getContentType()).thenReturn("application/json");
43+
when(mockRequest5.getContentType()).thenReturn("application/json");
44+
assertEquals(true, jsonHttpMessageConverter.support(mockRequest, instance3));
45+
assertEquals(true, jsonHttpMessageConverter.support(mockRequest5, instance5));
46+
}
47+
48+
49+
@Test
50+
void notMatch1() {
51+
when(mockRequest.getContentType()).thenReturn("application/jn");
52+
when(mockRequest5.getContentType()).thenReturn("application/n");
53+
assertEquals(false, jsonHttpMessageConverter.support(mockRequest, instance3));
54+
assertEquals(false, jsonHttpMessageConverter.support(mockRequest5, instance5));
55+
}
56+
57+
58+
@Test
59+
void getRequest() {
60+
assertEquals(0, jsonHttpMessageConverter.getRequest(instance3.wrapRequest(mockRequest), instance3).length);
61+
assertEquals(0, jsonHttpMessageConverter.getRequest(instance5.wrapRequest(mockRequest5), instance5).length);
62+
}
63+
64+
65+
@Test
66+
void getResponse() {
67+
assertEquals(0, jsonHttpMessageConverter.getResponse(instance3.wrapResponse(mockResponse), instance3).length);
68+
assertEquals(0, jsonHttpMessageConverter.getResponse(instance5.wrapResponse(mockResponse5), instance5).length);
69+
}
70+
71+
}

0 commit comments

Comments
 (0)