Skip to content

Commit 1f958f9

Browse files
authored
Extend serve_file to take a custom HTTP status code (#198)
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
1 parent c8f550c commit 1f958f9

File tree

4 files changed

+47
-4
lines changed

4 files changed

+47
-4
lines changed

src/httpserver/include/sourcemeta/hydra/httpserver.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ class SOURCEMETA_HYDRA_HTTPSERVER_EXPORT Server {
226226
/// ```
227227
auto SOURCEMETA_HYDRA_HTTPSERVER_EXPORT
228228
serve_file(const std::filesystem::path &file_path, const ServerRequest &request,
229-
ServerResponse &response) -> void;
229+
ServerResponse &response, const Status code = Status::OK) -> void;
230230

231231
} // namespace sourcemeta::hydra::http
232232

src/httpserver/static.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
namespace sourcemeta::hydra::http {
1010

1111
auto serve_file(const std::filesystem::path &file_path,
12-
const ServerRequest &request, ServerResponse &response)
13-
-> void {
12+
const ServerRequest &request, ServerResponse &response,
13+
const Status code) -> void {
1414
assert(request.method() == sourcemeta::hydra::http::Method::GET ||
1515
request.method() == sourcemeta::hydra::http::Method::HEAD);
1616

@@ -48,7 +48,7 @@ auto serve_file(const std::filesystem::path &file_path,
4848
return;
4949
}
5050

51-
response.status(sourcemeta::hydra::http::Status::OK);
51+
response.status(code);
5252
response.header("Content-Type", sourcemeta::hydra::mime_type(file_path));
5353
response.header_etag(etag.str());
5454
response.header_last_modified(last_modified);

test/e2e/httpserver/httpserver_test.cc

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -943,6 +943,31 @@ TEST(e2e_HTTP_Server, static_document_get) {
943943
EXPECT_EQ(result.str(), "{ \"foo\": \"bar\" }\n");
944944
}
945945

946+
TEST(e2e_HTTP_Server, static_document_get_with_code_override) {
947+
sourcemeta::hydra::http::ClientRequest request{
948+
std::string{HTTPSERVER_BASE_URL()} + "/static-404/document.json"};
949+
request.method(sourcemeta::hydra::http::Method::GET);
950+
request.capture();
951+
sourcemeta::hydra::http::ClientResponse response{request.send().get()};
952+
EXPECT_EQ(response.status(), sourcemeta::hydra::http::Status::NOT_FOUND);
953+
EXPECT_TRUE(response.header("content-length").has_value());
954+
EXPECT_EQ(response.header("content-length").value(), "37");
955+
EXPECT_TRUE(response.header("content-type").has_value());
956+
EXPECT_EQ(response.header("content-type").value(), "application/json");
957+
EXPECT_TRUE(response.header("last-modified").has_value());
958+
EXPECT_TRUE(response.header("etag").has_value());
959+
EXPECT_EQ(response.header("etag").value(),
960+
"\"cef8a5c5d7fcfb9cf601bf3a146a47e7\"");
961+
962+
std::ostringstream result;
963+
std::copy(
964+
std::istreambuf_iterator<std::ostringstream::char_type>(response.body()),
965+
std::istreambuf_iterator<std::ostringstream::char_type>(),
966+
std::ostreambuf_iterator<std::ostringstream::char_type>(result));
967+
968+
EXPECT_EQ(result.str(), "{ \"foo\": \"bar\" }\n");
969+
}
970+
946971
TEST(e2e_HTTP_Server, static_document_head) {
947972
sourcemeta::hydra::http::ClientRequest request{
948973
std::string{HTTPSERVER_BASE_URL()} + "/static/document.json"};

test/e2e/httpserver/stub.cc

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,22 @@ static auto on_static(const sourcemeta::hydra::http::ServerLogger &,
198198
sourcemeta::hydra::http::serve_file(file_path, request, response);
199199
}
200200

201+
static auto on_static_404(const sourcemeta::hydra::http::ServerLogger &,
202+
const sourcemeta::hydra::http::ServerRequest &request,
203+
sourcemeta::hydra::http::ServerResponse &response)
204+
-> void {
205+
const std::filesystem::path file_path{STATIC_PATH +
206+
request.path().substr(11)};
207+
if (!std::filesystem::exists(file_path)) {
208+
response.status(sourcemeta::hydra::http::Status::NOT_FOUND);
209+
response.end();
210+
return;
211+
}
212+
213+
sourcemeta::hydra::http::serve_file(
214+
file_path, request, response, sourcemeta::hydra::http::Status::NOT_FOUND);
215+
}
216+
201217
static auto on_error(std::exception_ptr error,
202218
const sourcemeta::hydra::http::ServerLogger &,
203219
const sourcemeta::hydra::http::ServerRequest &,
@@ -246,6 +262,8 @@ auto main(int argc, char *argv[]) -> int {
246262
server.route(sourcemeta::hydra::http::Method::POST, "/cache-me", on_cache_me);
247263
server.route(sourcemeta::hydra::http::Method::GET, "/etag-quoted",
248264
on_etag_quoted);
265+
server.route(sourcemeta::hydra::http::Method::GET, "/static-404/*",
266+
on_static_404);
249267
server.route(sourcemeta::hydra::http::Method::GET, "/static/*", on_static);
250268
server.route(sourcemeta::hydra::http::Method::HEAD, "/static/*", on_static);
251269

0 commit comments

Comments
 (0)