Request
that is used by
* BrazilServlet
to map servlet style requests and responses
* to and from Brazil style requests.
*
* @author Steve Drach true
if the request was successfully read and
* parsed, false
if the request was malformed.
*
* @throws IOException
* if there was an IOException reading from the socket. See
* the socket documentation for a description of socket
* exceptions.
*/
public boolean getRequest() throws IOException
{
if (server.props.get("debugProps") != null) {
PropertiesList.debug = true;
if (props != null) {
props.dump(false, "at beginning of getRequest");
}
}
/*
* Reset state.
*/
requestsLeft--;
connectionHeader = "Connection";
/* I don't think we need to do this
while ((props = server.props.getPrior()) != null) {
props.remove();
}
*/
String origUrl = req.getRequestURI().trim();
int strip = req.getContextPath().length();
url = origUrl.substring(strip);
method = req.getMethod().trim();
query = req.getQueryString();
if (query != null)
query = query.trim();
else
query = "";
protocol = req.getProtocol().trim();
headers.clear();
postData = null;
statusCode = 200;
statusPhrase = "OK";
responseHeaders.clear();
startMillis = System.currentTimeMillis();
out.bytesWritten=0;
log(Server.LOG_LOG, "Request " + requestsLeft + " " + toString());
if (protocol.equals("HTTP/1.0")) {
version = 10;
} else if (protocol.equals("HTTP/1.1")) {
version = 11;
// Should we turn off chunked transfer encoding?
} else {
sendError(505, toString(), null);
return false;
}
Enumeration names = req.getHeaderNames();
while (names.hasMoreElements()) {
String name = (String)names.nextElement();
headers.put(name, req.getHeader(name));
}
/*
* Remember POST data. "Transfer-Encoding: chunked" is not handled
* yet.
*/
String str;
str = getRequestHeader("Content-Length");
if (str != null) {
try {
postData = new byte[Integer.parseInt(str)];
} catch (Exception e) {
sendError(411, str, null);
return false;
} catch (OutOfMemoryError e) {
sendError(411, str, null);
return false;
}
in.readFully(postData);
}
str = getRequestHeader(connectionHeader);
if ("Keep-Alive".equalsIgnoreCase(str)) {
keepAlive = true;
} else if ("close".equalsIgnoreCase(str)) {
keepAlive = false;
} else if (version > 10) {
keepAlive = true;
} else {
keepAlive = false;
}
/*
* Delay initialization until we know we need these things
*/
serverProps = new PropertiesList(server.props);
props = new PropertiesList();
props.addBefore(serverProps);
props.put("url.servlet", origUrl);
props.put("url.orig", url);
return true;
}
/**
*
* Sets response code in the servlet response object.
*/
public void setStatus(int code)
{
if (code < 0)
return;
super.setStatus(code);
res.setStatus(code);
}
/**
*
* 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 to bugs in certain browsers, when
* using the server's internal name, the port number will be elided
* if it is 80.
*
* @return The string representation of the server's URL.
*/
public String serverUrl()
{
String host = headers.get("Host");
if (host == null) {
host = server.hostName;
}
int port = req.getServerPort();
if ((host.lastIndexOf(":") < 0) && (port != 80)) {
host += ":" + port;
}
return server.protocol + "://" + host;
}
/**
*
* An HttpOutputStream
that is used by the Brazil Servlet
* adaptor to add the web application
* context path to the front of all response URI's so subsequent requests
* will be mapped to the BrazilServlet
's context. See comments
* in BrazilServlet
that describe the assumptions regarding
* the context path.
*
* @author Steve Drach