Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extending response_builder_t<restinio_controlled_output_t> #122

Open
prince-chrismc opened this issue Aug 10, 2020 · 2 comments
Open

Extending response_builder_t<restinio_controlled_output_t> #122

prince-chrismc opened this issue Aug 10, 2020 · 2 comments

Comments

@prince-chrismc
Copy link
Contributor

Would it be possible to to extend the template specialization in order to add custom methods and/or default behavior to the constructor?

There's a lot of boiler plate between create_response() and done(), for example:

restinio::request_handling_status_t edit::operator()(const restinio::request_handle_t &req, restinio::router::route_params_t params) {
  auto &user = list_.get(restinio::cast_to<int>(params["id"]));
  user_management::user_modifier(user).apply(nlohmann::json::parse(req->body()));

  return req->create_response()
      .append_header(restinio::http_field::access_control_allow_origin, "*") // Added on every request
      // More CORS Headers...
      .append_header(restinio::http_field::content_type, "application/json") // Always true
      // Date, Last-Modified, ETag, Accept-Patch ... etc...
      .set_body(nlohmann::json(user).dump()) // This is a typical JSON API, it would be nice to have handlers for my custom types
      .done();
}

Now it would be very easy to have...

restinio::request_handling_status_t edit::operator()(const restinio::request_handle_t &req, restinio::router::route_params_t params) {
  auto &user = list_.get(restinio::cast_to<int>(params["id"]));
  user_management::user_modifier(user).apply(nlohmann::json::parse(req->body()));

  return add_edit_hedaers(add_api_headers(add_cors_headers(req->create_response())))
      .set_body(nlohmann::json(user).dump())
      .done();
}

What I would love to have...

restinio::request_handling_status_t edit::operator()(const restinio::request_handle_t &req, restinio::router::route_params_t params) {
  auto &user = list_.get(restinio::cast_to<int>(params["id"]));
  user_management::user_modifier(user).apply(nlohmann::json::parse(req->body()));

  return req->create_response<edit_response_builder>()
      .set_body(user)
      .done();
}

This begs the question

Why is this class marked final?

template <>
class response_builder_t< restinio_controlled_output_t > final
: public base_response_builder_t< response_builder_t< restinio_controlled_output_t > >

@eao197
Copy link
Member

eao197 commented Aug 10, 2020

Response builders use inheritance only to avoid code duplication. Because of that response_builder_t<T> is not designed to be used in class hierarchies.

I think your case can be solved by using your own response-builder class like that:

class edit_response_builder {
  restinio::response_builder_t<restinio::restinio_controlled_output_t> builder_;
...
public:
  edit_response_builder(restinio::request_t & req) : builder_{req.create_response()} {
    add_cors_headers(builder_);
    add_api_headers(builder_);
    add_edit_headers(builder_);
  }
  ...
  edit_response_builder & set_body(std::string body) {
    builder_.set_body(std::move(body));
    return *this;
  }
  auto done() { return builder_.done(); }
};
...
restinio::request_handling_status_t edit::operator()(const restinio::request_handle_t &req, restinio::router::route_params_t params) {
  auto &user = list_.get(restinio::cast_to<int>(params["id"]));
  user_management::user_modifier(user).apply(nlohmann::json::parse(req->body()));

  return edit_response_builder{*req}
      .set_body(user)
      .done();
}

@prince-chrismc
Copy link
Contributor Author

Typically templates are not bothered by inheritance. 🤔

That's a very interesting solution, I'll give it a shot!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants