Skip to content

Allow Overriding Default Keep-Alive Behavior #78

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 4, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/HTTPConnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -529,9 +529,15 @@ void HTTPConnection::loop() {
// Now we need to check if we can use keep-alive to reuse the SSL connection
// However, if the client did not set content-size or defined connection: close,
// we have no chance to do so.
// Also, the programmer may have explicitly set Connection: close for the response.
std::string hConnection = res.getHeader("Connection");
if (hConnection == "close") {
_isKeepAlive = false;
}
if (!_isKeepAlive) {
// No KeepAlive -> We are done. Transition to next state.
if (!isClosed()) {
res.finalize();
_connectionState = STATE_BODY_FINISHED;
}
} else {
Expand Down
26 changes: 25 additions & 1 deletion src/HTTPHeader.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
#include "HTTPHeader.hpp"

#include <locale>
#include <ostream>
#include <sstream>

namespace httpsserver {

HTTPHeader::HTTPHeader(const std::string &name, const std::string &value):
_name(name),
_name(normalizeHeaderName(name)),
_value(value) {

}
Expand All @@ -16,4 +20,24 @@ std::string HTTPHeader::print() {
return _name + ": " + _value;
}

std::string normalizeHeaderName(std::string const &name) {
std::locale loc;
std::stringbuf buf;
std::ostream oBuf(&buf);
bool upper = true;
std::string::size_type len = name.length();
for (std::string::size_type i = 0; i < len; ++i) {
if (upper) {
oBuf << std::toupper(name[i], loc);
upper = false;
} else {
oBuf << std::tolower(name[i], loc);
if (!std::isalnum(name[i], loc)) {
upper=true;
}
}
}
return buf.str();
}

} /* namespace httpsserver */
9 changes: 9 additions & 0 deletions src/HTTPHeader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@ class HTTPHeader {
std::string print();
};

/**
* \brief Normalizes case in header names
*
* It converts the first letter and every letter after a non-alnum character
* to uppercase. For example, "content-length" becomes "Content-Length" and
* "HOST" becomes "Host".
*/
std::string normalizeHeaderName(std::string const &name);

} /* namespace httpsserver */

#endif /* SRC_HTTPHEADER_HPP_ */
6 changes: 4 additions & 2 deletions src/HTTPHeaders.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,19 @@ HTTPHeaders::~HTTPHeaders() {
}

HTTPHeader * HTTPHeaders::get(std::string const &name) {
std::string normalizedName = normalizeHeaderName(name);
for(std::vector<HTTPHeader*>::iterator header = _headers->begin(); header != _headers->end(); ++header) {
if ((*header)->_name.compare(name)==0) {
if ((*header)->_name.compare(normalizedName)==0) {
return (*header);
}
}
return NULL;
}

std::string HTTPHeaders::getValue(std::string const &name) {
std::string normalizedName = normalizeHeaderName(name);
for(std::vector<HTTPHeader*>::iterator header = _headers->begin(); header != _headers->end(); ++header) {
if ((*header)->_name.compare(name)==0) {
if ((*header)->_name.compare(normalizedName)==0) {
return ((*header)->_value);
}
}
Expand Down
9 changes: 9 additions & 0 deletions src/HTTPResponse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,15 @@ void HTTPResponse::setHeader(std::string const &name, std::string const &value)
_headers.set(new HTTPHeader(name, value));
}

std::string HTTPResponse::getHeader(std::string const &name) {
HTTPHeader * h = _headers.get(name);
if (h != NULL) {
return h->_value;
} else {
return std::string();
}
}

bool HTTPResponse::isHeaderWritten() {
return _headerWritten;
}
Expand Down
1 change: 1 addition & 0 deletions src/HTTPResponse.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class HTTPResponse : public Print {
uint16_t getStatusCode();
std::string getStatusText();
void setHeader(std::string const &name, std::string const &value);
std::string getHeader(std::string const &name);
bool isHeaderWritten();

void printStd(std::string const &str);
Expand Down