Client: added support for non-standard line endings in response status and header
This commit is contained in:
parent
f1327d3bc3
commit
d9d554b1b5
3 changed files with 77 additions and 2 deletions
|
|
@ -9,6 +9,53 @@
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
namespace SimpleWeb {
|
||||||
|
class HeaderEndMatch {
|
||||||
|
int crlfcrlf = 0;
|
||||||
|
int lflf = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
std::pair<asio::buffers_iterator<asio::const_buffers_1>, bool> operator()(asio::buffers_iterator<asio::const_buffers_1> begin, asio::buffers_iterator<asio::const_buffers_1> end) {
|
||||||
|
auto it = begin;
|
||||||
|
for(; it != end; ++it) {
|
||||||
|
if(*it == '\n') {
|
||||||
|
if(crlfcrlf == 1)
|
||||||
|
++crlfcrlf;
|
||||||
|
else if(crlfcrlf == 2)
|
||||||
|
crlfcrlf = 0;
|
||||||
|
else if(crlfcrlf == 3)
|
||||||
|
return {++it, true};
|
||||||
|
if(lflf == 0)
|
||||||
|
++lflf;
|
||||||
|
else if(lflf == 1)
|
||||||
|
return {++it, true};
|
||||||
|
}
|
||||||
|
else if(*it == '\r') {
|
||||||
|
if(crlfcrlf == 0)
|
||||||
|
++crlfcrlf;
|
||||||
|
else if(crlfcrlf == 2)
|
||||||
|
++crlfcrlf;
|
||||||
|
lflf = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
crlfcrlf = 0;
|
||||||
|
lflf = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {it, false};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace SimpleWeb
|
||||||
|
#ifndef USE_STANDALONE_ASIO
|
||||||
|
namespace boost {
|
||||||
|
#endif
|
||||||
|
namespace asio {
|
||||||
|
template <> struct is_match_condition<SimpleWeb::HeaderEndMatch> : public std::true_type {};
|
||||||
|
} // namespace asio
|
||||||
|
#ifndef USE_STANDALONE_ASIO
|
||||||
|
} // namespace boost
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace SimpleWeb {
|
namespace SimpleWeb {
|
||||||
template <class socket_type>
|
template <class socket_type>
|
||||||
class Client;
|
class Client;
|
||||||
|
|
@ -468,7 +515,7 @@ namespace SimpleWeb {
|
||||||
|
|
||||||
void read(const std::shared_ptr<Session> &session) {
|
void read(const std::shared_ptr<Session> &session) {
|
||||||
session->connection->set_timeout();
|
session->connection->set_timeout();
|
||||||
asio::async_read_until(*session->connection->socket, session->response->streambuf, "\r\n\r\n", [this, session](const error_code &ec, std::size_t bytes_transferred) {
|
asio::async_read_until(*session->connection->socket, session->response->streambuf, HeaderEndMatch(), [this, session](const error_code &ec, std::size_t bytes_transferred) {
|
||||||
session->connection->cancel_timeout();
|
session->connection->cancel_timeout();
|
||||||
auto lock = session->connection->handler_runner->continue_lock();
|
auto lock = session->connection->handler_runner->continue_lock();
|
||||||
if(!lock)
|
if(!lock)
|
||||||
|
|
|
||||||
|
|
@ -176,6 +176,14 @@ int main() {
|
||||||
response->write("test");
|
response->write("test");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
server.resource["^/non-standard-line-endings1$"]["GET"] = [](shared_ptr<HttpServer::Response> response, shared_ptr<HttpServer::Request> /*request*/) {
|
||||||
|
*response << "HTTP/1.1 200 OK\r\nname: value\n\n";
|
||||||
|
};
|
||||||
|
|
||||||
|
server.resource["^/non-standard-line-endings2$"]["GET"] = [](shared_ptr<HttpServer::Response> response, shared_ptr<HttpServer::Request> /*request*/) {
|
||||||
|
*response << "HTTP/1.1 200 OK\nname: value\n\n";
|
||||||
|
};
|
||||||
|
|
||||||
thread server_thread([&server]() {
|
thread server_thread([&server]() {
|
||||||
// Start server
|
// Start server
|
||||||
server.start();
|
server.start();
|
||||||
|
|
@ -282,6 +290,26 @@ int main() {
|
||||||
auto r = client.request("GET", "/session-close-without-correct-header");
|
auto r = client.request("GET", "/session-close-without-correct-header");
|
||||||
ASSERT(r->content.string() == "test");
|
ASSERT(r->content.string() == "test");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test non-standard line endings
|
||||||
|
{
|
||||||
|
auto r = client.request("GET", "/non-standard-line-endings1");
|
||||||
|
ASSERT(r->http_version == "1.1");
|
||||||
|
ASSERT(r->status_code == "200 OK");
|
||||||
|
ASSERT(r->header.size() == 1);
|
||||||
|
ASSERT(r->header.begin()->first == "name");
|
||||||
|
ASSERT(r->header.begin()->second == "value");
|
||||||
|
ASSERT(r->content.string().empty());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto r = client.request("GET", "/non-standard-line-endings2");
|
||||||
|
ASSERT(r->http_version == "1.1");
|
||||||
|
ASSERT(r->status_code == "200 OK");
|
||||||
|
ASSERT(r->header.size() == 1);
|
||||||
|
ASSERT(r->header.begin()->first == "name");
|
||||||
|
ASSERT(r->header.begin()->second == "value");
|
||||||
|
ASSERT(r->content.string().empty());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
HttpClient client("localhost:8080");
|
HttpClient client("localhost:8080");
|
||||||
|
|
|
||||||
|
|
@ -283,7 +283,7 @@ namespace SimpleWeb {
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
if((version_end + 1) < line.size())
|
if((version_end + 1) < line.size())
|
||||||
status_code = line.substr(version_end + 1, line.size() - (version_end + 1) - 1);
|
status_code = line.substr(version_end + 1, line.size() - (version_end + 1) - (line.back() == '\r' ? 1 : 0));
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue