diff --git a/include/fastly/http/response.h b/include/fastly/http/response.h index efeeeb2..97b9f5c 100644 --- a/include/fastly/http/response.h +++ b/include/fastly/http/response.h @@ -308,6 +308,18 @@ class Response { fastly::expected> remove_header(std::string_view name); + /// Get the HTTP status code of the response. + /// + /// # Examples + /// + /// ```cpp + /// auto resp{fastly::Response::from_status( + /// fastly::http::StatusCode::NOT_FOUND)}; + /// assert(resp.get_status() == fastly::http::StatusCode::NOT_FOUND); + /// assert(resp.get_status().as_code() == 404); + /// ``` + StatusCode get_status(); + /// Builder-style equivalent of `Response::set_status()`. Response with_status(StatusCode status) &&; diff --git a/include/fastly/http/status_code.h b/include/fastly/http/status_code.h index 6537df5..1458df7 100644 --- a/include/fastly/http/status_code.h +++ b/include/fastly/http/status_code.h @@ -276,7 +276,7 @@ class StatusCode { /// The method validates the correctness of the supplied uint16_t. It must be /// greater or equal to 100 and less than 1000, or this method will return /// `std::nullopt`. - std::optional from_code(uint16_t code); + static std::optional from_code(uint16_t code); /// Returns the `uint16_t` corresponding to this `StatusCode`. uint16_t as_code(); diff --git a/src/cpp/http/response.cpp b/src/cpp/http/response.cpp index e6a8456..bc78e96 100644 --- a/src/cpp/http/response.cpp +++ b/src/cpp/http/response.cpp @@ -257,6 +257,10 @@ Response::remove_header(std::string_view name) { } } +StatusCode Response::get_status() { + return StatusCode(this->res->get_status()); +} + void Response::set_status(StatusCode status) { this->res->set_status(status.as_code()); } diff --git a/src/http/response.rs b/src/http/response.rs index 2dff3e9..5573294 100644 --- a/src/http/response.rs +++ b/src/http/response.rs @@ -204,6 +204,10 @@ impl Response { .is_some() } + pub fn get_status(&self) -> u16 { + self.0.get_status().as_u16() + } + pub fn set_status(&mut self, status: u16) { self.0.set_status(status); } diff --git a/src/lib.rs b/src/lib.rs index 2ec01d3..0bf65ca 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -645,6 +645,7 @@ mod ffi { out: Pin<&mut CxxString>, mut err: Pin<&mut *mut FastlyError>, ) -> bool; + fn get_status(&self) -> u16; fn set_status(&mut self, status: u16); fn get_backend_name(&self, out: Pin<&mut CxxString>) -> bool; fn get_backend(&self) -> *mut Backend; diff --git a/test/response.cpp b/test/response.cpp new file mode 100644 index 0000000..45f8ecc --- /dev/null +++ b/test/response.cpp @@ -0,0 +1,48 @@ +#include +#include +#include + +using namespace fastly::http; + +TEST_CASE("Response::get_status", "[response]") { + SECTION("new responses default to 200 OK") { + Response resp; + REQUIRE(resp.get_status().as_code() == 200); + REQUIRE(resp.get_status() == StatusCode::OK); + } + + SECTION("round-trips from_status") { + REQUIRE(Response::from_status(404).get_status().as_code() == 404); + REQUIRE(Response::from_status(StatusCode::NOT_FOUND).get_status() == + StatusCode::NOT_FOUND); + } + + SECTION("reflects set_status") { + Response resp; + resp.set_status(StatusCode::IM_A_TEAPOT); + REQUIRE(resp.get_status().as_code() == 418); + } + + SECTION("reflects with_status") { + auto resp{Response().with_status(StatusCode::SERVICE_UNAVAILABLE)}; + REQUIRE(resp.get_status().as_code() == 503); + } + + SECTION("interoperates with StatusCode helpers") { + REQUIRE(Response::from_status(204).get_status().is_success()); + REQUIRE(Response::from_status(StatusCode::PERMANENT_REDIRECT) + .get_status() + .is_redirection()); + REQUIRE(Response::from_status(500).get_status().is_server_error()); + } +} + +TEST_CASE("StatusCode::from_code", "[response]") { + REQUIRE(StatusCode::from_code(404) == std::optional(StatusCode::NOT_FOUND)); + REQUIRE(StatusCode::from_code(99) == std::nullopt); + REQUIRE(StatusCode::from_code(1000) == std::nullopt); +} + +// Required due to https://github.com/WebAssembly/wasi-libc/issues/485 +#include +int main(int argc, char *argv[]) { return Catch::Session().run(argc, argv); }