virthttp  0.0
libvirt http interface
compression.hpp
Go to the documentation of this file.
1 #pragma once
2 #include <charconv>
3 #include <cstring>
4 #include <string>
5 #include <boost/beast.hpp>
6 #include <ctre.hpp>
7 #include <flatmap.hpp>
8 #include "libdeflate.hpp"
9 
14 enum class Algs {
15  // compress, // unsupported
16  deflate,
17  gzip,
18  identity,
19  // br, // unsupported
20 };
21 
26 constexpr static ctll::fixed_string weigthed_encodings_pattern = R"(([a-z]+|\*)(?:;q=([0-1].?(?:[\d]+)?)?)?(?:,\s*)?)";
27 
38 template <class Allocator>
39 bool handle_compression(const boost::beast::http::basic_fields<Allocator>& in_head, boost::beast::http::basic_fields<Allocator>& out_head,
40  std::string& body) {
43  const auto in_algs = in_head[boost::beast::http::field::accept_encoding];
44  if (in_algs.empty())
45  return true;
46  flatmap<std::string_view, float> accepted_values;
47  for (auto [full, name, weight] : ctre::range<weigthed_encodings_pattern>(in_algs)) {
48  float w = 1;
49  if (weight) {
50  const std::string w_str = {weight.to_view().data(), weight.to_view().size()};
51  w = std::atof(w_str.c_str());
52  // at time of writing, only MSVC has a std::from_chars implementation for floating points
53  // std::from_chars(weight.begin(), weight.end(), w);
54  }
55  accepted_values[name.to_view()] = w;
56  }
57 
58  /*
59  * https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding:
60  * As long as the identity value, meaning no encoding, is not explicitly forbidden, by an identity;q=0 or a *;q=0 without another explicitly set
61  * value for identity, the server must never send back a 406 Not Acceptable error.
62  * */
63  if (const auto it = accepted_values.find("identity"sv); it != accepted_values.end() && it->second == 0.0f)
64  return false;
65 
66  // Hack; waiting for C++2a
67  if (const auto it = accepted_values.find("gzip"sv); it != accepted_values.end()) {
68  const auto res = libdeflate::compress(body, libdeflate::Mode::gzip);
69  if (res)
70  out_head.set(boost::beast::http::field::content_encoding, "gzip");
71  return res;
72  }
73  if (const auto it = accepted_values.find("deflate"sv); it != accepted_values.end()) {
74  const auto res = libdeflate::compress(body, libdeflate::Mode::zlib);
75  if (res)
76  out_head.set(boost::beast::http::field::content_encoding, "deflate");
77  return res;
78  }
79 
80  return true;
81 }
Algs
Definition: compression.hpp:14
static constexpr ctll::fixed_string weigthed_encodings_pattern
Definition: compression.hpp:26
bool handle_compression(const boost::beast::http::basic_fields< Allocator > &in_head, boost::beast::http::basic_fields< Allocator > &out_head, std::string &body)
Definition: compression.hpp:39
bool compress(std::string &body, Mode mode) noexcept
Definition: libdeflate.hpp:12