Merge pull request #422 from Massive-Dynamics/http-doc

Even more documentation changes (mainly) - HTTP
This commit is contained in:
Norman Maurer 2012-06-29 02:55:20 -07:00
commit cd95dc5924
5 changed files with 265 additions and 113 deletions

View File

@ -18,134 +18,191 @@ package io.netty.handler.codec.http;
import java.util.Set;
/**
* An HTTP <a href="http://en.wikipedia.org/wiki/HTTP_cookie">Cookie</a>.
* An interface defining an
* <a href="http://en.wikipedia.org/wiki/HTTP_cookie">HTTP cookie</a>.
*/
public interface Cookie extends Comparable<Cookie> {
/**
* Returns the name of this cookie.
* Returns the name of this {@link Cookie}.
*
* @return The name of this {@link Cookie}
*/
String getName();
/**
* Returns the value of this cookie.
* Returns the value of this {@link Cookie}.
*
* @return The value of this {@link Cookie}
*/
String getValue();
/**
* Sets the value of this cookie.
* Sets the value of this {@link Cookie}.
*
* @param value The value to set
*/
void setValue(String value);
/**
* Returns the domain of this cookie.
* Returns the domain of this {@link Cookie}.
*
* @return The domain of this {@link Cookie}
*/
String getDomain();
/**
* Sets the domain of this cookie.
* Sets the domain of this {@link Cookie}.
*
* @param domain The domain to use
*/
void setDomain(String domain);
/**
* Returns the path of this cookie.
* Returns the path of this {@link Cookie}.
*
* @return The {@link Cookie}'s path
*/
String getPath();
/**
* Sets the path of this cookie.
* Sets the path of this {@link Cookie}.
*
* @param path The path to use for this {@link Cookie}
*/
void setPath(String path);
/**
* Returns the comment of this cookie.
* Returns the comment of this {@link Cookie}.
*
* @return The comment of this {@link Cookie}
*/
String getComment();
/**
* Sets the comment of this cookie.
* Sets the comment of this {@link Cookie}.
*
* @param comment The comment to use
*/
void setComment(String comment);
/**
* Returns the max age of this cookie in seconds.
* Returns the maximum age of this {@link Cookie} in seconds.
*
* @return The maximum age of this {@link Cookie}
*/
long getMaxAge();
/**
* Sets the max age of this cookie in seconds. If {@code 0} is specified,
* this cookie will be removed by browser because it will be expired
* immediately. If {@code -1} is specified, this cookie will be removed
* when a user terminates browser.
* Sets the maximum age of this {@link Cookie} in seconds.
* If an age of {@code 0} is specified, this {@link Cookie} will be
* automatically removed by browser because it will expire immediately.
* If {@code -1} is specified, this {@link Cookie} will be removed when the
* browser is closed.
*
* @param maxAge The maximum age of this {@link Cookie} in seconds
*/
void setMaxAge(long maxAge);
/**
* Returns the version of this cookie.
* Returns the version of this {@link Cookie}.
*
* @return The version of this {@link Cookie}
*/
int getVersion();
/**
* Sets the version of this cookie.
* Sets the version of this {@link Cookie}.
*
* @param version The new version to use
*/
void setVersion(int version);
/**
* Returns the secure flag of this cookie.
* Checks to see if this {@link Cookie} is secure
*
* @return True if this {@link Cookie} is secure, otherwise false
*/
boolean isSecure();
/**
* Sets the secure flag of this cookie.
* Sets the security status of this {@link Cookie}
*
* @param secure True if this {@link Cookie} is to be secure, otherwise false
*/
void setSecure(boolean secure);
/**
* Returns if this cookie cannot be accessed through client side script.
* This flag works only if the browser supports it. For more information,
* see <a href="http://www.owasp.org/index.php/HTTPOnly">here</a>.
* Checks to see if this {@link Cookie} can only be accessed via HTTP.
* If this returns true, the {@link Cookie} cannot be accessed through
* client side script - But only if the browser supports it.
* For more information, please look <a href="http://www.owasp.org/index.php/HTTPOnly">here</a>
*
* @return True if this {@link Cookie} is HTTP-only or false if it isn't
*/
boolean isHttpOnly();
/**
* Sets if this cookie cannot be accessed through client side script.
* This flag works only if the browser supports it. For more information,
* see <a href="http://www.owasp.org/index.php/HTTPOnly">here</a>.
* Determines if this {@link Cookie} is HTTP only.
* If set to true, this {@link Cookie} cannot be accessed by a client
* side script. However, this works only if the browser supports it.
* For for information, please look
* <a href="http://www.owasp.org/index.php/HTTPOnly">here</a>.
*
* @param httpOnly True if the {@link Cookie} is HTTP only, otherwise false.
*/
void setHttpOnly(boolean httpOnly);
/**
* Returns the comment URL of this cookie.
* Returns the comment URL of this {@link Cookie}.
*
* @return The comment URL of this {@link Cookie}
*/
String getCommentUrl();
/**
* Sets the comment URL of this cookie.
* Sets the comment URL of this {@link Cookie}.
*
* @param commentUrl The comment URL to use
*/
void setCommentUrl(String commentUrl);
/**
* Returns the discard flag of this cookie.
* Checks to see if this {@link Cookie} is to be discarded by the browser
* at the end of the current session.
*
* @return True if this {@link Cookie} is to be discarded, otherwise false
*/
boolean isDiscard();
/**
* Sets the discard flag of this cookie.
* Sets the discard flag of this {@link Cookie}.
* If set to true, this {@link Cookie} will be discarded by the browser
* at the end of the current session
*
* @param discard True if the {@link Cookie} is to be discarded
*/
void setDiscard(boolean discard);
/**
* Returns the ports of this cookie.
* Returns the ports that this {@link Cookie} can be accessed on.
*
* @return The {@link Set} of ports that this {@link Cookie} can use
*/
Set<Integer> getPorts();
/**
* Sets the ports of this cookie.
* Sets the ports that this {@link Cookie} can be accessed on.
*
* @param ports The ports that this {@link Cookie} can be accessed on
*/
void setPorts(int... ports);
/**
* Sets the ports of this cookie.
* Sets the ports that this {@link Cookie} can be accessed on.
*
* @param ports The {@link Iterable} collection of ports that this
* {@link Cookie} can be accessed on.
*/
void setPorts(Iterable<Integer> ports);
}

View File

@ -17,57 +17,84 @@ package io.netty.handler.codec.http;
import java.util.List;
/**
* A utility class mainly for use with HTTP codec classes
*/
final class HttpCodecUtil {
static void validateHeaderName(String name) {
if (name == null) {
throw new NullPointerException("name");
/**
* Validates the name of a header
*
* @param headerName The header name being validated
*/
static void validateHeaderName(String headerName) {
//Check to see if the name is null
if (headerName == null) {
throw new NullPointerException("Header names cannot be null");
}
for (int i = 0; i < name.length(); i ++) {
char c = name.charAt(i);
if (c > 127) {
//Go through each of the characters in the name
for (int index = 0; index < headerName.length(); index ++) {
//Actually get the character
char character = headerName.charAt(index);
//Check to see if the character is not an ASCII character
if (character > 127) {
throw new IllegalArgumentException(
"name contains non-ascii character: " + name);
"Header name cannot contain non-ASCII characters: " + headerName);
}
// Check prohibited characters.
switch (c) {
//Check for prohibited characters.
switch (character) {
case '\t': case '\n': case 0x0b: case '\f': case '\r':
case ' ': case ',': case ':': case ';': case '=':
throw new IllegalArgumentException(
"name contains one of the following prohibited characters: " +
"=,;: \\t\\r\\n\\v\\f: " + name);
"Header name cannot contain the following prohibited characters: " +
"=,;: \\t\\r\\n\\v\\f: " + headerName);
}
}
}
static void validateHeaderValue(String value) {
if (value == null) {
throw new NullPointerException("value");
/**
* Validates the specified header value
*
* @param value The value being validated
*/
static void validateHeaderValue(String headerValue) {
//Check to see if the value is null
if (headerValue == null) {
throw new NullPointerException("Header values cannot be null");
}
// 0 - the previous character was neither CR nor LF
// 1 - the previous character was CR
// 2 - the previous character was LF
/*
* Set up the state of the validation
*
* States are as follows:
*
* 0: Previous character was neither CR nor LF
* 1: The previous character was CR
* 2: The previous character was LF
*/
int state = 0;
for (int i = 0; i < value.length(); i ++) {
char c = value.charAt(i);
//Start looping through each of the character
// Check the absolutely prohibited characters.
switch (c) {
for (int index = 0; index < headerValue.length(); index ++) {
char character = headerValue.charAt(index);
//Check the absolutely prohibited characters.
switch (character) {
case 0x0b: // Vertical tab
throw new IllegalArgumentException(
"value contains a prohibited character '\\v': " + value);
"Header value contains a prohibited character '\\v': " + headerValue);
case '\f':
throw new IllegalArgumentException(
"value contains a prohibited character '\\f': " + value);
"Header value contains a prohibited character '\\f': " + headerValue);
}
// Check the CRLF (HT | SP) pattern
switch (state) {
case 0:
switch (c) {
switch (character) {
case '\r':
state = 1;
break;
@ -77,47 +104,56 @@ final class HttpCodecUtil {
}
break;
case 1:
switch (c) {
switch (character) {
case '\n':
state = 2;
break;
default:
throw new IllegalArgumentException(
"Only '\\n' is allowed after '\\r': " + value);
"Only '\\n' is allowed after '\\r': " + headerValue);
}
break;
case 2:
switch (c) {
switch (character) {
case '\t': case ' ':
state = 0;
break;
default:
throw new IllegalArgumentException(
"Only ' ' and '\\t' are allowed after '\\n': " + value);
"Only ' ' and '\\t' are allowed after '\\n': " + headerValue);
}
}
}
if (state != 0) {
throw new IllegalArgumentException(
"value must not end with '\\r' or '\\n':" + value);
"Header value must not end with '\\r' or '\\n':" + headerValue);
}
}
static boolean isTransferEncodingChunked(HttpMessage m) {
List<String> chunked = m.getHeaders(HttpHeaders.Names.TRANSFER_ENCODING);
if (chunked.isEmpty()) {
/**
* Checks to see if the transfer encoding in a specified {@link HttpMessage} is chunked
*
* @param message The message to check
* @return True if transfer encoding is chunked, otherwise false
*/
static boolean isTransferEncodingChunked(HttpMessage message) {
List<String> transferEncodingHeaders = message.getHeaders(HttpHeaders.Names.TRANSFER_ENCODING);
if (transferEncodingHeaders.isEmpty()) {
return false;
}
for (String v: chunked) {
if (v.equalsIgnoreCase(HttpHeaders.Values.CHUNKED)) {
for (String value: transferEncodingHeaders) {
if (value.equalsIgnoreCase(HttpHeaders.Values.CHUNKED)) {
return true;
}
}
return false;
}
/**
* A constructor to ensure that instances of this class are never made
*/
private HttpCodecUtil() {
}
}

View File

@ -25,8 +25,10 @@ import java.util.Map;
import java.util.Set;
/**
* An HTTP message which provides common properties for {@link HttpRequest} and
* {@link HttpResponse}.
* An interface that defines a HTTP message, providing common properties for
* {@link HttpRequest} and {@link HttpResponse}.
* @see HttpResponse
* @see HttpRequest
* @see HttpHeaders
*
* @apiviz.landmark
@ -35,86 +37,111 @@ import java.util.Set;
public interface HttpMessage {
/**
* Returns the header value with the specified header name. If there are
* more than one header value for the specified header name, the first
* value is returned.
* Returns the value of a header with the specified name. If there are
* more than one values for the specified name, the first value is returned.
*
* @return the header value or {@code null} if there is no such header
* @param name The name of the header to search
* @return The first header value or {@code null} if there is no such header
*/
String getHeader(String name);
/**
* Returns the header values with the specified header name.
* Returns the values of headers with the specified name
*
* @return the {@link List} of header values. An empty list if there is no
* such header.
* @param name The name of the headers to search
* @return A {@link List} of header values which will be empty if no values
* are found
*/
List<String> getHeaders(String name);
/**
* Returns the all header names and values that this message contains.
* Returns the all headers that this message contains.
*
* @return the {@link List} of the header name-value pairs. An empty list
* if there is no header in this message.
* @return A {@link List} of the header name-value entries, which will be
* empty if no pairs are found
*/
List<Map.Entry<String, String>> getHeaders();
/**
* Returns {@code true} if and only if there is a header with the specified
* header name.
* Checks to see if there is a header with the specified name
*
* @param name The name of the header to search for
* @return True if at least one header is found
*/
boolean containsHeader(String name);
/**
* Returns the {@link Set} of all header names that this message contains.
* Gets a {@link Set} of all header names that this message contains
*
* @return A {@link Set} of all header names
*/
Set<String> getHeaderNames();
/**
* Returns the protocol version of this message.
* Returns the protocol version of this {@link HttpMessage}
*
* @returns The protocol version
*/
HttpVersion getProtocolVersion();
/**
* Sets the protocol version of this message.
* Sets the protocol version of this {@link HttpMessage}
*
* @param version The version to set
*/
void setProtocolVersion(HttpVersion version);
/**
* Returns the content of this message. If there is no content or
* {@link #isChunked()} returns {@code true}, an
* {@link Unpooled#EMPTY_BUFFER} is returned.
* Returns the content of this {@link HttpMessage}.
*
* If there is no content or {@link #isChunked()} returns {@code true},
* an {@link Unpooled#EMPTY_BUFFER} is returned.
*
* @return A {@link ByteBuf} containing this {@link HttpMessage}'s content
*/
ByteBuf getContent();
/**
* Sets the content of this message. If {@code null} is specified,
* the content of this message will be set to {@link Unpooled#EMPTY_BUFFER}.
* Sets the content of this {@link HttpMessage}.
*
* If {@code null} is specified, the content of this message
* will be set to {@link Unpooled#EMPTY_BUFFER}
*
* @param content The {@link ByteBuf} containing the content to use
*/
void setContent(ByteBuf content);
/**
* Adds a new header with the specified name and value.
* If the specified value is not a {@link String}, it is converted into a
* {@link String} by {@link Object#toString()}, except for {@link Date}
* and {@link Calendar} which are formatted to the date format defined in
* <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1">RFC2616</a>.
*
* If the specified value is not a {@link String}, it is converted
* into a {@link String} by {@link Object#toString()}, except in the cases
* of {@link Date} and {@link Calendar}, which are formatted to the date
* format defined in <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1">RFC2616</a>.
*
* @param name The name of the header being added
* @param value The value of the header being added
*/
void addHeader(String name, Object value);
/**
* Sets a new header with the specified name and value. If there is an
* existing header with the same name, the existing header is removed.
* Sets a header with the specified name and value.
*
* If there is an existing header with the same name, it is removed.
* If the specified value is not a {@link String}, it is converted into a
* {@link String} by {@link Object#toString()}, except for {@link Date}
* and {@link Calendar} which are formatted to the date format defined in
* and {@link Calendar}, which are formatted to the date format defined in
* <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1">RFC2616</a>.
*
* @param name The name of the header being set
* @param value The value of the header being set
*/
void setHeader(String name, Object value);
/**
* Sets a new header with the specified name and values. If there is an
* existing header with the same name, the existing header is removed.
* Sets a header with the specified name and values.
*
* If there is an existing header with the same name, it is removed.
* This method can be represented approximately as the following code:
* <pre>
* m.removeHeader(name);
@ -125,42 +152,62 @@ public interface HttpMessage {
* m.addHeader(name, v);
* }
* </pre>
*
* @param name The name of the headers being set
* @param values The values of the headers being set
*/
void setHeader(String name, Iterable<?> values);
/**
* Removes the header with the specified name.
*
* @param name The name of the header to remove
*/
void removeHeader(String name);
/**
* Removes all headers from this message.
* Removes all headers from this {@link HttpMessage}.
*/
void clearHeaders();
/**
* Returns {@code true} if and only if this message does not have any
* content but the {@link HttpChunk}s, which is generated by
* {@link HttpMessageDecoder} consecutively, contain the actual content.
* Checks to see if this {@link HttpMessage} is broken into multiple "chunks"
*
* If this returns true, it means that this {@link HttpMessage}
* actually has no content - The {@link HttpChunk}s (which are generated
* by the {@link HttpMessageDecoder} consecutively) contain the actual content.
* <p>
* Please note that this method will keep returning {@code true} if the
* {@code "Transfer-Encoding"} of this message is {@code "chunked"}, even if
* you attempt to override this property by calling {@link #setChunked(boolean)}
* with {@code false}.
* </p>
*
* @return True if this message is chunked, otherwise false
*/
boolean isChunked();
/**
* Sets if this message does not have any content but the
* {@link HttpChunk}s, which is generated by {@link HttpMessageDecoder}
* consecutively, contain the actual content.
* Sets the boolean defining if this {@link HttpMessage} is chunked.
*
* <p>
* If this method is called with {@code true}, the content of this message
* becomes {@link Unpooled#EMPTY_BUFFER}.
* If this is set to true, it means that this initial {@link HttpMessage}
* does not contain any content - The content is contained by multiple
* {@link HttpChunk}s, which are generated by the {@link HttpMessageDecoder}
* consecutively.
*
* Because of this, the content of this {@link HttpMessage} becomes
* {@link Unpooled#EMPTY_BUFFER}
* </p>
*
* <p>
* Even if this method is called with {@code false}, {@link #isChunked()}
* will keep returning {@code true} if the {@code "Transfer-Encoding"} of
* this message is {@code "chunked"}.
* </p>
*
* @param chunked True if this message is to be delivered in chunks,
* otherwise false.
*/
void setChunked(boolean chunked);
}

View File

@ -34,22 +34,30 @@ package io.netty.handler.codec.http;
public interface HttpRequest extends HttpMessage {
/**
* Returns the method of this request.
* Returns the {@link HttpMethod} of this {@link HttpRequest}.
*
* @return The {@link HttpMethod} of this {@link HttpRequest}
*/
HttpMethod getMethod();
/**
* Sets the method of this request.
* Sets the {@link HttpMethod} of this {@link HttpRequest}.
*
* @param The {@link HttpMethod} to set
*/
void setMethod(HttpMethod method);
/**
* Returns the URI (or path) of this request.
* Returns the requested URI (or alternatively, path)
*
* @return The URI being requested
*/
String getUri();
/**
* Sets the URI (or path) of this request.
* Sets the URI (or alternatively, path) being requested.
*
* @param uri The URI being requested
*/
void setUri(String uri);
}

View File

@ -19,7 +19,7 @@ package io.netty.handler.codec.http;
/**
* An HTTP response.
*
* <h3>Accessing Cookie</h3>
* <h3>Accessing Cookies</h3>
* <p>
* Unlike the Servlet API, {@link Cookie} support is provided separately via {@link CookieDecoder},
* {@link ClientCookieEncoder}, and {@link ServerCookieEncoder}.
@ -32,12 +32,16 @@ package io.netty.handler.codec.http;
public interface HttpResponse extends HttpMessage {
/**
* Returns the status of this response.
* Returns the status of this {@link HttpResponse}.
*
* @return The {@link HttpResponseStatus} of this {@link HttpResponse}
*/
HttpResponseStatus getStatus();
/**
* Sets the status of this response.
* Sets the status of this {@link HttpResponse}
*
* @param status The {@link HttpResponseStatus} to use
*/
void setStatus(HttpResponseStatus status);
}