added a maximum request size to CHTTPProtocol so we can bail
on clients that cause us to use too much memory. also put methods in CHTTPRequest to get/set headers and changed the data structure used to store them. fixed a couple of other miscellaneous bugs in CHTTPProtocol.cpp.
This commit is contained in:
parent
fa4d24216f
commit
1da9be88c9
|
@ -56,15 +56,86 @@ bool CHTTPUtil::CaselessCmp::operator()(
|
||||||
return less(a, b);
|
return less(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// CHTTPRequest
|
||||||
|
//
|
||||||
|
|
||||||
|
CHTTPRequest::CHTTPRequest()
|
||||||
|
{
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
CHTTPRequest::~CHTTPRequest()
|
||||||
|
{
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
void CHTTPRequest::insertHeader(
|
||||||
|
const CString& name, const CString& value)
|
||||||
|
{
|
||||||
|
CHeaderMap::iterator index = m_headerByName.find(name);
|
||||||
|
if (index != m_headerByName.end()) {
|
||||||
|
index->second->second = value;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
CHeaderList::iterator pos = m_headers.insert(
|
||||||
|
m_headers.end(), std::make_pair(name, value));
|
||||||
|
m_headerByName.insert(std::make_pair(name, pos));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CHTTPRequest::appendHeader(
|
||||||
|
const CString& name, const CString& value)
|
||||||
|
{
|
||||||
|
CHeaderMap::iterator index = m_headerByName.find(name);
|
||||||
|
if (index != m_headerByName.end()) {
|
||||||
|
index->second->second += ",";
|
||||||
|
index->second->second += value;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
CHeaderList::iterator pos = m_headers.insert(
|
||||||
|
m_headers.end(), std::make_pair(name, value));
|
||||||
|
m_headerByName.insert(std::make_pair(name, pos));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CHTTPRequest::eraseHeader(const CString& name)
|
||||||
|
{
|
||||||
|
CHeaderMap::iterator index = m_headerByName.find(name);
|
||||||
|
if (index != m_headerByName.end()) {
|
||||||
|
m_headers.erase(index->second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CHTTPRequest::isHeader(const CString& name) const
|
||||||
|
{
|
||||||
|
return (m_headerByName.find(name) != m_headerByName.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
CString CHTTPRequest::getHeader(const CString& name) const
|
||||||
|
{
|
||||||
|
CHeaderMap::const_iterator index = m_headerByName.find(name);
|
||||||
|
if (index != m_headerByName.end()) {
|
||||||
|
return index->second->second;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return CString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// CHTTPProtocol
|
// CHTTPProtocol
|
||||||
//
|
//
|
||||||
|
|
||||||
CHTTPRequest* CHTTPProtocol::readRequest(IInputStream* stream)
|
CHTTPRequest* CHTTPProtocol::readRequest(
|
||||||
|
IInputStream* stream, UInt32 maxSize)
|
||||||
{
|
{
|
||||||
CString scratch;
|
CString scratch;
|
||||||
|
|
||||||
|
// note if we should limit the request size
|
||||||
|
const bool checkSize = (maxSize > 0);
|
||||||
|
|
||||||
// parse request line by line
|
// parse request line by line
|
||||||
CHTTPRequest* request = new CHTTPRequest;
|
CHTTPRequest* request = new CHTTPRequest;
|
||||||
try {
|
try {
|
||||||
|
@ -73,6 +144,12 @@ CHTTPRequest* CHTTPProtocol::readRequest(IInputStream* stream)
|
||||||
// read request line. accept and discard leading empty lines.
|
// read request line. accept and discard leading empty lines.
|
||||||
do {
|
do {
|
||||||
line = readLine(stream, scratch);
|
line = readLine(stream, scratch);
|
||||||
|
if (checkSize) {
|
||||||
|
if (line.size() + 2 > maxSize) {
|
||||||
|
throw XHTTP(413);
|
||||||
|
}
|
||||||
|
maxSize -= line.size() + 2;
|
||||||
|
}
|
||||||
} while (line.empty());
|
} while (line.empty());
|
||||||
|
|
||||||
// parse request line: <method> <uri> <version>
|
// parse request line: <method> <uri> <version>
|
||||||
|
@ -109,12 +186,13 @@ CHTTPRequest* CHTTPProtocol::readRequest(IInputStream* stream)
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse headers
|
// parse headers
|
||||||
readHeaders(stream, request, false, scratch);
|
readHeaders(stream, request, false, scratch,
|
||||||
|
checkSize ? &maxSize : NULL);
|
||||||
|
|
||||||
// HTTP/1.1 requests must have a Host header
|
// HTTP/1.1 requests must have a Host header
|
||||||
if (request->m_majorVersion > 1 ||
|
if (request->m_majorVersion > 1 ||
|
||||||
(request->m_majorVersion == 1 && request->m_minorVersion >= 1)) {
|
(request->m_majorVersion == 1 && request->m_minorVersion >= 1)) {
|
||||||
if (request->m_headerIndexByName.count("Host") == 0) {
|
if (request->isHeader("Host") == 0) {
|
||||||
log((CLOG_DEBUG1 "Host header missing"));
|
log((CLOG_DEBUG1 "Host header missing"));
|
||||||
throw XHTTP(400);
|
throw XHTTP(400);
|
||||||
}
|
}
|
||||||
|
@ -123,8 +201,8 @@ CHTTPRequest* CHTTPProtocol::readRequest(IInputStream* stream)
|
||||||
// some methods may not have a body. ensure that the headers
|
// some methods may not have a body. ensure that the headers
|
||||||
// that indicate the body length do not exist for those methods
|
// that indicate the body length do not exist for those methods
|
||||||
// and do exist for others.
|
// and do exist for others.
|
||||||
if ((request->m_headerIndexByName.count("Transfer-Encoding") == 0 &&
|
if ((request->isHeader("Transfer-Encoding") ||
|
||||||
request->m_headerIndexByName.count("Content-Length") == 0) !=
|
request->isHeader("Content-Length")) ==
|
||||||
(request->m_method == "GET" ||
|
(request->m_method == "GET" ||
|
||||||
request->m_method == "HEAD")) {
|
request->m_method == "HEAD")) {
|
||||||
log((CLOG_DEBUG1 "HTTP method (%s)/body mismatch", request->m_method.c_str()));
|
log((CLOG_DEBUG1 "HTTP method (%s)/body mismatch", request->m_method.c_str()));
|
||||||
|
@ -136,13 +214,11 @@ CHTTPRequest* CHTTPProtocol::readRequest(IInputStream* stream)
|
||||||
// 1. Transfer-Encoding indicates a "chunked" transfer
|
// 1. Transfer-Encoding indicates a "chunked" transfer
|
||||||
// 2. Content-Length is present
|
// 2. Content-Length is present
|
||||||
// Content-Length is ignored for "chunked" transfers.
|
// Content-Length is ignored for "chunked" transfers.
|
||||||
CHTTPRequest::CHeaderMap::iterator index = request->
|
CString header;
|
||||||
m_headerIndexByName.find("Transfer-Encoding");
|
if (!(header = request->getHeader("Transfer-Encoding")).empty()) {
|
||||||
if (index != request->m_headerIndexByName.end()) {
|
|
||||||
// we only understand "chunked" encodings
|
// we only understand "chunked" encodings
|
||||||
if (!CHTTPUtil::CaselessCmp::equal(
|
if (!CHTTPUtil::CaselessCmp::equal(header, "chunked")) {
|
||||||
request->m_headers[index->second], "chunked")) {
|
log((CLOG_DEBUG1 "unsupported Transfer-Encoding %s", header.c_str()));
|
||||||
log((CLOG_DEBUG1 "unsupported Transfer-Encoding %s", request->m_headers[index->second].c_str()));
|
|
||||||
throw XHTTP(501);
|
throw XHTTP(501);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,36 +226,39 @@ CHTTPRequest* CHTTPProtocol::readRequest(IInputStream* stream)
|
||||||
UInt32 oldSize;
|
UInt32 oldSize;
|
||||||
do {
|
do {
|
||||||
oldSize = request->m_body.size();
|
oldSize = request->m_body.size();
|
||||||
request->m_body += readChunk(stream, scratch);
|
request->m_body += readChunk(stream, scratch,
|
||||||
|
checkSize ? &maxSize : NULL);
|
||||||
} while (request->m_body.size() != oldSize);
|
} while (request->m_body.size() != oldSize);
|
||||||
|
|
||||||
// read footer
|
// read footer
|
||||||
readHeaders(stream, request, true, scratch);
|
readHeaders(stream, request, true, scratch,
|
||||||
|
checkSize ? &maxSize : NULL);
|
||||||
|
|
||||||
// remove "chunked" from Transfer-Encoding and set the
|
// remove "chunked" from Transfer-Encoding and set the
|
||||||
// Content-Length.
|
// Content-Length.
|
||||||
// FIXME
|
std::ostringstream s;
|
||||||
// FIXME -- note that just deleting Transfer-Encoding will
|
s << std::dec << request->m_body.size();
|
||||||
// mess up indices in m_headerIndexByName, and replacing
|
request->eraseHeader("Transfer-Encoding");
|
||||||
// it with Content-Length could lead to two of those.
|
request->insertHeader("Content-Length", s.str());
|
||||||
}
|
}
|
||||||
else if ((index = request->m_headerIndexByName.
|
else if (!(header = request->getHeader("Content-Length")).empty()) {
|
||||||
find("Content-Length")) !=
|
|
||||||
request->m_headerIndexByName.end()) {
|
|
||||||
// FIXME -- check for overly-long requests
|
|
||||||
|
|
||||||
// parse content-length
|
// parse content-length
|
||||||
UInt32 length;
|
UInt32 length;
|
||||||
{
|
{
|
||||||
std::istringstream s(request->m_headers[index->second]);
|
std::istringstream s(header);
|
||||||
s.exceptions(std::ios::goodbit);
|
s.exceptions(std::ios::goodbit);
|
||||||
s >> length;
|
s >> length;
|
||||||
if (!s) {
|
if (!s) {
|
||||||
log((CLOG_DEBUG1 "cannot parse Content-Length", request->m_headers[index->second].c_str()));
|
log((CLOG_DEBUG1 "cannot parse Content-Length", header.c_str()));
|
||||||
throw XHTTP(400);
|
throw XHTTP(400);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check against expected size
|
||||||
|
if (checkSize && length > maxSize) {
|
||||||
|
throw XHTTP(413);
|
||||||
|
}
|
||||||
|
|
||||||
// use content length
|
// use content length
|
||||||
request->m_body = readBlock(stream, length, scratch);
|
request->m_body = readBlock(stream, length, scratch);
|
||||||
if (request->m_body.size() != length) {
|
if (request->m_body.size() != length) {
|
||||||
|
@ -287,13 +366,11 @@ bool CHTTPProtocol::parseFormData(
|
||||||
static const char quote[] = "\"";
|
static const char quote[] = "\"";
|
||||||
|
|
||||||
// find the Content-Type header
|
// find the Content-Type header
|
||||||
CHTTPRequest::CHeaderMap::const_iterator contentTypeIndex =
|
const CString contentType = request.getHeader("Content-Type");
|
||||||
request.m_headerIndexByName.find("Content-Type");
|
if (contentType.empty()) {
|
||||||
if (contentTypeIndex == request.m_headerIndexByName.end()) {
|
|
||||||
// missing required Content-Type header
|
// missing required Content-Type header
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const CString contentType = request.m_headers[contentTypeIndex->second];
|
|
||||||
|
|
||||||
// parse type
|
// parse type
|
||||||
CString::const_iterator index = std::search(
|
CString::const_iterator index = std::search(
|
||||||
|
@ -335,8 +412,7 @@ bool CHTTPProtocol::parseFormData(
|
||||||
if (body.size() >= partIndex + 2 &&
|
if (body.size() >= partIndex + 2 &&
|
||||||
body[partIndex ] == '-' &&
|
body[partIndex ] == '-' &&
|
||||||
body[partIndex + 1] == '-') {
|
body[partIndex + 1] == '-') {
|
||||||
// found last part. success if there's no trailing data.
|
// found last part. ignore trailing data, if any.
|
||||||
// FIXME -- check for trailing data (other than a single CRLF)
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -500,7 +576,8 @@ CString CHTTPProtocol::readBlock(
|
||||||
|
|
||||||
CString CHTTPProtocol::readChunk(
|
CString CHTTPProtocol::readChunk(
|
||||||
IInputStream* stream,
|
IInputStream* stream,
|
||||||
CString& tmpBuffer)
|
CString& tmpBuffer,
|
||||||
|
UInt32* maxSize)
|
||||||
{
|
{
|
||||||
CString line;
|
CString line;
|
||||||
|
|
||||||
|
@ -522,8 +599,15 @@ CString CHTTPProtocol::readChunk(
|
||||||
return CString();
|
return CString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check size
|
||||||
|
if (maxSize != NULL) {
|
||||||
|
if (line.size() + 2 + size + 2 > *maxSize) {
|
||||||
|
throw XHTTP(413);
|
||||||
|
}
|
||||||
|
maxSize -= line.size() + 2 + size + 2;
|
||||||
|
}
|
||||||
|
|
||||||
// read size bytes
|
// read size bytes
|
||||||
// FIXME -- check for overly-long requests
|
|
||||||
CString data = readBlock(stream, size, tmpBuffer);
|
CString data = readBlock(stream, size, tmpBuffer);
|
||||||
if (data.size() != size) {
|
if (data.size() != size) {
|
||||||
log((CLOG_DEBUG1 "expected/actual chunk size mismatch", size, data.size()));
|
log((CLOG_DEBUG1 "expected/actual chunk size mismatch", size, data.size()));
|
||||||
|
@ -544,27 +628,36 @@ void CHTTPProtocol::readHeaders(
|
||||||
IInputStream* stream,
|
IInputStream* stream,
|
||||||
CHTTPRequest* request,
|
CHTTPRequest* request,
|
||||||
bool isFooter,
|
bool isFooter,
|
||||||
CString& tmpBuffer)
|
CString& tmpBuffer,
|
||||||
|
UInt32* maxSize)
|
||||||
{
|
{
|
||||||
// parse headers. done with headers when we get a blank line.
|
// parse headers. done with headers when we get a blank line.
|
||||||
|
CString name;
|
||||||
CString line = readLine(stream, tmpBuffer);
|
CString line = readLine(stream, tmpBuffer);
|
||||||
while (!line.empty()) {
|
while (!line.empty()) {
|
||||||
|
// check size
|
||||||
|
if (maxSize != NULL) {
|
||||||
|
if (line.size() + 2 > *maxSize) {
|
||||||
|
throw XHTTP(413);
|
||||||
|
}
|
||||||
|
*maxSize -= line.size() + 2;
|
||||||
|
}
|
||||||
|
|
||||||
// if line starts with space or tab then append it to the
|
// if line starts with space or tab then append it to the
|
||||||
// previous header. if there is no previous header then
|
// previous header. if there is no previous header then
|
||||||
// throw.
|
// throw.
|
||||||
if (line[0] == ' ' || line[0] == '\t') {
|
if (line[0] == ' ' || line[0] == '\t') {
|
||||||
if (request->m_headers.size() == 0) {
|
if (name.empty()) {
|
||||||
log((CLOG_DEBUG1 "first header is a continuation"));
|
log((CLOG_DEBUG1 "first header is a continuation"));
|
||||||
throw XHTTP(400);
|
throw XHTTP(400);
|
||||||
}
|
}
|
||||||
request->m_headers.back() += ",";
|
request->appendHeader(name, line);
|
||||||
request->m_headers.back() == line;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// line should have the form: <name>:[<value>]
|
// line should have the form: <name>:[<value>]
|
||||||
else {
|
else {
|
||||||
// parse
|
// parse
|
||||||
CString name, value;
|
CString value;
|
||||||
std::istringstream s(line);
|
std::istringstream s(line);
|
||||||
s.exceptions(std::ios::goodbit);
|
s.exceptions(std::ios::goodbit);
|
||||||
std::getline(s, name, ':');
|
std::getline(s, name, ':');
|
||||||
|
@ -577,29 +670,14 @@ void CHTTPProtocol::readHeaders(
|
||||||
// check validity of name
|
// check validity of name
|
||||||
if (isFooter) {
|
if (isFooter) {
|
||||||
// FIXME -- only certain names are allowed in footers
|
// FIXME -- only certain names are allowed in footers
|
||||||
|
// but which ones?
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if we've seen this header before
|
request->appendHeader(name, value);
|
||||||
CHTTPRequest::CHeaderMap::iterator index =
|
|
||||||
request->m_headerIndexByName.find(name);
|
|
||||||
if (index == request->m_headerIndexByName.end()) {
|
|
||||||
// it's a new header
|
|
||||||
request->m_headerIndexByName.insert(std::make_pair(name,
|
|
||||||
request->m_headers.size()));
|
|
||||||
request->m_headers.push_back(value);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// it's an existing header. append value to previous
|
|
||||||
// header, separated by a comma.
|
|
||||||
request->m_headers[index->second] += ',';
|
|
||||||
request->m_headers[index->second] += value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// next header
|
// next header
|
||||||
line = readLine(stream, tmpBuffer);
|
line = readLine(stream, tmpBuffer);
|
||||||
|
|
||||||
// FIXME -- should check for overly-long requests
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "BasicTypes.h"
|
#include "BasicTypes.h"
|
||||||
#include "CString.h"
|
#include "CString.h"
|
||||||
|
#include "stdlist.h"
|
||||||
#include "stdmap.h"
|
#include "stdmap.h"
|
||||||
#include "stdvector.h"
|
#include "stdvector.h"
|
||||||
|
|
||||||
|
@ -25,19 +26,52 @@ public:
|
||||||
|
|
||||||
class CHTTPRequest {
|
class CHTTPRequest {
|
||||||
public:
|
public:
|
||||||
typedef std::map<CString, UInt32, CHTTPUtil::CaselessCmp> CHeaderMap;
|
typedef std::list<std::pair<CString, CString> > CHeaderList;
|
||||||
typedef std::vector<CString> CHeaderList;
|
typedef std::map<CString, CHeaderList::iterator,
|
||||||
|
CHTTPUtil::CaselessCmp> CHeaderMap;
|
||||||
|
typedef CHeaderList::const_iterator const_iterator;
|
||||||
|
|
||||||
|
CHTTPRequest();
|
||||||
|
~CHTTPRequest();
|
||||||
|
|
||||||
|
// manipulators
|
||||||
|
|
||||||
|
// add a header by name. replaces existing header, if any.
|
||||||
|
// headers are sent in the order they're inserted. replacing
|
||||||
|
// a header does not change its original position in the order.
|
||||||
|
void insertHeader(const CString& name, const CString& value);
|
||||||
|
|
||||||
|
// append a header. equivalent to insertHeader() if the header
|
||||||
|
// doesn't exist, otherwise it appends a comma and the value to
|
||||||
|
// the existing header.
|
||||||
|
void appendHeader(const CString& name, const CString& value);
|
||||||
|
|
||||||
|
// remove a header by name. does nothing if no such header.
|
||||||
|
void eraseHeader(const CString& name);
|
||||||
|
|
||||||
|
// accessors
|
||||||
|
|
||||||
|
// returns true iff the header exists
|
||||||
|
bool isHeader(const CString& name) const;
|
||||||
|
|
||||||
|
// get a header by name. returns the empty string if no such header.
|
||||||
|
CString getHeader(const CString& name) const;
|
||||||
|
|
||||||
|
// get iterator over all headers in the order they were added
|
||||||
|
const_iterator begin() const { return m_headers.begin(); }
|
||||||
|
const_iterator end() const { return m_headers.end(); }
|
||||||
|
|
||||||
|
public:
|
||||||
|
// note -- these members are public for convenience
|
||||||
CString m_method;
|
CString m_method;
|
||||||
CString m_uri;
|
CString m_uri;
|
||||||
SInt32 m_majorVersion;
|
SInt32 m_majorVersion;
|
||||||
SInt32 m_minorVersion;
|
SInt32 m_minorVersion;
|
||||||
|
|
||||||
CHeaderList m_headers;
|
|
||||||
CHeaderMap m_headerIndexByName;
|
|
||||||
|
|
||||||
CString m_body;
|
CString m_body;
|
||||||
// FIXME -- need parts-of-body for POST messages
|
|
||||||
|
private:
|
||||||
|
CHeaderList m_headers;
|
||||||
|
CHeaderMap m_headerByName;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CHTTPReply {
|
class CHTTPReply {
|
||||||
|
@ -59,9 +93,11 @@ class CHTTPProtocol {
|
||||||
public:
|
public:
|
||||||
// read and parse an HTTP request. result is returned in a
|
// read and parse an HTTP request. result is returned in a
|
||||||
// CHTTPRequest which the client must delete. throws an
|
// CHTTPRequest which the client must delete. throws an
|
||||||
// XHTTP if there was a parse error. throws an XIO
|
// XHTTP if there was a parse error. throws an XIO exception
|
||||||
// exception if there was a read error.
|
// if there was a read error. if maxSize is greater than
|
||||||
static CHTTPRequest* readRequest(IInputStream*);
|
// zero and the request is larger than maxSize bytes then
|
||||||
|
// throws XHTTP(413).
|
||||||
|
static CHTTPRequest* readRequest(IInputStream*, UInt32 maxSize = 0);
|
||||||
|
|
||||||
// send an HTTP reply on the stream
|
// send an HTTP reply on the stream
|
||||||
static void reply(IOutputStream*, CHTTPReply&);
|
static void reply(IOutputStream*, CHTTPReply&);
|
||||||
|
@ -77,10 +113,12 @@ private:
|
||||||
static CString readLine(IInputStream*, CString& tmpBuffer);
|
static CString readLine(IInputStream*, CString& tmpBuffer);
|
||||||
static CString readBlock(IInputStream*,
|
static CString readBlock(IInputStream*,
|
||||||
UInt32 numBytes, CString& tmpBuffer);
|
UInt32 numBytes, CString& tmpBuffer);
|
||||||
static CString readChunk(IInputStream*, CString& tmpBuffer);
|
static CString readChunk(IInputStream*, CString& tmpBuffer,
|
||||||
|
UInt32* maxSize);
|
||||||
static void readHeaders(IInputStream*,
|
static void readHeaders(IInputStream*,
|
||||||
CHTTPRequest*, bool isFooter,
|
CHTTPRequest*, bool isFooter,
|
||||||
CString& tmpBuffer);
|
CString& tmpBuffer,
|
||||||
|
UInt32* maxSize);
|
||||||
|
|
||||||
static bool isValidToken(const CString&);
|
static bool isValidToken(const CString&);
|
||||||
};
|
};
|
||||||
|
|
|
@ -14,6 +14,11 @@
|
||||||
// CHTTPServer
|
// CHTTPServer
|
||||||
//
|
//
|
||||||
|
|
||||||
|
// maximum size of an HTTP request. this should be large enough to
|
||||||
|
// handle any reasonable request but small enough to prevent a
|
||||||
|
// malicious client from causing us to use too much memory.
|
||||||
|
const UInt32 CHTTPServer::s_maxRequestSize = 32768;
|
||||||
|
|
||||||
CHTTPServer::CHTTPServer(CServer* server) : m_server(server)
|
CHTTPServer::CHTTPServer(CServer* server) : m_server(server)
|
||||||
{
|
{
|
||||||
// do nothing
|
// do nothing
|
||||||
|
@ -31,7 +36,8 @@ void CHTTPServer::processRequest(ISocket* socket)
|
||||||
CHTTPRequest* request = NULL;
|
CHTTPRequest* request = NULL;
|
||||||
try {
|
try {
|
||||||
// parse request
|
// parse request
|
||||||
request = CHTTPProtocol::readRequest(socket->getInputStream());
|
request = CHTTPProtocol::readRequest(
|
||||||
|
socket->getInputStream(), s_maxRequestSize);
|
||||||
if (request == NULL) {
|
if (request == NULL) {
|
||||||
throw XHTTP(400);
|
throw XHTTP(400);
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,6 +96,7 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CServer* m_server;
|
CServer* m_server;
|
||||||
|
static const UInt32 s_maxRequestSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue