1
0
Fork 0

issue #231: handle more client error cases

This commit is contained in:
Jan Steemann 2012-10-16 11:33:49 +02:00
parent 8cad4ff0a8
commit 29571a2e3a
3 changed files with 69 additions and 33 deletions

View File

@ -197,44 +197,31 @@ namespace triagens {
case HttpRequest::HTTP_REQUEST_GET:
case HttpRequest::HTTP_REQUEST_DELETE:
case HttpRequest::HTTP_REQUEST_HEAD:
this->_bodyLength = this->_request->contentLength();
if (this->_bodyLength > 0) {
LOGGER_WARNING << "received http GET/DELETE/HEAD request with body length, this should not happen";
this->_readRequestBody = true;
}
else {
handleRequest = true;
}
break;
case HttpRequest::HTTP_REQUEST_POST:
case HttpRequest::HTTP_REQUEST_PUT:
case HttpRequest::HTTP_REQUEST_PATCH:
this->_bodyLength = this->_request->contentLength();
case HttpRequest::HTTP_REQUEST_PATCH: {
const bool expectContentLength = (this->_requestType == HttpRequest::HTTP_REQUEST_POST ||
this->_requestType == HttpRequest::HTTP_REQUEST_PUT ||
this->_requestType == HttpRequest::HTTP_REQUEST_DELETE);
if (this->_bodyLength > 0) {
this->_readRequestBody = true;
if (this->_bodyLength > this->_maximalBodySize) {
LOGGER_WARNING << "maximal body size is " << this->_maximalBodySize << ", request body size is " << this->_bodyLength;
// request entity too large
HttpResponse response(HttpResponse::ENTITY_TOO_LARGE);
this->handleResponse(&response);
return true;
}
if (! checkContentLength(expectContentLength)) {
return true;
}
else {
if (this->_bodyLength == 0) {
handleRequest = true;
}
break;
}
default:
default: {
LOGGER_WARNING << "got corrupted HTTP request '" << string(this->_readBuffer->c_str(), (this->_readPosition < 6 ? this->_readPosition : 6)) << "'";
// bad request
HttpResponse response(HttpResponse::BAD);
// bad request, method not allowed
HttpResponse response(HttpResponse::METHOD_NOT_ALLOWED);
this->handleResponse(&response);
return true;
}
}
// check for a 100-continue
@ -430,6 +417,7 @@ namespace triagens {
response->headResponse(response->bodySize());
}
// reserve some outbuffer size
const size_t len = response->bodySize() + 128;
triagens::basics::StringBuffer* buffer = new triagens::basics::StringBuffer(TRI_UNKNOWN_MEM_ZONE, len);
// write header
@ -455,6 +443,48 @@ namespace triagens {
this->fillWriteBuffer();
}
////////////////////////////////////////////////////////////////////////////////
/// check the content-length header of a request and fail it is broken
////////////////////////////////////////////////////////////////////////////////
bool checkContentLength (const bool expectContentLength) {
const int64_t bodyLength = this->_request->contentLength();
if (bodyLength < 0) {
// bad request, body length is < 0. this is a client error
HttpResponse response(HttpResponse::LENGTH_REQUIRED);
this->handleResponse(&response);
return false;
}
if (! expectContentLength && bodyLength > 0) {
// content-length header was sent but the request method does not support that
// we'll warn but read the body anyway
LOGGER_WARNING << "received HTTP GET/DELETE/HEAD request with content-length, this should not happen";
}
if ((size_t) bodyLength > this->_maximalBodySize) {
// request entity too large
LOGGER_WARNING << "maximal body size is " << this->_maximalBodySize << ", request body size is " << bodyLength;
HttpResponse response(HttpResponse::ENTITY_TOO_LARGE);
this->handleResponse(&response);
return false;
}
// set instance variable to content-length value
this->_bodyLength = (size_t) bodyLength;
if (this->_bodyLength > 0) {
// we'll read the body
this->_readRequestBody = true;
}
// everything's fine
return true;
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////

View File

@ -235,7 +235,7 @@ void HttpRequest::write (TRI_string_buffer_t* buffer) const {
}
TRI_AppendString2StringBuffer(buffer, "content-length: ", 16);
TRI_AppendUInt64StringBuffer(buffer, _contentLength);
TRI_AppendInt64StringBuffer(buffer, _contentLength);
TRI_AppendString2StringBuffer(buffer, "\r\n\r\n", 4);
if (_body != 0 && 0 < _bodySize) {
@ -247,7 +247,7 @@ void HttpRequest::write (TRI_string_buffer_t* buffer) const {
/// {@inheritDoc}
////////////////////////////////////////////////////////////////////////////////
size_t HttpRequest::contentLength () const {
int64_t HttpRequest::contentLength () const {
return _contentLength;
}
@ -385,10 +385,15 @@ size_t HttpRequest::bodySize () const {
int HttpRequest::setBody (char const* newBody, size_t length) {
_body = TRI_DuplicateString2Z(TRI_UNKNOWN_MEM_ZONE, newBody, length);
_contentLength = _bodySize = length;
if (_body == 0) {
return TRI_ERROR_OUT_OF_MEMORY;
}
_freeables.push_back(_body);
_contentLength = (int64_t) length;
_bodySize = length;
return TRI_ERROR_NO_ERROR;
}
@ -398,7 +403,8 @@ int HttpRequest::setBody (char const* newBody, size_t length) {
void HttpRequest::setHeader (char const* key, size_t keyLength, char const* value) {
if (keyLength == 14 && memcmp(key, "content-length", keyLength) == 0) { // 14 = strlen("content-length")
_contentLength = TRI_UInt64String(value);
_contentLength = TRI_Int64String(value);
}
else {
_headers.insert(key, keyLength, value);

View File

@ -289,7 +289,7 @@ namespace triagens {
/// @brief returns the content length
////////////////////////////////////////////////////////////////////////////////
size_t contentLength () const;
int64_t contentLength () const;
////////////////////////////////////////////////////////////////////////////////
/// @brief returns a header field
@ -519,7 +519,7 @@ namespace triagens {
/// @brief content length
////////////////////////////////////////////////////////////////////////////////
size_t _contentLength;
int64_t _contentLength;
////////////////////////////////////////////////////////////////////////////////
/// @brief body