下面列出了 io.netty.handler.codec.http.HttpRequest # getUri ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* Identify the host of an HTTP request. This method uses the URI of the request if possible, otherwise it attempts to find the host
* in the request headers.
*
* @param httpRequest HTTP request to parse the host from
* @return the host the request is connecting to, or null if no host can be found
*/
public static String getHostFromRequest(HttpRequest httpRequest) {
// try to use the URI from the request first, if the URI starts with http:// or https://. checking for http/https avoids confusing
// java's URI class when the request is for a malformed URL like '//some-resource'.
String host = null;
if (startsWithHttpOrHttps(httpRequest.getUri())) {
try {
URI uri = new URI(httpRequest.getUri());
host = uri.getHost();
} catch (URISyntaxException e) {
}
}
// if there was no host in the URI, attempt to grab the host from the Host header
if (host == null || host.isEmpty()) {
host = parseHostHeader(httpRequest, false);
}
return host;
}
@Override
public void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
if (msg instanceof HttpRequest) {
HttpRequest request = (HttpRequest) msg;
String uri = request.getUri();
switch (uri) {
case "/plaintext":
writeResponse(ctx, request, CONTENT_BUFFER.duplicate(), TYPE_PLAIN, contentLength);
return;
case "/json":
byte[] json = MAPPER.writeValueAsBytes(new Message("Hello, World!"));
writeResponse(ctx, request, Unpooled.wrappedBuffer(json), TYPE_JSON, String.valueOf(json.length));
return;
}
FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.NOT_FOUND, Unpooled.EMPTY_BUFFER, false);
ctx.write(response).addListener(ChannelFutureListener.CLOSE);
}
}
/**
* Identify the host of an HTTP request. This method uses the URI of the request if possible, otherwise it attempts to find the host
* in the request headers.
*
* @param httpRequest HTTP request to parse the host from
* @return the host the request is connecting to, or null if no host can be found
*/
public static String getHostFromRequest(HttpRequest httpRequest) {
// try to use the URI from the request first, if the URI starts with http:// or https://. checking for http/https avoids confusing
// java's URI class when the request is for a malformed URL like '//some-resource'.
String host = null;
if (startsWithHttpOrHttps(httpRequest.getUri())) {
try {
URI uri = new URI(httpRequest.getUri());
host = uri.getHost();
} catch (URISyntaxException e) {
}
}
// if there was no host in the URI, attempt to grab the host from the Host header
if (host == null || host.isEmpty()) {
host = parseHostHeader(httpRequest, false);
}
return host;
}
@Override
public HttpResponse clientToProxyRequest(HttpObject httpObject) {
if (httpObject instanceof HttpRequest) {
HttpRequest httpRequest = (HttpRequest) httpObject;
if (ProxyUtils.isCONNECT(httpRequest)) {
Attribute<String> hostname = ctx.attr(AttributeKey.<String>valueOf(HttpsAwareFiltersAdapter.HOST_ATTRIBUTE_NAME));
String hostAndPort = httpRequest.getUri();
// CONNECT requests contain the port, even when using the default port. a sensible default is to remove the
// default port, since in most cases it is not explicitly specified and its presence (in a HAR file, for example)
// would be unexpected.
String hostNoDefaultPort = BrowserMobHttpUtil.removeMatchingPort(hostAndPort, 443);
hostname.set(hostNoDefaultPort);
}
}
return null;
}
/**
* Identify the host of an HTTP request. This method uses the URI of the request if possible, otherwise it attempts to find the host
* in the request headers.
*
* @param httpRequest HTTP request to parse the host from
* @return the host the request is connecting to, or null if no host can be found
*/
public static String getHostFromRequest(HttpRequest httpRequest) {
// try to use the URI from the request first, if the URI starts with http:// or https://. checking for http/https avoids confusing
// java's URI class when the request is for a malformed URL like '//some-resource'.
String host = null;
if (startsWithHttpOrHttps(httpRequest.getUri())) {
try {
URI uri = new URI(httpRequest.getUri());
host = uri.getHost();
} catch (URISyntaxException e) {
}
}
// if there was no host in the URI, attempt to grab the host from the Host header
if (host == null || host.isEmpty()) {
host = parseHostHeader(httpRequest, false);
}
return host;
}
protected void captureQueryParameters(HttpRequest httpRequest) {
// capture query parameters. it is safe to assume the query string is UTF-8, since it "should" be in US-ASCII (a subset of UTF-8),
// but sometimes does include UTF-8 characters.
QueryStringDecoder queryStringDecoder = new QueryStringDecoder(httpRequest.getUri(), StandardCharsets.UTF_8);
try {
for (Map.Entry<String, List<String>> entry : queryStringDecoder.parameters().entrySet()) {
for (String value : entry.getValue()) {
harEntry.getRequest().getQueryString().add(new HarNameValuePair(entry.getKey(), value));
}
}
} catch (IllegalArgumentException e) {
// QueryStringDecoder will throw an IllegalArgumentException if it cannot interpret a query string. rather than cause the entire request to
// fail by propagating the exception, simply skip the query parameter capture.
harEntry.setComment("Unable to decode query parameters on URI: " + httpRequest.getUri());
log.info("Unable to decode query parameters on URI: " + httpRequest.getUri(), e);
}
}
protected void captureRequestHeaderSize(HttpRequest httpRequest) {
Log.e("InnerHandle", "captureRequestHeaderSize " + harEntry.getId());
String requestLine = httpRequest.getMethod().toString() + ' ' + httpRequest.getUri() + ' ' + httpRequest.getProtocolVersion().toString();
// +2 => CRLF after status line, +4 => header/data separation
long requestHeadersSize = requestLine.length() + 6;
HttpHeaders headers = httpRequest.headers();
requestHeadersSize += BrowserMobHttpUtil.getHeaderSize(headers);
harRequest.getRequest().setHeadersSize(requestHeadersSize);
}
/**
* Resolve remote address
* */
private static InetSocketAddress getRemoteAddress(HttpRequest httpRequest) {
String uri = httpRequest.getUri();
String uriWithoutProtocol;
if (HTTP_PREFIX.matcher(uri).matches()) {
uriWithoutProtocol = StringUtils.substringAfter(uri, "://");
} else {
uriWithoutProtocol = uri;
}
String hostAndPort;
if (uriWithoutProtocol.contains("/")) {
hostAndPort = uriWithoutProtocol.substring(0, uriWithoutProtocol.indexOf("/"));
} else {
hostAndPort = uriWithoutProtocol;
}
String hostName;
int port;
if (hostAndPort.contains(":")) {
int index = hostAndPort.indexOf(":");
hostName = hostAndPort.substring(0, index);
port = Integer.parseInt(hostAndPort.substring(index + 1));
} else {
hostName = hostAndPort;
port = 80;
}
return new InetSocketAddress(hostName, port);
}
/**
* Retrieves the raw (unescaped) path + query string from the specified request. The returned path will not include
* the scheme, host, or port.
*
* @param httpRequest HTTP request
* @return the unescaped path + query string from the HTTP request
* @throws URISyntaxException if the path could not be parsed (due to invalid characters in the URI, etc.)
*/
public static String getRawPathAndParamsFromRequest(HttpRequest httpRequest) throws URISyntaxException {
// if this request's URI contains a full URI (including scheme, host, etc.), strip away the non-path components
if (HttpUtil.startsWithHttpOrHttps(httpRequest.getUri())) {
return getRawPathAndParamsFromUri(httpRequest.getUri());
} else {
// to provide consistent validation behavior for URIs that contain a scheme and those that don't, attempt to parse
// the URI, even though we discard the parsed URI object
new URI(httpRequest.getUri());
return httpRequest.getUri();
}
}
/**
* Returns the full, absolute URL of the specified request for both HTTP and HTTPS URLs. The request may reflect
* modifications from this or other filters. This filter instance must be currently handling the specified request;
* otherwise the results are undefined.
*
* @param modifiedRequest a possibly-modified version of the request currently being processed
* @return the full URL of the request, including scheme, host, port, path, and query parameters
*/
public String getFullUrl(HttpRequest modifiedRequest) {
// special case: for HTTPS requests, the full URL is scheme (https://) + the URI of this request
if (ProxyUtils.isCONNECT(modifiedRequest)) {
// CONNECT requests contain the default port, even if it isn't specified on the request.
String hostNoDefaultPort = BrowserMobHttpUtil.removeMatchingPort(modifiedRequest.getUri(), 443);
return "https://" + hostNoDefaultPort;
}
// To get the full URL, we need to retrieve the Scheme, Host + Port, Path, and Query Params from the request.
// If the request URI starts with http:// or https://, it is already a full URL and can be returned directly.
if (HttpUtil.startsWithHttpOrHttps(modifiedRequest.getUri())) {
return modifiedRequest.getUri();
}
// The URI did not include the scheme and host, so examine the request to obtain them:
// Scheme: the scheme (HTTP/HTTPS) are based on the type of connection, obtained from isHttps()
// Host and Port: available for HTTP and HTTPS requests using the getHostAndPort() helper method.
// Path + Query Params: since the request URI doesn't start with the scheme, we can safely assume that the URI
// contains only the path and query params.
String hostAndPort = getHostAndPort(modifiedRequest);
String path = modifiedRequest.getUri();
String url;
if (isHttps()) {
url = "https://" + hostAndPort + path;
} else {
url = "http://" + hostAndPort + path;
}
return url;
}
@Override
public void channelRead0
(final ChannelHandlerContext ctx, final HttpRequest req) {
uri = req.getUri();
final Channel client = ctx.channel();
Bootstrap proxiedServer = new Bootstrap()
.group(client.eventLoop())
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline p = ch.pipeline();
p.addLast(new HttpRequestEncoder(), new Forwarder(uri, client));
}
});
ChannelFuture f = proxiedServer.connect(host);
proxiedChannel = f.channel();
f.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
if (future.isSuccess()) {
ctx.channel().pipeline().remove(HttpResponseEncoder.class);
HttpRequest newReq = new DefaultFullHttpRequest(HTTP_1_1,
req.getMethod(), req.getUri());
newReq.headers().add(req.headers());
newReq.headers().set(CONNECTION, Values.CLOSE);
future.channel().writeAndFlush(newReq);
} else {
DefaultHttpResponse resp = new DefaultHttpResponse(HTTP_1_1,
INTERNAL_SERVER_ERROR);
resp.headers().set(CONNECTION, Values.CLOSE);
LOG.info("Proxy " + uri + " failed. Cause: ", future.cause());
ctx.writeAndFlush(resp).addListener(ChannelFutureListener.CLOSE);
client.close();
}
}
});
}
protected void captureRequestHeaderSize(HttpRequest httpRequest) {
String requestLine = httpRequest.getMethod().toString() + ' ' + httpRequest.getUri() + ' ' + httpRequest.getProtocolVersion().toString();
// +2 => CRLF after status line, +4 => header/data separation
long requestHeadersSize = requestLine.length() + 6;
HttpHeaders headers = httpRequest.headers();
requestHeadersSize += BrowserMobHttpUtil.getHeaderSize(headers);
harEntry.getRequest().setHeadersSize(requestHeadersSize);
}
public HttpsOriginalHostCaptureFilter(HttpRequest originalRequest, ChannelHandlerContext ctx) {
super(originalRequest, ctx);
// if this is an HTTP CONNECT, set the isHttps attribute on the ChannelHandlerConect and capture the hostname from the original request.
// capturing the original host (and the remapped/modified host in clientToProxyRequest() below) guarantees that we will
// have the "true" host, rather than relying on the Host header in subsequent requests (which may be absent or spoofed by malicious clients).
if (ProxyUtils.isCONNECT(originalRequest)) {
Attribute<String> originalHostAttr = ctx.attr(AttributeKey.<String>valueOf(HttpsAwareFiltersAdapter.ORIGINAL_HOST_ATTRIBUTE_NAME));
String hostAndPort = originalRequest.getUri();
originalHostAttr.set(hostAndPort);
Attribute<Boolean> isHttpsAttr = ctx.attr(AttributeKey.<Boolean>valueOf(HttpsAwareFiltersAdapter.IS_HTTPS_ATTRIBUTE_NAME));
isHttpsAttr.set(true);
}
}
/**
* Returns the full, absolute URL of the specified request for both HTTP and HTTPS URLs. The request may reflect
* modifications from this or other filters. This filter instance must be currently handling the specified request;
* otherwise the results are undefined.
*
* @param modifiedRequest a possibly-modified version of the request currently being processed
* @return the full URL of the request, including scheme, host, port, path, and query parameters
*/
public String getFullUrl(HttpRequest modifiedRequest) {
// special case: for HTTPS requests, the full URL is scheme (https://) + the URI of this request
if (ProxyUtils.isCONNECT(modifiedRequest)) {
// CONNECT requests contain the default port, even if it isn't specified on the request.
String hostNoDefaultPort = BrowserMobHttpUtil.removeMatchingPort(modifiedRequest.getUri(), 443);
return "https://" + hostNoDefaultPort;
}
// To get the full URL, we need to retrieve the Scheme, Host + Port, Path, and Query Params from the request.
// If the request URI starts with http:// or https://, it is already a full URL and can be returned directly.
if (HttpUtil.startsWithHttpOrHttps(modifiedRequest.getUri())) {
return modifiedRequest.getUri();
}
// The URI did not include the scheme and host, so examine the request to obtain them:
// Scheme: the scheme (HTTP/HTTPS) are based on the type of connection, obtained from isHttps()
// Host and Port: available for HTTP and HTTPS requests using the getHostAndPort() helper method.
// Path + Query Params: since the request URI doesn't start with the scheme, we can safely assume that the URI
// contains only the path and query params.
String hostAndPort = getHostAndPort(modifiedRequest);
String path = modifiedRequest.getUri();
String url;
if (isHttps()) {
url = "https://" + hostAndPort + path;
} else {
url = "http://" + hostAndPort + path;
}
return url;
}
/**
* Resolves the request to an application by mapping the request url to the application path.
*
* @param request
* @return the application that this request resolves to
*/
public Application<ApplicationConfiguration> resolve(HttpRequest request) {
String path = request.getUri();
for (Entry<String, Application<ApplicationConfiguration>> entry : getSortedApplications().entrySet()) {
if (path.startsWith(entry.getKey())) {
return entry.getValue();
}
}
return null;
}
@Override
public void handle(RakamHttpRequest request) {
WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(
getWebSocketLocation(request), null, true);
handshaker = wsFactory.newHandshaker(request.getRequest());
if (handshaker == null) {
WebSocketServerHandshakerFactory.sendUnsupportedVersionResponse(request.context().channel());
} else {
HttpRequest request1 = request.getRequest();
DefaultFullHttpRequest defaultFullHttpRequest = new DefaultFullHttpRequest(request1.getProtocolVersion(), request1.getMethod(), request1.getUri());
defaultFullHttpRequest.headers().set(request1.headers());
handshaker.handshake(request.context().channel(), defaultFullHttpRequest);
onOpen(new WebSocketRequest(request));
}
}
/**
* Tells the client that something went wrong trying to proxy its request. If the Bad Gateway is a response to
* an HTTP HEAD request, the response will contain no body, but the Content-Length header will be set to the
* value it would have been if this 502 Bad Gateway were in response to a GET.
*
* @param httpRequest the HttpRequest that is resulting in the Bad Gateway response
* @return true if the connection will be kept open, or false if it will be disconnected
*/
private boolean writeBadGateway(HttpRequest httpRequest) {
String body = "Bad Gateway: " + httpRequest.getUri();
FullHttpResponse response = ProxyUtils.createFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_GATEWAY, body);
if (ProxyUtils.isHEAD(httpRequest)) {
// don't allow any body content in response to a HEAD request
response.content().clear();
}
return respondWithShortCircuitResponse(response);
}
/**
* Tells the client that the request was malformed or erroneous. If the Bad Request is a response to
* an HTTP HEAD request, the response will contain no body, but the Content-Length header will be set to the
* value it would have been if this Bad Request were in response to a GET.
*
* @return true if the connection will be kept open, or false if it will be disconnected
*/
private boolean writeBadRequest(HttpRequest httpRequest) {
String body = "Bad Request to URI: " + httpRequest.getUri();
FullHttpResponse response = ProxyUtils.createFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_REQUEST, body);
if (ProxyUtils.isHEAD(httpRequest)) {
// don't allow any body content in response to a HEAD request
response.content().clear();
}
return respondWithShortCircuitResponse(response);
}
/**
* Returns true if the specified request is a request to an origin server, rather than to a proxy server. If this
* request is being MITM'd, this method always returns false. The format of requests to a proxy server are defined
* in RFC 7230, section 5.3.2 (all other requests are considered requests to an origin server):
<pre>
When making a request to a proxy, other than a CONNECT or server-wide
OPTIONS request (as detailed below), a client MUST send the target
URI in absolute-form as the request-target.
[...]
An example absolute-form of request-line would be:
GET http://www.example.org/pub/WWW/TheProject.html HTTP/1.1
To allow for transition to the absolute-form for all requests in some
future version of HTTP, a server MUST accept the absolute-form in
requests, even though HTTP/1.1 clients will only send them in
requests to proxies.
</pre>
*
* @param httpRequest the request to evaluate
* @return true if the specified request is a request to an origin server, otherwise false
*/
private boolean isRequestToOriginServer(HttpRequest httpRequest) {
// while MITMing, all HTTPS requests are requests to the origin server, since the client does not know
// the request is being MITM'd by the proxy
if (httpRequest.getMethod() == HttpMethod.CONNECT || isMitming()) {
return false;
}
// direct requests to the proxy have the path only without a scheme
String uri = httpRequest.getUri();
return !HTTP_SCHEME.matcher(uri).matches();
}
public final static Map<String,Object> getReqParams(HttpRequest req,String reqIP){
Map<String,Object> params = new HashMap<>();
QueryStringDecoder decoder = new QueryStringDecoder(req.getUri());
for(Map.Entry<String,List<String>> para :decoder.parameters().entrySet()){
params.put(para.getKey(),para.getValue().get(0));
}
params.put("req_ip",reqIP);
return params;
}