File Coverage

/usr/local/lib/perl5/site_perl/5.26.1/x86_64-linux/Protocol/HTTP.x/i/panda/protocol/http/Request.h
Criterion Covered Total %
statement 0 2 0.0
branch 0 2 0.0
condition n/a
subroutine n/a
pod n/a
total 0 4 0.0


line stmt bran cond sub pod time code
1             #pragma once
2             #include "Response.h"
3             #include
4             #include
5              
6             namespace panda { namespace protocol { namespace http {
7              
8              
9             struct Request : Message, AllocatedObject {
10             enum class Method {unspecified, OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT};
11             enum class EncType {MULTIPART, URLENCODED, disabled};
12             enum class FormStreaming { none, started, file, done };
13              
14             static inline string method_str(Request::Method rm) noexcept {
15             using Method = Request::Method;
16             switch (rm) {
17             case Method::unspecified : return "[unspecified]";
18             case Method::OPTIONS : return "OPTIONS";
19             case Method::GET : return "GET";
20             case Method::HEAD : return "HEAD";
21             case Method::POST : return "POST";
22             case Method::PUT : return "PUT";
23             case Method::DELETE : return "DELETE";
24             case Method::TRACE : return "TRACE";
25             case Method::CONNECT : return "CONNECT";
26             default: return "[UNKNOWN]";
27             }
28             }
29              
30             struct Builder; template struct BuilderImpl;
31             using Cookies = Fields;
32              
33             struct NamedString {
34             string value;
35             string name;
36             string content_type;
37             };
38              
39             struct Form: string_multimap {
40              
41 0           Form(EncType enc_type = EncType::disabled) noexcept :_enc_type(enc_type){}
42              
43             void enc_type (const EncType value) noexcept { _enc_type = value; }
44             EncType enc_type () const noexcept { return _enc_type; }
45              
46             operator bool () const noexcept { return _enc_type != EncType::disabled; }
47              
48             void add(const string& key, const string& value, const string& filename = "", const string content_type = "") {
49             insert({key, NamedString{value, filename, content_type}});
50             }
51              
52             private:
53             const URI* to_body (Body& body, uri::URI &uri, const URISP original_uri, const string& boundary) const noexcept;
54             void to_uri (URI& uri, const URISP original_uri) const ;
55             EncType _enc_type = EncType::MULTIPART;
56             friend struct Request;
57             };
58              
59              
60             URISP uri;
61             Cookies cookies;
62             Form form;
63              
64             compression::storage_t compression_prefs = Compression::IDENTITY;
65              
66 0 0         Request () {}
67              
68             Request (Method method, const URISP& uri, Headers&& header = Headers(), Body&& body = Body(), bool chunked = false, int http_version = 0) :
69             Message(std::move(header), std::move(body), chunked, http_version), uri(uri), _method(method)
70             {
71             }
72              
73             bool expects_continue () const;
74              
75             std::vector to_vector () const;
76             string to_string () const { return Message::to_string(to_vector()); }
77              
78             virtual ResponseSP new_response () const { return make_iptr(); }
79              
80              
81             template
82             void allow_compression (PrefN... prefn) {
83             return _allow_compression(prefn...);
84             }
85              
86             Method method() const noexcept;
87             Method method_raw() const noexcept { return _method; }
88              
89             void method_raw(Method value) noexcept { _method = value; }
90              
91             std::uint8_t allowed_compression (bool inverse = false) const noexcept;
92              
93             void form_stream() {
94             if (_form_streaming == FormStreaming::none) {
95             _form_streaming = FormStreaming::started;
96             form._enc_type = EncType::MULTIPART;
97             _form_boundary = _generate_boundary();
98             }
99             else if (_form_streaming != FormStreaming::started) {
100             throw "invalid state for form streaming";
101             }
102             }
103              
104             bool form_streaming() noexcept { return _form_streaming == FormStreaming::started; }
105              
106             wrapped_chunk form_finish();
107             wrapped_chunk form_field(const string& name, const string& content, const string& filename = "", const string& mime_type = "");
108             wrapped_chunk form_file(const string& name, const string filename = "", const string& mime_type = "application/octet-stream");
109             wrapped_chunk form_data(const string& data);
110              
111             protected:
112             struct SerializationContext: Message::SerializationContext {
113             const URI* uri;
114             };
115              
116             string form_trailer(const string& boundary) const noexcept {
117             auto sz = boundary.size() + 6;
118             string r(sz);
119             r += "--";
120             r += boundary;
121             r += "--\r\n";
122             return r;
123             }
124              
125             Method _method = Method::unspecified;
126             FormStreaming _form_streaming = FormStreaming::none;
127             string _form_boundary;
128              
129             template
130             void _allow_compression (Compression::Type p, PrefN... prefn) {
131             compression::pack(this->compression_prefs, p);
132             return _allow_compression(prefn...);
133             }
134             void _allow_compression () {}
135             void form_file_finalize(string& out) noexcept;
136              
137             ~Request () {} // restrict stack allocation
138              
139             private:
140             friend struct RequestParser;
141              
142             static Method deduce_method (bool has_form, EncType form_enc, Method _method) noexcept;
143             string _http_header (SerializationContext &ctx) const;
144             static string _generate_boundary() noexcept;
145             };
146             using RequestSP = iptr;
147              
148             template
149             struct Request::BuilderImpl : Message::Builder {
150             using Message::Builder::Builder;
151              
152             T& method (Request::Method method) {
153             this->_message->method_raw(method);
154             return this->self();
155             }
156              
157             T& uri (const string& uri) {
158             this->_message->uri = new URI(uri);
159             return this->self();
160             }
161              
162             T& uri (const URISP& uri) {
163             this->_message->uri = uri;
164             return this->self();
165             }
166              
167             T& cookie (const string& name, const string& value) {
168             this->_message->cookies.add(name, value);
169             return this->self();
170             }
171              
172             template
173             T& allow_compression(PrefN... prefn) {
174             this->_message->allow_compression(prefn...);
175             return this->self();
176             }
177              
178             template
179             T& form(Form&& form) {
180             this->_message->form = std::forward
(form);
181             return this->self();
182             }
183              
184             T& form_stream() {
185             this->_message->form_stream();
186             return this->self();
187             }
188             };
189              
190             struct Request::Builder : Request::BuilderImpl {
191             Builder () : BuilderImpl(new Request()) {}
192             };
193              
194             }}}