s23-custom-methods.md 2.9 KB


title: "S23. Handle custom HTTP methods" order: 42

status: "draft"

The server rejects HTTP methods it does not know with 400 Bad Request. To accept an extension method, such as the WebDAV methods of RFC 4918 (PROPFIND, PROPPATCH, MKCOL and friends) or UPnP's SUBSCRIBE, register a handler with CustomRoute(). Registering the handler is what makes the server accept the method.

Basic usage

svr.CustomRoute("PROPFIND", "/dav/:id",
                [](const httplib::Request &req, httplib::Response &res) {
                  // The request body is available as usual
                  auto id = req.path_params.at("id");
                  res.status = httplib::StatusCode::MultiStatus_207;
                  res.set_content(build_multistatus(req.body), "application/xml");
                });

Patterns work the same way as they do for Get(). Regular expressions and path parameters are both available.

Advertise your methods with OPTIONS

A WebDAV client asks the server about its capabilities with OPTIONS before doing anything else. cpp-httplib generates neither the DAV: header nor Allow, so return them yourself. Forget this and clients will turn you away even though your PROPFIND works.

svr.Options("/dav/.*", [](const httplib::Request &req, httplib::Response &res) {
  res.set_header("DAV", "1");
  res.set_header("Allow", "OPTIONS, GET, HEAD, PROPFIND, PROPPATCH, MKCOL");
});

Read the body as a stream

There is a content reader overload, just like the one on Post(). Use it when you would rather not hold a large XML document in memory all at once.

svr.CustomRoute("REPORT", "/dav/.*",
                [](const httplib::Request &req, httplib::Response &res,
                   const httplib::ContentReader &content_reader) {
                  content_reader([&](const char *data, size_t data_length) {
                    // Process it a chunk at a time
                    return true;
                  });
                  res.status = httplib::StatusCode::MultiStatus_207;
                });

Things to keep in mind

  • The method name has to be a valid HTTP method token (RFC 9110), and it must be registered before you call listen()
  • GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE, PATCH and PRI cannot be registered here. Use the dedicated methods for those
  • A rejected registration makes is_valid() return false and listen() fail, so the server never starts holding a handler that would never run
  • Static file serving and WebSocket upgrades stay GET/HEAD only

Note: cpp-httplib takes you as far as routing the method. If you want to call it WebDAV, generating the 207 Multi-Status XML, interpreting the Depth header and managing locks are all yours to implement. The protocol itself lives outside the library.

For the basics of registering handlers, see S01. Register GET / POST / PUT / DELETE handlers.