Class Request
- java.lang.Object
-
- sunlabs.brazil.server.Request
-
- Direct Known Subclasses:
TestRequest
public class Request extends java.lang.Object
Represents an HTTP transaction. A new instance is created by the server for each connection.Provides a set of accessor functions to fetch the individual fields of the HTTP request.
Utility methods that are generically useful for manipulating HTTP requests are included here as well. An instance of this class is passed to handlers. There will be exactly one request object per thead at any time.
The fields
headers
,query
, andurl
, and the methodgetQueryData()
are most often used to examine the content of the request. The fieldprops
contains information about the server, or up-stream handlers.The methods
sendResponse(String, String, int)
andsendError(int, String)
are commonly used to return content to the client. The methodsaddHeader(String)
andsetStatus(int)
can be used to modify the response headers and return code respectively before the response is sent.Many of the other methods are used internally, but can be useful to handlers that need finer control over the output that the above methods provide. Note that the order of the methods is important. For instance, the user cannot change the HTTP response headers (by calling the
addHeader
method or by modifying theresponseHeaders
field) after having already sent an HTTP response.A number of the fields in the
Request
object are public, by design. Many of the methods are convenience methods; the underlying data fields are meant to be accessed for more complicated operations, such as changing the URL or deleting HTTP response headers.
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static class
Request.HttpOutputStream
TheHttpOutputStream
provides the convenience methodwriteBytes
for writing the byte representation of a string, without bringing in the overhead and the deprecated warnings associated with ajava.io.DataOutputStream
.
-
Field Summary
Fields Modifier and Type Field Description java.lang.String
connectionHeader
The header "Connection" usually controls whether the client connection will be of type "Keep-Alive" or "close".MimeHeaders
headers
The HTTP request headers.protected boolean
headersSent
protected HttpInputStream
in
boolean
keepAlive
true
if the client requested a persistent connection,false
otherwise.static int
MAX_BLANKS
Maximum number of blank lines allowed between requests before aborting the connecion.java.lang.String
method
The HTTP request method, such as "GET", "POST", or "PUT".Request.HttpOutputStream
out
The HTTP response to the client is written to this stream.byte[]
postData
The uploaded content of this request, usually from a POST.PropertiesList
props
A set of properties local to this request.java.lang.String
protocol
The HTTP protocol specified in the request, either "HTTP/1.0" or "HTTP/1.1".java.lang.String
query
The query string specified after the URL, or""
if no query string was specified.protected int
requestsLeft
MimeHeaders
responseHeaders
The HTTP response headers.Server
server
The server that initiated this request.PropertiesList
serverProps
APropertiesList
object that wrapsserver.props
.java.lang.String
serverProtocol
This is the server's protocol.java.net.Socket
sock
Our connection to the client.long
startMillis
Time stamp for start of this request - set, but not used.protected int
statusCode
protected java.lang.String
statusPhrase
java.lang.String
url
The URL specified in the request, not including any "?" query string.int
version
Derived fromprotocol
, the version of the HTTP protocol used for this request.
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description void
addHeader(java.lang.String line)
Adds a response header to the HTTP response.void
addHeader(java.lang.String key, java.lang.String value)
Adds a response header to the HTTP response.boolean
addSharedProps(java.util.Dictionary d)
Adds the givenDictionary
to the set of properties that are searched byrequest.props.getProperty()
.java.util.Hashtable
getQueryData()
Retrieves the query data as a hashtable.java.util.Hashtable
getQueryData(java.util.Hashtable table)
Retrieves the query data as a hashtable.boolean
getRequest()
Reads an HTTP request from the socket.java.lang.String
getRequestHeader(java.lang.String key)
Returns the value that the given case-insensitive key maps to in the HTTP request headers.int
getReuseCount()
Return uses of this socketjava.net.Socket
getSocket()
The socket from which the HTTP request was received, and to where the HTTP response will be written.int
getStatus()
Return the status code.void
log(int level, java.lang.Object obj, java.lang.String message)
Logs a message by callingServer.log
.void
log(int level, java.lang.String message)
Logs a message by callingServer.log
.void
redirect(java.lang.String url, java.lang.String body)
Responds to an HTTP request with a redirection reply, telling the client that the requested url has moved.boolean
removeSharedProps(java.util.Dictionary d)
Removes aDictionary
added byaddSharedProps
.void
sendError(int code, java.lang.String clientMessage)
Sends a HTTP error response to the client.void
sendError(int code, java.lang.String clientMessage, java.lang.String logMessage)
Sends a HTTP error response to the client.void
sendHeaders(int code, java.lang.String type, int length)
Sends the HTTP status line and response headers to the client.void
sendResponse(byte[] body, java.lang.String type)
Sends an HTTP response to the client.void
sendResponse(java.io.InputStream in, int length, java.lang.String type, int code)
Sends the contents of the given input stream as the HTTP response.void
sendResponse(java.lang.String body)
Convenience method that sends an HTTP response to the client with a "Content-Type" of "text/html" and the default HTTP status code.void
sendResponse(java.lang.String body, java.lang.String type)
Convenience method that sends an HTTP response to the client with the default HTTP status code.void
sendResponse(java.lang.String body, java.lang.String type, int code)
Sends an HTTP response to the client.java.lang.String
serverUrl()
Returns the server's fully-qualified base URL.void
setStatus(int code)
Sets the status code of the HTTP response.protected void
setStatus(int code, java.lang.String message)
Set the HTTP status code and status phrase of this request.java.lang.String
toString()
Returns a string representation of thisRequest
.
-
-
-
Field Detail
-
MAX_BLANKS
public static final int MAX_BLANKS
Maximum number of blank lines allowed between requests before aborting the connecion. The spec allows 0, but some clients add one or more.- See Also:
- Constant Field Values
-
server
public Server server
The server that initiated this request. Only under rare circumstances should this be modified.
-
sock
public java.net.Socket sock
Our connection to the client. Only under rare circumstances would this need to be modified.
-
in
protected HttpInputStream in
-
props
public PropertiesList props
A set of properties local to this request. The property is wrapped in aPropertiesList
object and initially is the head of a linked list of properties that are searched in order. This is useful for handlers that wish to communicate via properties to down-stream handlers, such as modifying a server property for a particular request. Some handlers may even add entire new sets of properties onto the front ofrequest.props
to temporarily modify the properties seen by downstream handlers.
-
serverProps
public PropertiesList serverProps
APropertiesList
object that wrapsserver.props
. When thisrequest
is created, a newPropertiesList
wrappingserver.props
is created and added to a list consisting only ofprops
andserverProps
.
-
out
public Request.HttpOutputStream out
The HTTP response to the client is written to this stream. Normally the convenience methods, such assendResponse
, are used to send the response, but this field is available if a handler needs to generate the response specially.If the user chooses to write the response directly to this stream, the user is still encouraged to use the convenience methods, such as
sendHeaders
, to first send the HTTP response headers. TheFilterHandler
examines the HTTP response headers set by the convenience methods to determine whether to filter the output.Note that the HTTP response headers will not automatically be sent as a side effect if the user writes to this stream. The user would either need to call the convenience method
sendHeaders
or need to generate the HTTP response headers themselves.This variable is declared as a
Request.HttpOutputStream
, which provides the convenience methodwriteBytes
to write the byte representation of a string back to the client. If the user does not need this functionality, this variable may be accessed simply as a normalOutputStream
.
-
requestsLeft
protected int requestsLeft
-
method
public java.lang.String method
The HTTP request method, such as "GET", "POST", or "PUT".
-
url
public java.lang.String url
The URL specified in the request, not including any "?" query string.NOTE: Traditionally handlers modify this as needed. The request property "url.orig" is set to match the url at creation time, and should be considered "Read only", for those cases where the original url is required.
-
query
public java.lang.String query
The query string specified after the URL, or""
if no query string was specified.
-
protocol
public java.lang.String protocol
The HTTP protocol specified in the request, either "HTTP/1.0" or "HTTP/1.1".- See Also:
version
-
version
public int version
Derived fromprotocol
, the version of the HTTP protocol used for this request. Either10
for "HTTP/1.0" or11
for "HTTP/1.1".
-
headers
public MimeHeaders headers
The HTTP request headers. Keys and values in this table correspond the field names and values from each line in the HTTP header; field names are case-insensitive, but the case of the values is preserved. The order of entries in this table corresponds to the order in which the request headers were seen. Multiple header lines with the same key are stored as separate entries in the table.
-
postData
public byte[] postData
The uploaded content of this request, usually from a POST. Set tonull
if the request has no content.
-
keepAlive
public boolean keepAlive
true
if the client requested a persistent connection,false
otherwise. Derived from theprotocol
and theheaders
,When "Keep-Alive" is requested, the client can issue multiple, consecutive requests via a single socket connection. By default:
- HTTP/1.0 requests are not Keep-Alive, unless the "Connection: Keep-Alive" header was present.
- HTTP/1.1 requests are Keep-Alive, unless the "Connection: close" header was present.
true
tofalse
to forcefully close the connection to the client after sending the response. The user can change this value fromfalse
totrue
if the client is using a different header to request a persistent connection. SeeconnectionHeader
.Regardless of this value, if an error is detected while receiving or responding to an HTTP request, the connection will be closed.
-
connectionHeader
public java.lang.String connectionHeader
The header "Connection" usually controls whether the client connection will be of type "Keep-Alive" or "close". The same header is written back to the client in the response headers.The field
keepAlive
is set based on the value of the "Connection" header. However, not all clients use "Connection" to request that the connection be kept alive. For instance (although it does not appear in the HTTP/1.0 or HTTP/1.1 documentation) both Netscape and IE use the "Proxy-Connection" header when issuing requests via an HTTP proxy. If aHandler
is written to respond to HTTP proxy requests, it should setkeepAlive
depending on the value of the "Proxy-Connection" header, and setconnectionHeader
to "Proxy-Connection", since the convenience methods likesetResponse()
use these fields when constructing the response. The server does not handle the "Proxy-Connection" header by default, since trying to pre-anticipate all the exceptions to the specification is a "slippery slope".
-
serverProtocol
public java.lang.String serverProtocol
This is the server's protocol. It is normally null, but may be overriden to change the protocol on a per-request basis. If not set then server.protocol should be used instead.
-
statusCode
protected int statusCode
-
statusPhrase
protected java.lang.String statusPhrase
-
responseHeaders
public MimeHeaders responseHeaders
The HTTP response headers. Keys and values in this table correspond to the HTTP headers that will be written back to the client when the response is sent. The order of entries in this table corresponds to the order in which the HTTP headers will be sent. Multiple header lines with the same key will be stored as separate entries in the table.- See Also:
addHeader(String, String)
-
headersSent
protected boolean headersSent
-
startMillis
public long startMillis
Time stamp for start of this request - set, but not used.
-
-
Constructor Detail
-
Request
protected Request(Server server, java.net.Socket sock)
Create a new http request. Requests are created by the server for use by handlers.- Parameters:
server
- The server that owns this request.sock
- The socket of the incoming HTTP request.
-
Request
protected Request()
Needed by VelocityFilter.Vrequest. Should not be used to create aRequest
object.
-
-
Method Detail
-
toString
public java.lang.String toString()
Returns a string representation of thisRequest
. The string representation is the first line (the method line) of the HTTP request that thisRequest
is handling. Useful for debugging.- Overrides:
toString
in classjava.lang.Object
- Returns:
- The string representation of this
Request
.
-
getRequest
public boolean getRequest() throws java.io.IOException
Reads an HTTP request from the socket.- Returns:
true
if the request was successfully read and parsed,false
if the request was malformed.- Throws:
java.io.IOException
- if there was an IOException reading from the socket. See the socket documentation for a description of socket exceptions.
-
getSocket
public java.net.Socket getSocket()
The socket from which the HTTP request was received, and to where the HTTP response will be written. The user should not directly read from or write to this socket. The socket is provided other purposes, for example, imagine a handler that provided different content depending upon the IP address of the client.- Returns:
- The client socket that issued this HTTP request.
-
log
public void log(int level, java.lang.String message)
Logs a message by callingServer.log
. Typically a message is generated on the console or in a log file, if thelevel
is less than the current server log setting.- Parameters:
level
- The severity of the message.message
- The message that will be logged.- See Also:
Server.log(int, Object, String)
-
log
public void log(int level, java.lang.Object obj, java.lang.String message)
Logs a message by callingServer.log
. Typically a message is generated on the console or in a log file, if thelevel
is less than the current server log setting.- Parameters:
level
- The severity of the message.obj
- The object that the message relates to.message
- The message that will be logged.- See Also:
Server.log(int, Object, String)
-
getRequestHeader
public java.lang.String getRequestHeader(java.lang.String key)
Returns the value that the given case-insensitive key maps to in the HTTP request headers. In order to do fancier things like changing or deleting an existing request header, the user may directly access theheaders
field.- Parameters:
key
- The key to look for in the HTTP request headers. May not benull
.- Returns:
- The value to which the given key is mapped, or
null
if the key is not in the headers. - See Also:
headers
-
getQueryData
public java.util.Hashtable getQueryData(java.util.Hashtable table)
Retrieves the query data as a hashtable. This includes both the query information included as part of the url and any posted "application/x-www-form-urlencoded" data.- Parameters:
table
- An existing hashtable in which to put the query data as name/value pairs. May benull
, in which case a new hashtable is allocated.- Returns:
- The hashtable in which the query data was stored.
-
getQueryData
public java.util.Hashtable getQueryData()
Retrieves the query data as a hashtable. This includes both the query information included as part of the url and any posted "application/x-www-form-urlencoded" data.- Returns:
- The hashtable in which the query data was stored.
-
setStatus
public void setStatus(int code)
Sets the status code of the HTTP response. The default status code for a response is200
if this method is not called.An HTTP status phrase will be chosen based on the given status code. For example, the status code
404
will get the status phrase "Not Found".If this method is called, it must be called before
sendHeaders
is either directly or indirectly called. Otherwise, it will have no effect.- Parameters:
code
- The HTTP status code, such as200
or404
. If < 0, the HTTP status code will not be changed.- See Also:
sendHeaders(int, String, int)
-
setStatus
protected void setStatus(int code, java.lang.String message)
Set the HTTP status code and status phrase of this request. The given status will be sent to the client when the user directly or indirectly calls the methodsendHeaders
. The given status phrase replaces the default HTTP status phrase normally associated with the given status code.- Parameters:
code
- The HTTP status code, such as200
or404
.message
- The HTTP status phrase, such as"Okey dokey"
or"I don't see it"
.- See Also:
sendHeaders(int, String, int)
-
getStatus
public int getStatus()
Return the status code.
-
getReuseCount
public int getReuseCount()
Return uses of this socket
-
addHeader
public void addHeader(java.lang.String key, java.lang.String value)
Adds a response header to the HTTP response. In order to do fancier things like appending a value to an existing response header, the user may directly access theresponseHeaders
field.If this method is called, it must be called before
sendHeaders
is either directly or indirectly called. Otherwise, it will have no effect.- Parameters:
key
- The header name.value
- The value for the request header.- See Also:
sendHeaders(int, String, int)
,responseHeaders
-
addHeader
public void addHeader(java.lang.String line)
Adds a response header to the HTTP response. In order to do fancier things like appending a value to an existing response header, the user may directly access theresponseHeaders
field.If this method is called, it must be called before
sendHeaders
is either directly or indirectly called. Otherwise, it will have no effect.- Parameters:
line
- The HTTP response header, of the form "key
:value
".- See Also:
sendHeaders(int, String, int)
,responseHeaders
-
sendResponse
public void sendResponse(byte[] body, java.lang.String type) throws java.io.IOException
Sends an HTTP response to the client.This method first calls
sendHeaders
to send the HTTP response headers, then sends the given byte array as the HTTP response body. If the request method is HEAD, or the result code is "204", the body is not sent.The "Content-Length" will be set to the length of the given byte array. The "Content-Type" will be set to the given MIME type.
- Parameters:
body
- The array of bytes to send as the HTTP response body. May not benull
.type
- The MIME type of the response, such as "text/html". May benull
to use the existing "Content-Type" response header (if any).- Throws:
java.io.IOException
- if there was an I/O error while sending the response to the client.- See Also:
sendHeaders(int, String, int)
-
sendResponse
public void sendResponse(java.lang.String body, java.lang.String type, int code) throws java.io.IOException
Sends an HTTP response to the client.This method first calls
sendHeaders
to send the HTTP response headers. It then writes out the given string to the client as a sequence of bytes. Each character in the string is written out by discarding its high eight bits.The "Content-Length" will be set to the length of the string. The "Content-Type" will be set to the given MIME type.
Note: to use a different character encoding, use
sendResponse(body.getBytes(encoding)...)
instead.- Parameters:
body
- The string to send as the HTTP response body. May not benull
. If the request method is HEAD, the body is not sent.type
- The MIME type of the response, such as "text/html". May benull
to preserve the existing "Content-Type" response header (if any).code
- The HTTP status code for the response, such as200
. May be < 0 to preserve the existing status code.- Throws:
java.io.IOException
- if there was an I/O error while sending the response to the client.- See Also:
sendHeaders(int, String, int)
-
sendResponse
public void sendResponse(java.lang.String body) throws java.io.IOException
Convenience method that sends an HTTP response to the client with a "Content-Type" of "text/html" and the default HTTP status code.- Parameters:
body
- The string to send as the HTTP response body.- Throws:
java.io.IOException
- See Also:
sendResponse(String, String, int)
-
sendResponse
public void sendResponse(java.lang.String body, java.lang.String type) throws java.io.IOException
Convenience method that sends an HTTP response to the client with the default HTTP status code.- Parameters:
body
- The string to send as the HTTP response body. If the request method is HEAD, only the headers are sent to the client.type
- The MIME type of the response.- Throws:
java.io.IOException
- See Also:
sendResponse(String, String, int)
-
sendResponse
public void sendResponse(java.io.InputStream in, int length, java.lang.String type, int code) throws java.io.IOException
Sends the contents of the given input stream as the HTTP response.This method first calls
sendHeaders
to send the HTTP response headers. It then transfers a total oflength
bytes of data from the given input stream to the client as the HTTP response body.This method takes care of setting the "Content-Length" header if the actual content length is known, or the "Transfer-Encoding" header if the content length is not known (for HTTP/1.1 clients only).
This method may set the
keepAlive
tofalse
before returning, if fewer thanlength
bytes could be read. If the request method is HEAD, only the headers are sent.- Parameters:
in
- The input stream to read from.length
- The content length. The number of bytes to send to the client. May be < 0, in which case this method will read until reaching the end of the input stream.type
- The MIME type of the response, such as "text/html". May benull
to preserve the existing "Content-Type" response header (if any).code
- The HTTP status code for the response, such as200
. May be < 0 to preserve the existing status code.- Throws:
java.io.IOException
- if there was an I/O error while sending the response to the client.
-
sendError
public void sendError(int code, java.lang.String clientMessage)
Sends a HTTP error response to the client.- Parameters:
code
- The HTTP status code.clientMessage
- A short message to be included in the error response and logged to the server.
-
sendError
public void sendError(int code, java.lang.String clientMessage, java.lang.String logMessage)
Sends a HTTP error response to the client.- Parameters:
code
- The HTTP status code.clientMessage
- A short message to be included in the error response.logMessage
- A short message to be logged to the server. This message is not sent to the client.
-
sendHeaders
public void sendHeaders(int code, java.lang.String type, int length) throws java.io.IOException
Sends the HTTP status line and response headers to the client. This method is automatically invoked bysendResponse
, but can be manually invoked if the user needs direct access to the client's output stream. If this method is not called, then the HTTP status and response headers will not automatically be sent to the client; the user would be responsible for forming the entire HTTP response.The user may call the
addHeader
method or modify theresponseHeaders
field before calling this method. This method then adds a number of HTTP headers, as follows:- "Date" - the current time, if this header is not already present.
- "Server" - the server's name (from
server.name
), if this header is not already present. - "Connection" - "Keep-Alive" or "close", depending upon the
keepAlive
field. - "Content-Length" - set to the given
length
. - "Content-Type" - set to the given
type
.
The string used for "Connection" header actually comes from the
connectionHeader
field.- Parameters:
code
- The HTTP status code for the response, such as200
. May be < 0 to preserve the existing status code.type
- The MIME type of the response, such as "text/html". May benull
to preserve the existing "Content-Type" response header (if any).length
- The length of the response body. May be < 0 if the length is unknown and/or to preserve the existing "Content-Length" response header (if any).- Throws:
java.io.IOException
- if there was an I/O error while sending the headers to the client.- See Also:
setStatus(int)
,addHeader(String, String)
,sendResponse(String, String, int)
,connectionHeader
-
redirect
public void redirect(java.lang.String url, java.lang.String body) throws java.io.IOException
Responds to an HTTP request with a redirection reply, telling the client that the requested url has moved. Generally, this is used if the client did not put a '/' on the end of a directory.- Parameters:
url
- The URL the client should have requested. This URL may be fully-qualified (in the form "http://....") or host-relative (in the form "/...").body
- The body of the redirect response, ornull
to send a hardcoded message.- Throws:
java.io.IOException
-
serverUrl
public java.lang.String serverUrl()
Returns the server's fully-qualified base URL. This is "http://" followed by the server's hostname and port.If the HTTP request header "Host" is present, it specifies the hostname and port that will be used instead of the server's internal name for itself. Due bugs in certain browsers, when using the server's internal name, the port number will be elided if it is
80
.- Returns:
- The string representation of the server's URL.
-
addSharedProps
public boolean addSharedProps(java.util.Dictionary d)
Adds the givenDictionary
to the set of properties that are searched byrequest.props.getProperty()
. This method is used to optimize the case when the caller has an existingDictionary
object that should be added to the search chain.Assume the caller is constructing a new
Properties
object and wants to chain it onto the front ofrequest.props
. The following code is appropriate:
However,/* Push a temporary Dictionary onto request.props. */ PropertiesList old = request.props; (new PropertiesList()).addBefore(request.props); request.props = request.props.getPrior(); request.props.put("foo", "bar"); request.props.put("baz", "garply"); /* Do something that accesses new properties. */ . . . /* Restore old Dictionary when done. */ request.props.remove(); request.props = old;
addSharedProps
may be called when the caller has an existing set ofProperties
and is faced with copying its contents intorequest.props
and/or trying to share the existingProperties
object among multiple threads concurrently.
is more efficient and esthetically pleasing than:/* Some properties created at startup. */ static Properties P = new Properties(); . . . /* Share properties at runtime. */ request.addSharedProps(P);
The givenforeach key in P.keys() { request.props.put(key, P.get(key)); }
Dictionary
object is added to theProperties.getProperty()
search chain before serverProps; it will be searched after therequest.props
and beforeserverProps
. MultipleDictionary
objects can be added and they will be searched in the order given. The sameDictionary
object can be added multiple times safely. However, the search chain for the givenDictionary
must not refer back torequest.props
itself or a circular chain will be created causing an infinite loop:
Subsequent calls torequest.addSharedProps(request.props); // Bad request.addSharedProps(request.props.getWrapped()); // Good Properties d1 = new Properties(request.props); request.addSharedProps(d1); // Bad Hashtable d2 = new Hashtable(); Properties d3 = new Properties(); request.addSharedProps(d2); // Good request.addSharedProps(d3); // Good
request.props.getProperty()
may fetch properties from an addedDictionary
, butrequest.put()
will not modify those dictionaries.- Parameters:
d
- ADictionary
ofString
key/value pairs that will be added to the chain searched whenrequest.props.getProperty()
is called. The dictionaryd
is "live", meaning that external changes to the contents ofd
will be seen on subsequent calls torequest.props.getProperty()
.- Returns:
false
if the dictionary had already been added by a previous call to this method,true
otherwise.
-
removeSharedProps
public boolean removeSharedProps(java.util.Dictionary d)
Removes aDictionary
added byaddSharedProps
.Dictionary
objects may be removed in any order.Dictionary
objects do not need to be removed; they will automatically get cleaned up at the end of the request.- Parameters:
d
- TheDictionary
object to remove from therequest.props.getProperty()
search chain.- Returns:
true
if theDictionary
was found and removed,false
if theDictionary
was not found (it had already been removed or had never been added).
-
-