#include "HTTPRequest.hpp" namespace httpsserver { HTTPRequest::HTTPRequest( ConnectionContext * con, HTTPHeaders * headers, HTTPNode * resolvedNode, std::string method, ResourceParameters * params, std::string requestString): _con(con), _headers(headers), _resolvedNode(resolvedNode), _method(method), _params(params), _requestString(requestString) { HTTPHeader * contentLength = headers->get("Content-Length"); if (contentLength == NULL) { _remainingContent = 0; _contentLengthSet = false; } else { _remainingContent = parseInt(contentLength->_value); _contentLengthSet = true; } } HTTPRequest::~HTTPRequest() { _headers->clearAll(); } ResourceParameters * HTTPRequest::getParams() { return _params; } std::string HTTPRequest::getHeader(std::string const &name) { HTTPHeader * h = _headers->get(name); if (h != NULL) { return h->_value; } else { return std::string(); } } void HTTPRequest::setHeader(std::string const &name, std::string const &value) { _headers->set(new HTTPHeader(name, value)); } HTTPNode * HTTPRequest::getResolvedNode() { return _resolvedNode; } size_t HTTPRequest::readBytes(byte * buffer, size_t length) { // Limit reading to content length if (_contentLengthSet && length > _remainingContent) { length = _remainingContent; } size_t bytesRead = 0; if (length > 0) { bytesRead = _con->readBuffer(buffer, length); } if (_contentLengthSet) { _remainingContent -= bytesRead; } return bytesRead; } size_t HTTPRequest::readChars(char * buffer, size_t length) { return readBytes((byte*)buffer, length); } size_t HTTPRequest::getContentLength() { return _remainingContent; } std::string HTTPRequest::getRequestString() { return _requestString; } std::string HTTPRequest::getMethod() { return _method; } std::string HTTPRequest::getTag() { return _resolvedNode->_tag; } bool HTTPRequest::requestComplete() { if (_contentLengthSet) { // If we have a content size, rely on it. return (_remainingContent == 0); } else { // If there is no more input... return (_con->pendingBufferSize() == 0); } } /** * This function will drop whatever is remaining of the request body */ void HTTPRequest::discardRequestBody() { byte buf[16]; while(!requestComplete()) { readBytes(buf, 16); } } std::string HTTPRequest::getBasicAuthUser() { std::string token = decodeBasicAuthToken(); size_t splitpoint = token.find(":"); if (splitpoint != std::string::npos && splitpoint > 0) { return token.substr(0, splitpoint); } else { return std::string(); } } std::string HTTPRequest::getBasicAuthPassword() { std::string token = decodeBasicAuthToken(); size_t splitpoint = token.find(":"); if (splitpoint != std::string::npos && splitpoint > 0) { return token.substr(splitpoint+1); } else { return std::string(); } } std::string HTTPRequest::decodeBasicAuthToken() { std::string basicAuthString = getHeader("Authorization"); // Get the length of the token size_t sourceLength = basicAuthString.length(); // Only handle basic auth tokens if (basicAuthString.substr(0, 6) != "Basic ") { return std::string(); } // If the token is too long, skip if (sourceLength > 100) { return std::string(); } else { // Try to decode. As we are using mbedtls anyway, we can use that function unsigned char * bufOut = new unsigned char[basicAuthString.length()]; size_t outputLength = 0; int res = mbedtls_base64_decode( bufOut, sourceLength, &outputLength, ((const unsigned char *)basicAuthString.substr(6).c_str()), // Strip "Basic " sourceLength - 6 // Strip "Basic " ); // Failure of decoding if (res != 0) { delete[] bufOut; return std::string(); } std::string tokenRes = std::string((char*)bufOut, outputLength); delete[] bufOut; return tokenRes; } } bool HTTPRequest::isSecure() { return _con->isSecure(); } void HTTPRequest::setWebsocketHandler(WebsocketHandler *wsHandler) { _con->setWebsocketHandler(wsHandler); } } /* namespace httpsserver */