-
Notifications
You must be signed in to change notification settings - Fork 191
Expand file tree
/
Copy pathhttp_resource.hpp
More file actions
239 lines (207 loc) · 8.08 KB
/
Copy pathhttp_resource.hpp
File metadata and controls
239 lines (207 loc) · 8.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
/*
This file is part of libhttpserver
Copyright (C) 2011-2019 Sebastiano Merlino
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#if !defined (_HTTPSERVER_HPP_INSIDE_) && !defined (HTTPSERVER_COMPILATION)
#error "Only <httpserver.hpp> or <httpserverpp> can be included directly."
#endif
#ifndef SRC_HTTPSERVER_HTTP_RESOURCE_HPP_
#define SRC_HTTPSERVER_HTTP_RESOURCE_HPP_
// TASK-036: render_* virtuals now return http_response by value; the
// inline defaults call render(req) and forward the prvalue, which
// requires http_response to be a complete type at every override site.
// Hard-include is the simplest correct shape (the umbrella already
// reaches both headers).
#include "httpserver/http_method.hpp"
#include "httpserver/http_response.hpp"
namespace httpserver { class http_request; }
namespace httpserver { class webserver; }
namespace httpserver { namespace detail { class webserver_impl; } }
namespace httpserver {
// TASK-036 / DR-004 / PRD-RSP-REQ-007: render_* virtuals return
// http_response by value. The webserver dispatch path moves the value
// into mr->response_ (an std::optional<http_response> living on the
// per-connection modded_request, see §5.3) and keeps it alive until
// MHD fires request_completed. The default render() returns a
// default-constructed http_response whose status_code_ == -1 is the
// v1-compatible sentinel for "handler did not produce a response"; the
// dispatch path routes the sentinel through the internal-error handler.
/**
* Class representing a callable http resource.
**/
class http_resource {
public:
/**
* Class destructor
**/
virtual ~http_resource() = default;
/**
* Method used to answer to a generic request
* @param req Request passed through http
* @return A http_response object
**/
virtual http_response render(const http_request& req) {
(void)req;
// TASK-036: default-constructed http_response carries
// status_code_ == -1 — the v1-compatible "handler did not
// produce a response" sentinel that finalize_answer recognises
// and routes through internal_error_page (see
// test/integ/basic.cpp::default_render_method).
return http_response{};
}
/**
* Method used to answer to a GET request
* @param req Request passed through http
* @return A http_response object
**/
virtual http_response render_get(const http_request& req) {
return render(req);
}
/**
* Method used to answer to a POST request
* @param req Request passed through http
* @return A http_response object
**/
virtual http_response render_post(const http_request& req) {
return render(req);
}
/**
* Method used to answer to a PUT request
* @param req Request passed through http
* @return A http_response object
**/
virtual http_response render_put(const http_request& req) {
return render(req);
}
/**
* Method used to answer to a HEAD request
* @param req Request passed through http
* @return A http_response object
**/
virtual http_response render_head(const http_request& req) {
return render(req);
}
/**
* Method used to answer to a DELETE request
* @param req Request passed through http
* @return A http_response object
**/
virtual http_response render_delete(const http_request& req) {
return render(req);
}
/**
* Method used to answer to a TRACE request
* @param req Request passed through http
* @return A http_response object
**/
virtual http_response render_trace(const http_request& req) {
return render(req);
}
/**
* Method used to answer to a OPTIONS request
* @param req Request passed through http
* @return A http_response object
**/
virtual http_response render_options(const http_request& req) {
return render(req);
}
/**
* Method used to answer to a PATCH request
* @param req Request passed through http
* @return A http_response object
**/
virtual http_response render_patch(const http_request& req) {
return render(req);
}
/**
* Method used to answer to a CONNECT request
* @param req Request passed through http
* @return A http_response object
**/
virtual http_response render_connect(const http_request& req) {
return render(req);
}
/**
* Toggle whether a specific http_method is allowed on this resource.
* @param method enum identifying the method (no string lookup)
* @param allow true to enable the method, false to disable it
**/
void set_allowing(http_method method, bool allow) noexcept {
if (method == http_method::count_) return; // sentinel; never settable
if (allow) {
methods_allowed_.set(method);
} else {
methods_allowed_.clear(method);
}
}
/**
* Allow every defined http_method on this resource.
**/
void allow_all() noexcept {
methods_allowed_.set_all();
}
/**
* Disallow every http_method on this resource.
**/
void disallow_all() noexcept {
methods_allowed_.clear_all();
}
/**
* Test whether `method` is allowed on this resource. Const-noexcept
* because the answer is a single bitmask test on a trivial member;
* no string lookup, no allocation.
* @param method enum identifying the method to query
* @return true if the method is currently allowed
**/
bool is_allowed(http_method method) const noexcept {
return methods_allowed_.contains(method);
}
/**
* Return the full allow-mask by value. The returned method_set is
* trivially copyable (sizeof == 4) so by-value is the natural ABI.
**/
method_set get_allowed_methods() const noexcept {
return methods_allowed_;
}
protected:
/**
* Constructor of the class. The default state allows every defined
* http_method, matching the v1 behaviour where `resource_init`
* marked all nine methods true.
**/
http_resource() = default;
/**
* Copy / move special members are trivial — the only data member
* is method_set (a 32-bit aggregate).
**/
http_resource(const http_resource& b) = default;
http_resource(http_resource&& b) noexcept = default;
http_resource& operator=(const http_resource& b) = default;
http_resource& operator=(http_resource&& b) = default;
private:
friend class webserver;
friend class detail::webserver_impl; // TASK-014: dispatch helpers
// Default-allow every valid method. method_set::set_all() is
// constexpr, so the chained call is a constant expression and the
// default member initialiser stays well-formed.
method_set methods_allowed_ = method_set{}.set_all();
};
// TASK-021 acceptance: http_resource is now a vptr plus a 32-bit
// method_set plus padding. The cap below leaves headroom for one
// future small member (e.g. an arena tag) without re-invalidating
// PRD-REQ-REQ-002 / PRD-REQ-REQ-003.
static_assert(sizeof(http_resource) <= sizeof(void*) + sizeof(method_set) * 2,
"http_resource should be approximately vptr + method_set");
} // namespace httpserver
#endif // SRC_HTTPSERVER_HTTP_RESOURCE_HPP_