http server unittest + refactoring
This commit is contained in:
parent
2fb0ebb05b
commit
f18980d010
@ -9,6 +9,7 @@
|
|||||||
#include "IXNetSystem.h"
|
#include "IXNetSystem.h"
|
||||||
#include "IXSocketConnect.h"
|
#include "IXSocketConnect.h"
|
||||||
#include "IXSocketFactory.h"
|
#include "IXSocketFactory.h"
|
||||||
|
#include "IXUserAgent.h"
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
@ -112,6 +113,9 @@ namespace ix
|
|||||||
uri = "/index.html";
|
uri = "/index.html";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WebSocketHttpHeaders headers;
|
||||||
|
headers["Server"] = userAgent();
|
||||||
|
|
||||||
std::string path("." + uri);
|
std::string path("." + uri);
|
||||||
auto res = readAsString(path);
|
auto res = readAsString(path);
|
||||||
bool found = res.first;
|
bool found = res.first;
|
||||||
@ -129,7 +133,6 @@ namespace ix
|
|||||||
<< request->uri << " " << content.size();
|
<< request->uri << " " << content.size();
|
||||||
logInfo(ss.str());
|
logInfo(ss.str());
|
||||||
|
|
||||||
WebSocketHttpHeaders headers;
|
|
||||||
// FIXME: check extensions to set the content type
|
// FIXME: check extensions to set the content type
|
||||||
// headers["Content-Type"] = "application/octet-stream";
|
// headers["Content-Type"] = "application/octet-stream";
|
||||||
headers["Accept-Ranges"] = "none";
|
headers["Accept-Ranges"] = "none";
|
||||||
@ -143,4 +146,36 @@ namespace ix
|
|||||||
200, "OK", HttpErrorCode::Ok, headers, content);
|
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
|
} // namespace ix
|
||||||
|
@ -34,6 +34,8 @@ namespace ix
|
|||||||
|
|
||||||
void setOnConnectionCallback(const OnConnectionCallback& callback);
|
void setOnConnectionCallback(const OnConnectionCallback& callback);
|
||||||
|
|
||||||
|
void makeRedirectServer(const std::string& redirectUrl);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Member variables
|
// Member variables
|
||||||
OnConnectionCallback _onConnectionCallback;
|
OnConnectionCallback _onConnectionCallback;
|
||||||
|
@ -69,6 +69,7 @@ namespace ix
|
|||||||
ss << " ";
|
ss << " ";
|
||||||
ss << reason;
|
ss << reason;
|
||||||
ss << "\r\n";
|
ss << "\r\n";
|
||||||
|
ss << "Server: " << userAgent() << "\r\n";
|
||||||
|
|
||||||
// Socket write can only be cancelled through a timeout here, not manually.
|
// Socket write can only be cancelled through a timeout here, not manually.
|
||||||
static std::atomic<bool> requestInitCancellation(false);
|
static std::atomic<bool> requestInitCancellation(false);
|
||||||
|
@ -62,4 +62,55 @@ TEST_CASE("http server", "[httpd]")
|
|||||||
|
|
||||||
server.stop();
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,33 +24,7 @@ namespace ix
|
|||||||
|
|
||||||
if (redirect)
|
if (redirect)
|
||||||
{
|
{
|
||||||
//
|
server.makeRedirectServer(redirectUrl);
|
||||||
// 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());
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto res = server.listen();
|
auto res = server.listen();
|
||||||
|
Loading…
Reference in New Issue
Block a user