Skip to content

Commit 05d0017

Browse files
committed
init
1 parent 772e547 commit 05d0017

25 files changed

+1841
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,6 @@
2121

2222
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
2323
hs_err_pid*
24+
.idea/
25+
*.iml
26+
/target

pom.xml

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
3+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<groupId>love.wangqi</groupId>
8+
<artifactId>api-gateway-core</artifactId>
9+
<version>1.0-SNAPSHOT</version>
10+
11+
<name>api-gateway-core</name>
12+
<!-- FIXME change it to the project's website -->
13+
<url>http://www.example.com</url>
14+
15+
<properties>
16+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
17+
<maven.compiler.source>1.8</maven.compiler.source>
18+
<maven.compiler.target>1.8</maven.compiler.target>
19+
</properties>
20+
21+
<dependencies>
22+
<dependency>
23+
<groupId>junit</groupId>
24+
<artifactId>junit</artifactId>
25+
<version>4.11</version>
26+
<scope>test</scope>
27+
</dependency>
28+
<dependency>
29+
<groupId>io.netty</groupId>
30+
<artifactId>netty-all</artifactId>
31+
<version>4.1.25.Final</version>
32+
</dependency>
33+
<dependency>
34+
<groupId>com.fasterxml.jackson.core</groupId>
35+
<artifactId>jackson-databind</artifactId>
36+
<version>2.9.3</version>
37+
</dependency>
38+
<dependency>
39+
<groupId>ch.qos.logback</groupId>
40+
<artifactId>logback-classic</artifactId>
41+
<version>1.2.3</version>
42+
</dependency>
43+
</dependencies>
44+
45+
<build>
46+
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
47+
<plugins>
48+
<plugin>
49+
<artifactId>maven-clean-plugin</artifactId>
50+
<version>3.0.0</version>
51+
</plugin>
52+
<!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
53+
<plugin>
54+
<artifactId>maven-resources-plugin</artifactId>
55+
<version>3.0.2</version>
56+
</plugin>
57+
<plugin>
58+
<artifactId>maven-compiler-plugin</artifactId>
59+
<version>3.7.0</version>
60+
</plugin>
61+
<plugin>
62+
<artifactId>maven-surefire-plugin</artifactId>
63+
<version>2.20.1</version>
64+
</plugin>
65+
<plugin>
66+
<artifactId>maven-jar-plugin</artifactId>
67+
<version>3.0.2</version>
68+
</plugin>
69+
<plugin>
70+
<artifactId>maven-install-plugin</artifactId>
71+
<version>2.5.2</version>
72+
</plugin>
73+
<plugin>
74+
<artifactId>maven-deploy-plugin</artifactId>
75+
<version>2.8.2</version>
76+
</plugin>
77+
</plugins>
78+
</pluginManagement>
79+
</build>
80+
</project>
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
package love.wangqi.codec;
2+
3+
import io.netty.buffer.ByteBuf;
4+
import io.netty.buffer.Unpooled;
5+
import io.netty.handler.codec.http.*;
6+
import io.netty.handler.codec.http.multipart.DefaultHttpDataFactory;
7+
import io.netty.handler.codec.http.multipart.HttpDataFactory;
8+
import io.netty.handler.codec.http.multipart.HttpPostRequestEncoder;
9+
import io.netty.handler.codec.http.multipart.InterfaceHttpData;
10+
import org.slf4j.Logger;
11+
import org.slf4j.LoggerFactory;
12+
import love.wangqi.exception.NoRouteException;
13+
import love.wangqi.route.Route;
14+
import love.wangqi.route.RouteMapper;
15+
16+
import java.net.URI;
17+
import java.net.URL;
18+
import java.nio.charset.StandardCharsets;
19+
import java.util.List;
20+
import java.util.Map;
21+
22+
/**
23+
* @author: wangqi
24+
* @description:
25+
* @date: Created in 2018/5/29 下午7:08
26+
*/
27+
public class DefaultHttpRequestBuilder implements HttpRequestBuilder {
28+
private static final Logger logger = LoggerFactory.getLogger(DefaultHttpRequestBuilder.class);
29+
30+
private RouteMapper routeMapper;
31+
private FullHttpRequest originRequest;
32+
private HttpRequest newRequest;
33+
private HttpPostRequestEncoder newBodyRequestEncoder;
34+
35+
protected HttpRequestDecomposer httpRequestDecomposer;
36+
37+
HttpDataFactory factory = new DefaultHttpDataFactory(DefaultHttpDataFactory.MINSIZE);
38+
39+
public class RequestHolder {
40+
public URL url;
41+
public HttpRequest request;
42+
public HttpPostRequestEncoder bodyRequestEncoder;
43+
44+
public RequestHolder(URL url, HttpRequest request, HttpPostRequestEncoder bodyRequestEncoder) {
45+
this.url = url;
46+
this.request = request;
47+
this.bodyRequestEncoder = bodyRequestEncoder;
48+
}
49+
}
50+
51+
public DefaultHttpRequestBuilder() {
52+
}
53+
54+
@Override
55+
public DefaultHttpRequestBuilder setRouteMapper(RouteMapper routeMapper) {
56+
this.routeMapper = routeMapper;
57+
return this;
58+
}
59+
60+
@Override
61+
public DefaultHttpRequestBuilder setOriginRequest(FullHttpRequest originRequest) {
62+
this.originRequest = originRequest;
63+
this.httpRequestDecomposer = new HttpRequestDecomposer(originRequest);
64+
return this;
65+
}
66+
67+
@Override
68+
public Route getRoute() {
69+
return routeMapper.getRoute(this.originRequest);
70+
}
71+
72+
@Override
73+
public RequestHolder build() throws Exception {
74+
Route route = getRoute();
75+
if (route == null) {
76+
throw new NoRouteException();
77+
}
78+
URL url = route.getMapUrl();
79+
logger.info(url.toString());
80+
81+
// 请求路径
82+
QueryStringEncoder queryStringEncoder = new QueryStringEncoder(url.getPath());
83+
// 请求参数
84+
buildParams(route).forEach((key, values) -> {
85+
values.forEach(value -> {
86+
queryStringEncoder.addParam(key, value);
87+
});
88+
});
89+
newRequest = new DefaultFullHttpRequest(originRequest.protocolVersion(), originRequest.method(), new URI(queryStringEncoder.toString()).toASCIIString());
90+
// 请求头
91+
buildHeaders(route).forEach((key, values) -> {
92+
values.forEach(value -> {
93+
newRequest.headers().set(key, value);
94+
});
95+
});
96+
newRequest.headers().remove(HttpHeaderNames.COOKIE);
97+
newRequest.headers().set(HttpHeaderNames.HOST, url.getHost());
98+
99+
// 请求体
100+
String contentType = httpRequestDecomposer.getContentType();
101+
if (contentType != null) {
102+
if (contentType.startsWith("application/json")) {
103+
ByteBuf bbuf = Unpooled.copiedBuffer(buildContentJson(route), StandardCharsets.UTF_8);
104+
newRequest.headers().set(HttpHeaderNames.CONTENT_LENGTH, bbuf.readableBytes());
105+
((FullHttpRequest)newRequest).content().writeBytes(bbuf);
106+
} else if (contentType.startsWith("application/x-www-form-urlencoded")) {
107+
HttpPostRequestEncoder requestEncoder = new HttpPostRequestEncoder(newRequest, false);
108+
buildContentFormUrlEncoded(route).forEach((key, values) -> {
109+
values.forEach(value -> {
110+
try {
111+
requestEncoder.addBodyAttribute(key, value);
112+
} catch (HttpPostRequestEncoder.ErrorDataEncoderException e) {
113+
logger.error(e.getMessage());
114+
}
115+
});
116+
});
117+
newRequest = (FullHttpRequest) requestEncoder.finalizeRequest();
118+
} else if (contentType.startsWith("multipart/form-data")) {
119+
HttpPostRequestEncoder requestEncoder = new HttpPostRequestEncoder(factory, newRequest, true);
120+
for (InterfaceHttpData data : buildContentFormdata(route)) {
121+
if (data.getHttpDataType() == InterfaceHttpData.HttpDataType.Attribute) {
122+
requestEncoder.addBodyHttpData(data);
123+
} else if (data.getHttpDataType() == InterfaceHttpData.HttpDataType.FileUpload) {
124+
requestEncoder.addBodyHttpData(data);
125+
}
126+
}
127+
HttpRequest hr = requestEncoder.finalizeRequest();
128+
newRequest = hr;
129+
newBodyRequestEncoder = requestEncoder;
130+
} else {
131+
ByteBuf bbuf = buildContentOther(route);
132+
newRequest.headers().set(HttpHeaderNames.CONTENT_LENGTH, bbuf.readableBytes());
133+
((FullHttpRequest)newRequest).content().writeBytes(bbuf);
134+
}
135+
}
136+
return new RequestHolder(url, newRequest, newBodyRequestEncoder);
137+
}
138+
139+
/**
140+
* 返回path(不包含?后面的参数部分)
141+
* @return
142+
*/
143+
protected String buildPath(Route route) {
144+
return httpRequestDecomposer.getPath();
145+
}
146+
147+
/**
148+
* 返回请求的请求参数
149+
* @return
150+
*/
151+
protected Map<String, List<String>> buildParams(Route route) {
152+
return httpRequestDecomposer.getParams();
153+
}
154+
155+
/**
156+
* 返回请求的请求头
157+
* @return
158+
*/
159+
protected Map<String, List<String>> buildHeaders(Route route) {
160+
return httpRequestDecomposer.getHeaders();
161+
}
162+
163+
/**
164+
* 如果content-type为application/json,获取请求体
165+
* @return
166+
*/
167+
protected String buildContentJson(Route route) {
168+
return httpRequestDecomposer.getContentJsonAsString();
169+
}
170+
171+
/**
172+
* 如果content-type为application/x-www-form-urlencoded,获取请求体
173+
* @return
174+
*/
175+
protected Map<String, List<String>> buildContentFormUrlEncoded(Route route) {
176+
return httpRequestDecomposer.getContentFormUrlEncoded();
177+
}
178+
179+
/**
180+
* 如果content-type为multipart/form-data,获取请求体
181+
* @return
182+
*/
183+
protected List<InterfaceHttpData> buildContentFormdata(Route route) {
184+
return httpRequestDecomposer.getContentFormdata();
185+
}
186+
187+
/**
188+
* 其他类型的content-type则直接返回相应的ByteBuf
189+
* @return
190+
*/
191+
private ByteBuf buildContentOther(Route route) {
192+
return httpRequestDecomposer.getContentOther();
193+
}
194+
195+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package love.wangqi.codec;
2+
3+
import io.netty.handler.codec.http.FullHttpRequest;
4+
import love.wangqi.route.Route;
5+
import love.wangqi.route.RouteMapper;
6+
7+
8+
/**
9+
* @author: wangqi
10+
* @description:
11+
* @date: Created in 2018/5/30 下午6:58
12+
*/
13+
public interface HttpRequestBuilder {
14+
/**
15+
* 设置路由映射器
16+
* @param routeMapper
17+
* @return
18+
*/
19+
DefaultHttpRequestBuilder setRouteMapper(RouteMapper routeMapper);
20+
21+
/**
22+
* 设置原始请求
23+
* @param originRequest
24+
* @return
25+
*/
26+
DefaultHttpRequestBuilder setOriginRequest(FullHttpRequest originRequest);
27+
28+
/**
29+
* 生成新的请求
30+
* @return
31+
* @throws Exception
32+
*/
33+
DefaultHttpRequestBuilder.RequestHolder build() throws Exception;
34+
35+
/**
36+
* 获取路由
37+
* @return
38+
*/
39+
Route getRoute();
40+
}

0 commit comments

Comments
 (0)