http server unittest + refactoring

This commit is contained in:
Benjamin Sergeant 2019-09-26 09:45:59 -07:00
parent 2fb0ebb05b
commit f18980d010
5 changed files with 91 additions and 28 deletions

View File

@ -9,6 +9,7 @@
#include "IXNetSystem.h"
#include "IXSocketConnect.h"
#include "IXSocketFactory.h"
#include "IXUserAgent.h"
#include <fstream>
#include <iostream>
#include <sstream>
@ -112,6 +113,9 @@ namespace ix
uri = "/index.html";
}
WebSocketHttpHeaders headers;
headers["Server"] = userAgent();
std::string path("." + uri);
auto res = readAsString(path);
bool found = res.first;
@ -129,7 +133,6 @@ namespace ix
<< request->uri << " " << content.size();
logInfo(ss.str());
WebSocketHttpHeaders headers;
// FIXME: check extensions to set the content type
// headers["Content-Type"] = "application/octet-stream";
headers["Accept-Ranges"] = "none";
@ -143,4 +146,36 @@ namespace ix
200, "OK", HttpErrorCode::Ok, headers, content);
});
}
void HttpServer::makeRedirectServer(const std::string& redirectUrl)
{
//
// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Redirections
//
setOnConnectionCallback(
[this, redirectUrl](
HttpRequestPtr request,
std::shared_ptr<ConnectionState> /*connectionState*/) -> HttpResponsePtr {
WebSocketHttpHeaders headers;
headers["Server"] = userAgent();
// Log request
std::stringstream ss;
ss << request->method << " " << request->headers["User-Agent"] << " "
<< request->uri;
logInfo(ss.str());
if (request->method == "POST")
{
return std::make_shared<HttpResponse>(
200, "OK", HttpErrorCode::Ok, headers, std::string());
}
headers["Location"] = redirectUrl;
return std::make_shared<HttpResponse>(
301, "OK", HttpErrorCode::Ok, headers, std::string());
});
}
} // namespace ix

View File

@ -34,6 +34,8 @@ namespace ix
void setOnConnectionCallback(const OnConnectionCallback& callback);
void makeRedirectServer(const std::string& redirectUrl);
private:
// Member variables
OnConnectionCallback _onConnectionCallback;

View File

@ -69,6 +69,7 @@ namespace ix
ss << " ";
ss << reason;
ss << "\r\n";
ss << "Server: " << userAgent() << "\r\n";
// Socket write can only be cancelled through a timeout here, not manually.
static std::atomic<bool> requestInitCancellation(false);

View File

@ -62,4 +62,55 @@ TEST_CASE("http server", "[httpd]")
server.stop();
}
SECTION("Connect to a local HTTP server, with redirection enabled")
{
int port = getFreePort();
ix::HttpServer server(port, "127.0.0.1");
server.makeRedirectServer("http://example.com");
auto res = server.listen();
REQUIRE(res.first);
server.start();
HttpClient httpClient;
WebSocketHttpHeaders headers;
std::string url("http://127.0.0.1:");
url += std::to_string(port);
url += "/data/foo.txt";
auto args = httpClient.createRequest(url);
args->extraHeaders = headers;
args->connectTimeout = 60;
args->transferTimeout = 60;
args->followRedirects = false; // we dont want to follow redirect during testing
args->maxRedirects = 10;
args->verbose = true;
args->compress = true;
args->logger = [](const std::string& msg) { std::cout << msg; };
args->onProgressCallback = [](int current, int total) -> bool {
std::cerr << "\r"
<< "Downloaded " << current << " bytes out of " << total;
return true;
};
auto response = httpClient.get(url, args);
for (auto it : response->headers)
{
std::cerr << it.first << ": " << it.second << std::endl;
}
std::cerr << "Upload size: " << response->uploadSize << std::endl;
std::cerr << "Download size: " << response->downloadSize << std::endl;
std::cerr << "Status: " << response->statusCode << std::endl;
std::cerr << "Error message: " << response->errorMsg << std::endl;
REQUIRE(response->errorCode == HttpErrorCode::Ok);
REQUIRE(response->statusCode == 301);
REQUIRE(response->headers["Location"] == "http://example.com");
server.stop();
}
}

View File

@ -24,33 +24,7 @@ namespace ix
if (redirect)
{
//
// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Redirections
//
server.setOnConnectionCallback(
[redirectUrl](
HttpRequestPtr request,
std::shared_ptr<ConnectionState> /*connectionState*/) -> HttpResponsePtr {
WebSocketHttpHeaders headers;
// Log request
std::stringstream ss;
ss << request->method << " " << request->headers["User-Agent"] << " "
<< request->uri;
spdlog::info(ss.str());
if (request->method == "POST")
{
return std::make_shared<HttpResponse>(
200, "OK", HttpErrorCode::Ok, headers, std::string());
}
headers["Location"] = redirectUrl;
return std::make_shared<HttpResponse>(
301, "OK", HttpErrorCode::Ok, headers, std::string());
});
server.makeRedirectServer(redirectUrl);
}
auto res = server.listen();