This commit is contained in:
@@ -77,7 +77,6 @@
|
|||||||
readTimeoutSecond: 读操作超时秒数, 默认0, 表示永久不超时
|
readTimeoutSecond: 读操作超时秒数, 默认0, 表示永久不超时
|
||||||
writeTimeoutSecond: 写操作超时秒数, 默认0, 表示永久不超时
|
writeTimeoutSecond: 写操作超时秒数, 默认0, 表示永久不超时
|
||||||
|
|
||||||
forwardproxy: 正向代理(支持CONNECT); 默认: false, 只有当 protocol==HTTP 才生效
|
|
||||||
-->
|
-->
|
||||||
<server protocol="HTTP" host="127.0.0.1" port="6060" root="root" lib="">
|
<server protocol="HTTP" host="127.0.0.1" port="6060" root="root" lib="">
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import java.util.regex.*;
|
|||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
public final class HttpPrepareServlet extends PrepareServlet<HttpRequest, HttpResponse> {
|
public final class HttpPrepareServlet extends PrepareServlet<HttpRequest, HttpResponse<HttpRequest>> {
|
||||||
|
|
||||||
private ByteBuffer flashPolicyBuffer;
|
private ByteBuffer flashPolicyBuffer;
|
||||||
|
|
||||||
@@ -31,10 +31,6 @@ public final class HttpPrepareServlet extends PrepareServlet<HttpRequest, HttpRe
|
|||||||
|
|
||||||
private SimpleEntry<Predicate<String>, HttpServlet>[] regArray = new SimpleEntry[0];
|
private SimpleEntry<Predicate<String>, HttpServlet>[] regArray = new SimpleEntry[0];
|
||||||
|
|
||||||
private boolean forwardproxy = false;
|
|
||||||
|
|
||||||
private final HttpServlet proxyServlet = new HttpProxyServlet();
|
|
||||||
|
|
||||||
private HttpServlet resourceHttpServlet = new HttpResourceServlet();
|
private HttpServlet resourceHttpServlet = new HttpResourceServlet();
|
||||||
|
|
||||||
private String flashdomain = "*";
|
private String flashdomain = "*";
|
||||||
@@ -69,23 +65,9 @@ public final class HttpPrepareServlet extends PrepareServlet<HttpRequest, HttpRe
|
|||||||
}
|
}
|
||||||
this.flashdomain = config.getValue("crossdomain-domain", "*");
|
this.flashdomain = config.getValue("crossdomain-domain", "*");
|
||||||
this.flashports = config.getValue("crossdomain-ports", "80,443,$");
|
this.flashports = config.getValue("crossdomain-ports", "80,443,$");
|
||||||
this.forwardproxy = config.getBoolValue("forwardproxy", false);
|
|
||||||
if (forwardproxy) this.proxyServlet.init(context, config);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void recycle(HttpRequest request) {
|
|
||||||
request.recycle();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean recycle(HttpResponse response) {
|
|
||||||
return response.recycle();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void prepare(HttpRequest request) {
|
|
||||||
request.prepare();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(HttpRequest request, HttpResponse response) throws IOException {
|
public void execute(HttpRequest request, HttpResponse response) throws IOException {
|
||||||
try {
|
try {
|
||||||
@@ -102,10 +84,6 @@ public final class HttpPrepareServlet extends PrepareServlet<HttpRequest, HttpRe
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final String uri = request.getRequestURI();
|
final String uri = request.getRequestURI();
|
||||||
if (forwardproxy && (uri.charAt(0) != '/' || "CONNECT".equalsIgnoreCase(request.getMethod()))) { //正向代理
|
|
||||||
proxyServlet.execute(request, response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
HttpServlet servlet = this.strmaps.isEmpty() ? null : this.strmaps.get(uri);
|
HttpServlet servlet = this.strmaps.isEmpty() ? null : this.strmaps.get(uri);
|
||||||
if (servlet == null && this.regArray != null) {
|
if (servlet == null && this.regArray != null) {
|
||||||
for (SimpleEntry<Predicate<String>, HttpServlet> en : regArray) {
|
for (SimpleEntry<Predicate<String>, HttpServlet> en : regArray) {
|
||||||
|
|||||||
@@ -1,194 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package com.wentch.redkale.net.http;
|
|
||||||
|
|
||||||
import com.wentch.redkale.net.*;
|
|
||||||
import com.wentch.redkale.util.*;
|
|
||||||
import java.io.*;
|
|
||||||
import java.net.*;
|
|
||||||
import java.nio.*;
|
|
||||||
import java.nio.channels.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 在appliation.xml中的HTTP类型的server节点加上forwardproxy="true"表示该HttpServer支持正向代理
|
|
||||||
*
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
public final class HttpProxyServlet extends HttpServlet {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(HttpRequest request, HttpResponse response) throws IOException {
|
|
||||||
response.skipHeader();
|
|
||||||
if ("CONNECT".equalsIgnoreCase(request.getMethod())) {
|
|
||||||
connect(request, response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String url = request.getRequestURI();
|
|
||||||
url = url.substring(url.indexOf("://") + 3);
|
|
||||||
url = url.substring(url.indexOf('/'));
|
|
||||||
final ByteBuffer buffer = response.getContext().pollBuffer();
|
|
||||||
buffer.put((request.getMethod() + " " + url + " HTTP/1.1\r\n").getBytes());
|
|
||||||
for (AnyValue.Entry<String> en : request.header.getStringEntrys()) {
|
|
||||||
if (!en.name.startsWith("Proxy-")) {
|
|
||||||
buffer.put((en.name + ": " + en.getValue() + "\r\n").getBytes());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (request.getHost() != null) {
|
|
||||||
buffer.put(("Host: " + request.getHost() + "\r\n").getBytes());
|
|
||||||
}
|
|
||||||
if (request.getContentType() != null) {
|
|
||||||
buffer.put(("Content-Type: " + request.getContentType() + "\r\n").getBytes());
|
|
||||||
}
|
|
||||||
if (request.getContentLength() > 0) {
|
|
||||||
buffer.put(("Content-Length: " + request.getContentLength() + "\r\n").getBytes());
|
|
||||||
}
|
|
||||||
buffer.put(HttpResponse.LINE);
|
|
||||||
buffer.flip();
|
|
||||||
final AsyncConnection remote = AsyncConnection.create("TCP", request.getHostSocketAddress(), 6, 6);
|
|
||||||
remote.write(buffer, null, new CompletionHandler<Integer, Void>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void completed(Integer result, Void attachment) {
|
|
||||||
if (buffer.hasRemaining()) {
|
|
||||||
remote.write(buffer, attachment, this);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
response.getContext().offerBuffer(buffer);
|
|
||||||
new ProxyCompletionHandler(remote, request, response).completed(0, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void failed(Throwable exc, Void attachment) {
|
|
||||||
response.getContext().offerBuffer(buffer);
|
|
||||||
response.finish(true);
|
|
||||||
try {
|
|
||||||
remote.close();
|
|
||||||
} catch (IOException ex) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void connect(HttpRequest request, HttpResponse response) throws IOException {
|
|
||||||
final InetSocketAddress remoteAddress = HttpRequest.parseSocketAddress(request.getRequestURI());
|
|
||||||
final AsyncConnection remote = remoteAddress.getPort() == 443
|
|
||||||
? AsyncConnection.create(Utility.createDefaultSSLSocket(remoteAddress)) : AsyncConnection.create("TCP", remoteAddress, 6, 6);
|
|
||||||
final ByteBuffer buffer0 = response.getContext().pollBuffer();
|
|
||||||
buffer0.put("HTTP/1.1 200 Connection established\r\nConnection: close\r\n\r\n".getBytes());
|
|
||||||
buffer0.flip();
|
|
||||||
response.sendBody(buffer0, null, new CompletionHandler<Integer, Void>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void completed(Integer result, Void attachment) {
|
|
||||||
new ProxyCompletionHandler(remote, request, response).completed(0, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void failed(Throwable exc, Void attachment) {
|
|
||||||
response.finish(true);
|
|
||||||
try {
|
|
||||||
remote.close();
|
|
||||||
} catch (IOException ex) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class ProxyCompletionHandler implements CompletionHandler<Integer, Void> {
|
|
||||||
|
|
||||||
private AsyncConnection remote;
|
|
||||||
|
|
||||||
private HttpRequest request;
|
|
||||||
|
|
||||||
private HttpResponse response;
|
|
||||||
|
|
||||||
public ProxyCompletionHandler(AsyncConnection remote, HttpRequest request, HttpResponse response) {
|
|
||||||
this.remote = remote;
|
|
||||||
this.request = request;
|
|
||||||
this.response = response;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void completed(Integer result0, Void v0) {
|
|
||||||
final ByteBuffer rbuffer = request.getContext().pollBuffer();
|
|
||||||
remote.read(rbuffer, null, new CompletionHandler<Integer, Void>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void completed(Integer result, Void attachment) {
|
|
||||||
rbuffer.flip();
|
|
||||||
CompletionHandler parent = this;
|
|
||||||
response.sendBody(rbuffer.duplicate().asReadOnlyBuffer(), null, new CompletionHandler<Integer, Void>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void completed(Integer result, Void attachment) {
|
|
||||||
rbuffer.clear();
|
|
||||||
remote.read(rbuffer, attachment, parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void failed(Throwable exc, Void attachment) {
|
|
||||||
parent.failed(exc, attachment);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void failed(Throwable exc, Void attachment) {
|
|
||||||
response.getContext().offerBuffer(rbuffer);
|
|
||||||
response.finish(true);
|
|
||||||
try {
|
|
||||||
remote.close();
|
|
||||||
} catch (IOException ex) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
final ByteBuffer qbuffer = request.getContext().pollBuffer();
|
|
||||||
request.getChannel().read(qbuffer, null, new CompletionHandler<Integer, Void>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void completed(Integer result, Void attachment) {
|
|
||||||
qbuffer.flip();
|
|
||||||
CompletionHandler parent = this;
|
|
||||||
remote.write(qbuffer, null, new CompletionHandler<Integer, Void>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void completed(Integer result, Void attachment) {
|
|
||||||
qbuffer.clear();
|
|
||||||
request.getChannel().read(qbuffer, null, parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void failed(Throwable exc, Void attachment) {
|
|
||||||
parent.failed(exc, attachment);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void failed(Throwable exc, Void attachment) {
|
|
||||||
response.getContext().offerBuffer(qbuffer);
|
|
||||||
response.finish(true);
|
|
||||||
try {
|
|
||||||
remote.close();
|
|
||||||
} catch (IOException ex) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void failed(Throwable exc, Void v) {
|
|
||||||
response.finish(true);
|
|
||||||
try {
|
|
||||||
remote.close();
|
|
||||||
} catch (IOException ex) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -19,7 +19,7 @@ import java.nio.charset.*;
|
|||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
public final class HttpRequest extends Request {
|
public class HttpRequest extends Request {
|
||||||
|
|
||||||
protected static final Charset UTF8 = Charset.forName("UTF-8");
|
protected static final Charset UTF8 = Charset.forName("UTF-8");
|
||||||
|
|
||||||
|
|||||||
@@ -22,8 +22,9 @@ import java.util.concurrent.atomic.*;
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
|
* @param <R>
|
||||||
*/
|
*/
|
||||||
public final class HttpResponse extends Response<HttpRequest> {
|
public class HttpResponse<R extends HttpRequest> extends Response<R> {
|
||||||
|
|
||||||
private static final ByteBuffer buffer304 = ByteBuffer.wrap("HTTP/1.1 304 Not Modified\r\n\r\n".getBytes()).asReadOnlyBuffer();
|
private static final ByteBuffer buffer304 = ByteBuffer.wrap("HTTP/1.1 304 Not Modified\r\n\r\n".getBytes()).asReadOnlyBuffer();
|
||||||
|
|
||||||
@@ -109,7 +110,7 @@ public final class HttpResponse extends Response<HttpRequest> {
|
|||||||
return new ObjectPool<>(creatCounter, cycleCounter, max, creator, (x) -> ((HttpResponse) x).prepare(), (x) -> ((HttpResponse) x).recycle());
|
return new ObjectPool<>(creatCounter, cycleCounter, max, creator, (x) -> ((HttpResponse) x).prepare(), (x) -> ((HttpResponse) x).recycle());
|
||||||
}
|
}
|
||||||
|
|
||||||
public HttpResponse(Context context, HttpRequest request, String[][] defaultAddHeaders, String[][] defaultSetHeaders, HttpCookie defcookie) {
|
public HttpResponse(Context context, R request, String[][] defaultAddHeaders, String[][] defaultSetHeaders, HttpCookie defcookie) {
|
||||||
super(context, request);
|
super(context, request);
|
||||||
this.defaultAddHeaders = defaultAddHeaders;
|
this.defaultAddHeaders = defaultAddHeaders;
|
||||||
this.defaultSetHeaders = defaultSetHeaders;
|
this.defaultSetHeaders = defaultSetHeaders;
|
||||||
@@ -132,6 +133,11 @@ public final class HttpResponse extends Response<HttpRequest> {
|
|||||||
return super.recycle();
|
return super.recycle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void init(AsyncConnection channel) {
|
||||||
|
super.init(channel);
|
||||||
|
}
|
||||||
|
|
||||||
protected String getHttpCode(int status) {
|
protected String getHttpCode(int status) {
|
||||||
return httpCodes.get(status);
|
return httpCodes.get(status);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import com.wentch.redkale.util.*;
|
|||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
public abstract class HttpServlet implements Servlet<HttpRequest, HttpResponse> {
|
public abstract class HttpServlet implements Servlet<HttpRequest, HttpResponse<HttpRequest>> {
|
||||||
|
|
||||||
AnyValue conf; //当前HttpServlet的配置
|
AnyValue conf; //当前HttpServlet的配置
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user