Package org.littleshoot.proxy.impl
Class ProxyUtils
java.lang.Object
org.littleshoot.proxy.impl.ProxyUtils
Utilities for the proxy.
-
Field Summary
FieldsModifier and TypeFieldDescriptionprivate static final com.google.common.base.SplitterSplits comma-separated header values (such as Connection) into their individual tokens.private static final TimeZoneprivate static final Patternprivate static final org.slf4j.Loggerprivate static final StringDate format pattern used to parse HTTP date headers in RFC 1123 format.Hop-by-hop headers that should be removed when proxying, as defined by the HTTP 1.1 spec, section 13.5.1 (https://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.5.1). -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionstatic voidaddVia(HttpMessage httpMessage, String alias) Adds the Via header to specify that the message has passed through the proxy.private static booleancheckTrueOrFalse(String val, String str1, String str2) static HttpResponsecopyMutableResponseFields(HttpResponse original) Make a copy of the response including all mutable fields.static FullHttpResponsecreateFullHttpResponse(HttpVersion httpVersion, HttpResponseStatus status) Creates a newFullHttpResponsewith no body contentstatic FullHttpResponsecreateFullHttpResponse(HttpVersion httpVersion, HttpResponseStatus status, String body) Creates a newFullHttpResponsewith the specified String as the body contents (encoded using UTF-8).static FullHttpResponsecreateFullHttpResponse(HttpVersion httpVersion, HttpResponseStatus status, String contentType, ByteBuf body, int contentLength) Creates a newFullHttpResponsewith the specified body.static HttpResponseduplicateHttpResponse(HttpResponse originalResponse) Duplicates the status line and headers of an HttpResponse object.static booleanextractBooleanDefaultFalse(Properties props, String key) static booleanextractBooleanDefaultTrue(Properties props, String key) static intextractInt(Properties props, String key) static intextractInt(Properties props, String key, int defaultValue) static StringformatDate(Date date) Formats the given date according to the RFC 1123 pattern.static StringformatDate(Date date, String pattern) Formats the given date according to the specified pattern.getAllCommaSeparatedHeaderValues(AsciiString headerName, HttpMessage httpMessage) Retrieves all comma-separated values for headers with the specified name on the HttpMessage.static StringAttempts to resolve the local machine's hostname.static booleanisChunked(HttpObject httpObject) If an HttpObject is not the last chunk, then that means there are other chunks that will follow.static booleanisCONNECT(HttpObject httpObject) static booleanReturns true if the HTTP message cannot contain an entity body, according to the HTTP spec.static booleanReturnstrueif the specified string is either "false" or "off" ignoring case.static booleanisHEAD(HttpRequest httpRequest) Returns true if the specified HttpRequest is a HEAD request.static booleanisLastChunk(HttpObject httpObject) If an HttpObject implements the market interface LastHttpContent, it represents the last chunk of a transfer.static booleanisResponseSelfTerminating(HttpResponse response) Returns true if the HTTP response from the server is expected to indicate its own message length/end-of-message.static booleanTests whether the given request indicates that the connection is switching to the WebSocket protocol.static booleanisSwitchingToWebSocketProtocol(HttpResponse response) Tests whether the given response indicates that the connection is switching to the WebSocket protocol.static booleanReturnstrueif the specified string is either "true" or "on" ignoring case.static booleanDetermines if UDT is available on the classpath.static StringparseHostAndPort(HttpRequest httpRequest) Parses the host and port an HTTP request is being sent to.static StringparseHostAndPort(String uri) Parses the host and port an HTTP request is being sent to.static voidremoveSdchEncoding(HttpHeaders headers) Given an HttpHeaders instance, removes 'sdch' from the 'Accept-Encoding' header list (if it exists) and returns the modified instance.static booleanshouldRemoveHopByHopHeader(String headerName) Determines if the specified header should be removed from the proxied response because it is a hop-by-hop header, as defined by the HTTP 1.1 spec in section 13.5.1.splitCommaSeparatedHeaderValues(String headerValue) Splits comma-separated header values into tokens.static voidstripHopByHopHeaders(HttpHeaders headers) Removes all headers that should not be forwarded.static StringStrips the host from a URI string.
-
Field Details
-
SHOULD_NOT_PROXY_HOP_BY_HOP_HEADERS
Hop-by-hop headers that should be removed when proxying, as defined by the HTTP 1.1 spec, section 13.5.1 (https://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.5.1). Transfer-Encoding is NOT included in this list, since LittleProxy does not typically modify the transfer encoding. See alsoshouldRemoveHopByHopHeader(String). Header names are stored as lowercase to make case-insensitive comparisons easier. -
LOG
private static final org.slf4j.Logger LOG -
GMT
-
COMMA_SEPARATED_HEADER_VALUE_SPLITTER
private static final com.google.common.base.Splitter COMMA_SEPARATED_HEADER_VALUE_SPLITTERSplits comma-separated header values (such as Connection) into their individual tokens. -
PATTERN_RFC1123
Date format pattern used to parse HTTP date headers in RFC 1123 format.- See Also:
-
HTTP_PREFIX
-
-
Constructor Details
-
ProxyUtils
public ProxyUtils()
-
-
Method Details
-
stripHost
Strips the host from a URI string. This will turn "https://host.com/path" into "/path".- Parameters:
uri- The URI to transform.- Returns:
- A string with the URI stripped.
-
formatDate
Formats the given date according to the RFC 1123 pattern.- Parameters:
date- The date to format.- Returns:
- An RFC 1123 formatted date string.
- See Also:
-
formatDate
Formats the given date according to the specified pattern. The pattern must conform to that used by thesimple date formatclass.- Parameters:
date- The date to format.pattern- The pattern to use for formatting the date.- Returns:
- A formatted date string.
- Throws:
IllegalArgumentException- If the given date pattern is invalid.- See Also:
-
isLastChunk
If an HttpObject implements the market interface LastHttpContent, it represents the last chunk of a transfer.- See Also:
-
isChunked
If an HttpObject is not the last chunk, then that means there are other chunks that will follow.- See Also:
-
parseHostAndPort
Parses the host and port an HTTP request is being sent to.- Parameters:
httpRequest- The request.- Returns:
- The host and port string.
-
parseHostAndPort
Parses the host and port an HTTP request is being sent to.- Parameters:
uri- The URI.- Returns:
- The host and port string.
-
copyMutableResponseFields
Make a copy of the response including all mutable fields.- Parameters:
original- The original response to copy from.- Returns:
- The copy with all mutable fields from the original.
-
addVia
Adds the Via header to specify that the message has passed through the proxy. The specified alias will be appended to the Via header line. The alias may be the hostname of the machine proxying the request, or a pseudonym. From RFC 7230, section 5.7.1:The received-by portion of the field value is normally the host and optional port number of a recipient server or client that subsequently forwarded the message. However, if the real host is considered to be sensitive information, a sender MAY replace it with a pseudonym.- Parameters:
httpMessage- HTTP message to add the Via header toalias- the alias to provide in the Via header for this proxy
-
isTrue
Returnstrueif the specified string is either "true" or "on" ignoring case.- Parameters:
val- The string in question.- Returns:
trueif the specified string is either "true" or "on" ignoring case, otherwisefalse.
-
isFalse
Returnstrueif the specified string is either "false" or "off" ignoring case.- Parameters:
val- The string in question.- Returns:
trueif the specified string is either "false" or "off" ignoring case, otherwisefalse.
-
extractBooleanDefaultFalse
-
extractBooleanDefaultTrue
-
extractInt
-
extractInt
-
isCONNECT
-
isHEAD
Returns true if the specified HttpRequest is a HEAD request.- Parameters:
httpRequest- http request- Returns:
- true if request is a HEAD, otherwise false
-
checkTrueOrFalse
-
isContentAlwaysEmpty
Returns true if the HTTP message cannot contain an entity body, according to the HTTP spec. This code is taken directly fromHttpObjectDecoder.isContentAlwaysEmpty(HttpMessage).- Parameters:
msg- HTTP message- Returns:
- true if the HTTP message is always empty, false if the message may have entity content.
-
isResponseSelfTerminating
Returns true if the HTTP response from the server is expected to indicate its own message length/end-of-message. Returns false if the server is expected to indicate the end of the HTTP entity by closing the connection.This method is based on the allowed message length indicators in the HTTP specification, section 4.4:
4.4 Message Length The transfer-length of a message is the length of the message-body as it appears in the message; that is, after any transfer-codings have been applied. When a message-body is included with a message, the transfer-length of that body is determined by one of the following (in order of precedence): 1.Any response message which "MUST NOT" include a message-body (such as the 1xx, 204, and 304 responses and any response to a HEAD request) is always terminated by the first empty line after the header fields, regardless of the entity-header fields present in the message. 2.If a Transfer-Encoding header field (section 14.41) is present and has any value other than "identity", then the transfer-length is defined by use of the "chunked" transfer-coding (section 3.6), unless the message is terminated by closing the connection. 3.If a Content-Length header field (section 14.13) is present, its decimal value in OCTETs represents both the entity-length and the transfer-length. The Content-Length header field MUST NOT be sent if these two lengths are different (i.e., if a Transfer-Encoding header field is present). If a message is received with both a Transfer-Encoding header field and a Content-Length header field, the latter MUST be ignored. [LP note: multipart/byteranges support has been removed from the HTTP 1.1 spec by RFC 7230, section A.2. Since it is seldom used, LittleProxy does not check for it.] 5.By the server closing the connection. (Closing the connection cannot be used to indicate the end of a request body, since that would leave no possibility for the server to send back a response.)The rules for Transfer-Encoding are clarified in RFC 7230, section 3.3.1 and 3.3.3 (3):If any transfer coding other than chunked is applied to a response payload body, the sender MUST either apply chunked as the final transfer coding or terminate the message by closing the connection.- Parameters:
response- the HTTP response object- Returns:
- true if the message will indicate its own message length, or false if the server is expected to indicate the message length by closing the connection
-
getAllCommaSeparatedHeaderValues
public static List<String> getAllCommaSeparatedHeaderValues(AsciiString headerName, HttpMessage httpMessage) Retrieves all comma-separated values for headers with the specified name on the HttpMessage. Any whitespace (spaces or tabs) surrounding the values will be removed. Empty values (e.g. two consecutive commas, or a value followed by a comma and no other value) will be removed; they will not appear as empty elements in the returned list. If the message contains repeated headers, their values will be added to the returned list in the order in which the headers appear. For example, if a message has headers like:Transfer-Encoding: gzip,deflate Transfer-Encoding: chunkedThis method will return a list of three values: "gzip", "deflate", "chunked".Placing values on multiple header lines is allowed under certain circumstances in RFC 2616 section 4.2, and in RFC 7230 section 3.2.2 quoted here:
A sender MUST NOT generate multiple header fields with the same field name in a message unless either the entire field value for that header field is defined as a comma-separated list [i.e., #(values)] or the header field is a well-known exception (as noted below). A recipient MAY combine multiple header fields with the same field name into one "field-name: field-value" pair, without changing the semantics of the message, by appending each subsequent field value to the combined field value in order, separated by a comma. The order in which header fields with the same field name are received is therefore significant to the interpretation of the combined field value; a proxy MUST NOT change the order of these field values when forwarding a message.- Parameters:
headerName- the name of the header for which values will be retrievedhttpMessage- the HTTP message whose header values will be retrieved- Returns:
- a list of single header values, or an empty list if the header was not present in the message or contained no values
-
duplicateHttpResponse
Duplicates the status line and headers of an HttpResponse object. Does not duplicate any content associated with that response.- Parameters:
originalResponse- HttpResponse to be duplicated- Returns:
- a new HttpResponse with the same status line and headers
-
getHostName
Attempts to resolve the local machine's hostname.- Returns:
- the local machine's hostname, or null if a hostname cannot be determined
-
shouldRemoveHopByHopHeader
Determines if the specified header should be removed from the proxied response because it is a hop-by-hop header, as defined by the HTTP 1.1 spec in section 13.5.1. The comparison is case-insensitive, so "Connection" will be treated the same as "connection" or "CONNECTION". From https://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.5.1 :The following HTTP/1.1 headers are hop-by-hop headers: - Connection - Keep-Alive - Proxy-Authenticate - Proxy-Authorization - TE - Trailers [LittleProxy note: actual header name is Trailer] - Transfer-Encoding [LittleProxy note: this header is not normally removed when proxying, since the proxy does not re-chunk responses. The exception is when an HttpObjectAggregator is enabled, which aggregates chunked content and removes the 'Transfer-Encoding: chunked' header itself.] - Upgrade All other headers defined by HTTP/1.1 are end-to-end headers.- Parameters:
headerName- the header name- Returns:
- true if this header is a hop-by-hop header and should be removed when proxying, otherwise false
-
stripHopByHopHeaders
Removes all headers that should not be forwarded. See RFC 2616 13.5.1 End-to-end and Hop-by-hop Headers.- Parameters:
headers- The headers to modify
-
splitCommaSeparatedHeaderValues
Splits comma-separated header values into tokens. For example, if the value of the Connection header is "Transfer-Encoding, close", this method will return "Transfer-Encoding" and "close". This method strips trims any optional whitespace from the tokens. UnlikegetAllCommaSeparatedHeaderValues(AsciiString, HttpMessage), this method only operates on a single header value, rather than all instances of the header in a message.- Parameters:
headerValue- the un-tokenized header value (must not be null)- Returns:
- all tokens within the header value, or an empty list if there are no values
-
isUdtAvailable
public static boolean isUdtAvailable()Determines if UDT is available on the classpath.- Returns:
- true if UDT is available
-
createFullHttpResponse
public static FullHttpResponse createFullHttpResponse(HttpVersion httpVersion, HttpResponseStatus status, String body) Creates a newFullHttpResponsewith the specified String as the body contents (encoded using UTF-8).- Parameters:
httpVersion- HTTP version of the responsestatus- HTTP status codebody- body to include in the FullHttpResponse; will be UTF-8 encoded- Returns:
- new http response object
-
createFullHttpResponse
public static FullHttpResponse createFullHttpResponse(HttpVersion httpVersion, HttpResponseStatus status) Creates a newFullHttpResponsewith no body content- Parameters:
httpVersion- HTTP version of the responsestatus- HTTP status code- Returns:
- new http response object
-
createFullHttpResponse
public static FullHttpResponse createFullHttpResponse(HttpVersion httpVersion, HttpResponseStatus status, String contentType, ByteBuf body, int contentLength) Creates a newFullHttpResponsewith the specified body.- Parameters:
httpVersion- HTTP version of the responsestatus- HTTP status codecontentType- the Content-Type of the bodybody- body to include in the FullHttpResponse; if nullcontentLength- number of bytes to send in the Content-Length header; should equal the number of bytes in the ByteBuf- Returns:
- new http response object
-
removeSdchEncoding
Given an HttpHeaders instance, removes 'sdch' from the 'Accept-Encoding' header list (if it exists) and returns the modified instance. Removes all occurrences of 'sdch' from the 'Accept-Encoding' header.- Parameters:
headers- The headers to modify.
-
isSwitchingToWebSocketProtocol
Tests whether the given response indicates that the connection is switching to the WebSocket protocol.- Parameters:
response- the response to check.- Returns:
- true if switching to the WebSocket protocol; false otherwise;
-
isSwitchingToWebSocketProtocol
Tests whether the given request indicates that the connection is switching to the WebSocket protocol.- Parameters:
request- the request to check.- Returns:
- true if switching to the WebSocket protocol; false otherwise;
-