From 6a41444c3ed98acbcc95e942d0998b933df2c046 Mon Sep 17 00:00:00 2001 From: Willem Kaufmann Date: Tue, 30 Apr 2024 15:25:31 -0400 Subject: [PATCH] http: add `to_reply()` in `httpd::redirect_exception` This function allows for the creation of an `http::reply` from a thrown `redirect_exception`, with a url for the `Location` header and an optional `Retry-After` timeout value. --- include/seastar/http/exception.hh | 16 ++++++++++++++-- src/http/routes.cc | 6 ++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/include/seastar/http/exception.hh b/include/seastar/http/exception.hh index 048a9de42f7..f03ee42441c 100644 --- a/include/seastar/http/exception.hh +++ b/include/seastar/http/exception.hh @@ -65,10 +65,22 @@ private: */ class redirect_exception : public base_exception { public: - redirect_exception(const std::string& url, http::reply::status_type status = http::reply::status_type::moved_permanently) - : base_exception("", status), url(url) { + redirect_exception(const std::string& url, http::reply::status_type status = http::reply::status_type::moved_permanently, const std::optional& retry_after = std::nullopt) + : base_exception("", status), url(url), retry_after(retry_after) { } + + http::reply to_reply() const { + http::reply reply{}; + reply.add_header("Location", url); + if (retry_after.has_value()) { + reply.add_header("Retry-After", std::to_string(retry_after.value())); + } + reply.set_status(status()).done("json"); + return reply; + } + std::string url; + std::optional retry_after; }; /** diff --git a/src/http/routes.cc b/src/http/routes.cc index 66d0f99e682..35135299131 100644 --- a/src/http/routes.cc +++ b/src/http/routes.cc @@ -73,8 +73,8 @@ std::unique_ptr routes::exception_reply(std::exception_ptr eptr) { } std::rethrow_exception(eptr); } catch (const redirect_exception& _e) { - rep.reset(new http::reply()); - rep->add_header("Location", _e.url).set_status(_e.status()); + *rep = _e.to_reply(); + return rep; } catch (const base_exception& e) { rep->set_status(e.status(), json_exception(e).to_json()); } catch (...) { @@ -94,6 +94,8 @@ future > routes::handle(const sstring& path, std::u handler->verify_mandatory_params(*req); auto r = handler->handle(path, std::move(req), std::move(rep)); return r.handle_exception(_general_handler); + } catch (const redirect_exception& _e) { + *rep = _e.to_reply(); } catch (...) { rep = exception_reply(std::current_exception()); }