public interface HttpRequest
An http request contains a method, a URI, some headers, and optionally an entity.
See HttpRequestImpl
for a mutable implementation.
Abstract Methods | |
---|---|
InetAddress |
ip()
IP address of the client.
|
boolean |
isHttps()
Whether this is an HTTPS request.
|
String |
method()
Request method.
|
String |
uri()
The request URI.
|
Map<String,String> |
headers()
Request headers.
|
HttpEntity |
entity()
Request entity; null if none.
|
Default Methods | |
String |
scheme()
The scheme, either "https" or "http".
|
List<X509Certificate> |
certs()
Certificates of the client.
|
String |
host()
The "Host" header of the request.
|
String |
absoluteUri()
The absolute request URI.
|
String |
uriPath()
The path component of the request URI.
|
String |
uriParam(String name)
Get the value of a parameter in the request URI.
|
String |
httpVersion()
The HTTP version of the request.
|
String |
header(String name)
Get the value of a header.
|
boolean |
acceptsGzip()
Whether the client accepts "gzip" Content-Encoding.
|
Map<String,String> |
cookies()
Request cookies.
|
String |
cookie(String name)
Get the value of a cookie.
|
Static Methods | |
HttpRequest |
current()
The current fiber-local request; null if none.
|
void |
setFiberLocal(HttpRequest request)
Set the fiber-local request.
|
HttpRequestImpl |
toGet(String uri)
Create a GET request.
|
HttpRequestImpl |
toPost(String uri,
String entityContentType,
byte[] entityBody)
Create a POST request.
|
InetAddress ip()
This IP address may reflect the "X-Forwarded-For"
header,
see HttpServerConf.xForwardLevel(int)
.
boolean isHttps()
This value may reflect the "X-Forwarded-Proto"
header,
see HttpServerConf.xForwardLevel(int)
.
scheme()
default String scheme()
scheme()
and isHttps()
must be consistent with each other.
The default implementation is
return isHttps() ? "https" : "http";
default List<X509Certificate> certs()
SSLSession.getPeerCertificates()
.
Return an empty list if this information is not available.
The default implementation returns an empty list.
String method()
Request methods are case sensitive, and typically in all upper cases, e.g. "GET".
If the method is "HEAD", an HttpServer application can usually treat it as "GET".
default String host()
This method must return a non-null, valid "host[:port]"
, in lower case.
e.g. "example.com", "localhost:8080"
.
The "host" part could be
"example.com"
, "localhost"
"192.168.68.100"
[]
, e.g. "[2001:db8::ff00:42:8329]"
The "port" part is mandatory if the request method is "CONNECT".
The default implementation returns header("Host").toLowerCase()
.
String uri()
In most cases, uri()
returns path-query, which is defined here as
(in the context of RFC7230)
path-query = absolute-path [ "?" query ]
for example: "/", "/page1", "/search?q=cat"
.
They are non-empty and always start with "/".
However, there are 2 special cases:
for a "CONNECT" request,
uri()
returns host:port
, same as the host()
method.
for an "OPTIONS *" request,
uri()
returns "*"
( Note that CONNECT and OPTIONS are disabled by default in
HttpServerConf.supportedMethods(String...)
)
The uri()
method never returns an absolute URI;
see absoluteUri()
instead.
Our definition of uri()
is consistent with
Request-URI in RFC2616,
as well as
request-target in RFC7230.
Chars in URI
We use java String
to represent URIs,
however, a URI is really a sequence of octets.
Each char
in the String
should be interpreted as a byte
. Applications may need to convert the String
to byte[] (using ISO-8859-1 charset), convert "%HH" to byte `0xHH`, and convert bytes
to unicode characters (typically as UTF-8).
According to RFC3986, the only allowed octets in URI path and query are
ALPHA DIGIT - . _ ~ ! $ ' & ( ) * + , ; = : @ / ? %
Applications should generate URIs using only these octets for maximum interoperability. However, the reality is that major browsers and other HTTP implementations could also use other octets in URIs. To accommodate that, our library allows the following octets in URI path and query
0x21-0xFF, excluding 0x23(#)
default String absoluteUri()
In most cases, absolute URI includes scheme, host, and path-query (see uri()
doc):
absoluteUri() = scheme()+"://"+host()+uri()
for example, "https://example.com/", "http://localhost:8080/search?q=cat"
However, in the 2 special cases of
"CONNECT" and
"OPTIONS *" requests
(see uri()
doc)
absoluteUri() = scheme()+"://"+host()
for example, "https://example.com"
. Notice the lack of a trailing slash.
Our definition of absoluteUri()
is consistent with
Effective Request URI
in RFC7230.
default String uriPath()
The path is the substring before the first question mark ("?").
For example, if uri()=="/query?term=cat"
, then uriPath()=="/query"
.
default String uriParam(String name)
For example, if uri()=="/query?term=cat"
, then uriParam("term")=="cat"
.
The query component of the request URI is parsed as "application/x-www-form-urlencoded"
with UTF-8 charset. If there's any parsing error, this method returns null
.
See FormParser
for more options.
default String httpVersion()
It should be two integers separated by a dot, e.g. "1.1".
The default implementation returns "1.1".
Map<String,String> headers()
The returned Map is case insensitive for lookup. The caller should treat the Map as read-only.
A request must contains a "Host" header with a valid host[:port]
value.
Note that the value is case insensitive.
See also host()
.
The following headers should not be included in this Map:
"Content-Type"
).
Entity metadata should be expressed on the entity()
.
"Content-Length"
and "Transport-Encoding"
headers.
They are handled automatically by underlying libraries.
See Headers
for common header names.
See HeaderMap
for a suitable implementation.
See TokenParams
for a certain type of header values.
Note that each header contains a single value. Per spec, multiple headers with the same name is identical in semantics to a single combined header:
Foo: value1 | Foo: value2 | ====> | Foo: value1, value2, value3 Foo: value3 |
default String header(String name)
The default implementation returns headers().get(name)
.
default boolean acceptsGzip()
This method returns true if the "Accept-Encoding" header contains "gzip" with non-zero "q" value. See RFC2616.
Almost all browsers accept "gzip".
default Map<String,String> cookies()
The cookies are expressed in the "Cookie" request header;
cookies()
and header("Cookie")
must be consistent with each other.
Cookie names are case sensitive. The returned Map should be treated as read-only.
The default implementation parses the "Cookie" header according to RFC6265; ill-formed entries are ignored. If there are multiple cookies with the same name, the last one wins.
cookie(String)
default String cookie(String name)
The default implementation returns cookies().get(name)
.
HttpEntity entity()
There's no strict rules when a request must or must not contain an entity, though typically,
GET/HEAD/DELETE
request should not have an entity
POST/PUT
request should have an entity
The recipient of a request needs to prepare for the possibility
that request.entity()==null
(even for POST/PUT).
static HttpRequest current()
IllegalStateException
- if `Fiber.current()==null`static void setFiberLocal(HttpRequest request)
After this method is called on a fiber,
the HttpRequest.current()
call on the same fiber will return `request`.
The `request` arg can be null to clear the fiber-local request.
IllegalStateException
- if `Fiber.current()==null`FiberLocal
static HttpRequestImpl toGet(String uri)
`uri` can be absolute (preferred) or just path-query
.
If not absolute, the caller should set the host
afterwards.
Examples:
HttpRequest.toGet("http://example.com"); HttpRequest.toGet("/page1").host("localhost:8080");
FormData.toRequest()
static HttpRequestImpl toPost(String uri, String entityContentType, byte[] entityBody)
The request contains an entity with the specified Content-Type and body.
`uri` can be absolute (preferred) or just path-query
.
If not absolute, the caller should set the host
afterwards.
Example usage:
HttpRequest.toPost("http://localhost:8080/action", "application/x-www-form-urlencoded", "a=1&b=2".getBytes() ).header("Origin", "http://localhost:8080");
Note that to avoid the request being treated as CSRF by FormParser, the simplest way is to set the "Origin" header.
FormData.toRequest()