Files
cpp-httplib/docs-src/pages/en/cookbook/s10-post-routing.md
T
yhirose 9bfd2ddf1c Fix README and docs pages that no longer match the code
Bring the READMEs and the docs pages (en and ja) in line with the
current header:

- Fix the client sample that does not compile, the Transfer-Encoding
  statement for default headers, the verifier callback comment, the
  thread pool spawn rule, the sanitize_filename description, and the
  inverted Accept-Encoding sentence.
- Describe recent behaviour: TLS errors behind Read/Write failures,
  Host validation, Connection: close for a body without length,
  content_reader rules, refused CONNECT, WebSocketClient proxies,
  CPPHTTPLIB_INTERIM_RESPONSE_MAX_COUNT, the SSE event size limit, and
  the payload limit of the Stream API.
- Complete the API references of WebSocket, WebSocketClient and the
  stream:: helpers, and the SSE reconnect rules.
- Fix cookbook pages: keychain loading on every backend, received Close
  status, a multipart sample that trusted the client's file name, an
  echo sample that sent binary as text, SNI, pre-request handler scope,
  stop() with WebSocket handlers, and the thread pool notes.
- Restore the mutex in the LLM app's Chapter 5 code.
2026-10-18 10:13:57 -04:00

2.1 KiB

title, order, status
title order status
S10. Add Response Headers with a Post-Routing Handler 29 draft

Sometimes you want to add shared headers to the response after the handler has run — CORS headers, security headers, a request ID, and so on. That's what set_post_routing_handler() is for.

Basic usage

svr.set_post_routing_handler(
  [](const httplib::Request &req, httplib::Response &res) {
    res.set_header("X-Request-ID", generate_request_id());
  });

The post-routing handler runs after the route handler, before the response is sent. From here you can call res.set_header() or res.headers.erase() to add or remove headers across every response in one place.

Add CORS headers

CORS is a classic use case.

svr.set_post_routing_handler(
  [](const httplib::Request &req, httplib::Response &res) {
    res.set_header("Access-Control-Allow-Origin", "*");
    res.set_header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
    res.set_header("Access-Control-Allow-Headers", "Content-Type, Authorization");
  });

For the preflight OPTIONS requests, register a separate handler — or handle them in the pre-routing handler.

svr.Options("/.*", [](const auto &req, auto &res) {
  res.status = 204;
});

/.* is a regex route, so it isn't applied to paths longer than CPPHTTPLIB_REGEX_ROUTE_PATH_MAX_LENGTH (256 by default). If your paths can be longer, handle OPTIONS in the pre-routing handler instead.

Bundle your security headers

Manage browser security headers in one spot.

svr.set_post_routing_handler(
  [](const httplib::Request &req, httplib::Response &res) {
    res.set_header("X-Content-Type-Options", "nosniff");
    res.set_header("X-Frame-Options", "DENY");
    res.set_header("Referrer-Policy", "strict-origin-when-cross-origin");
  });

No matter which handler produced the response, the same headers get attached.

Note: The post-routing handler also runs for responses that didn't match any route and for responses from error handlers. That's exactly what you want when you need certain headers on every response, guaranteed.