From 6196a68239afbf946448c0ffd1f7c602f26a6ad0 Mon Sep 17 00:00:00 2001 From: Willem Kaufmann Date: Mon, 6 May 2024 19:55:10 -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 | 15 +++++++++++++-- src/http/routes.cc | 6 ++++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/include/seastar/http/exception.hh b/include/seastar/http/exception.hh index 048a9de42f7..759516464d8 100644 --- a/include/seastar/http/exception.hh +++ b/include/seastar/http/exception.hh @@ -65,10 +65,21 @@ 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()); + return reply; } std::string url; + std::optional retry_after; }; /** diff --git a/src/http/routes.cc b/src/http/routes.cc index 66d0f99e682..bd0cd08795d 100644 --- a/src/http/routes.cc +++ b/src/http/routes.cc @@ -73,8 +73,7 @@ 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(); } catch (const base_exception& e) { rep->set_status(e.status(), json_exception(e).to_json()); } catch (...) { @@ -94,6 +93,9 @@ 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(); + rep->done("json"); } catch (...) { rep = exception_reply(std::current_exception()); }