drogon
C++14/17-based HTTP application framework
Loading...
Searching...
No Matches
HttpResponse.h
Go to the documentation of this file.
1
13
14#pragma once
15
16#include <drogon/exports.h>
17#include <trantor/net/Certificate.h>
18#include <trantor/net/callbacks.h>
19#include <trantor/net/AsyncStream.h>
20#include <drogon/DrClassMap.h>
21#include <drogon/Cookie.h>
22#include <drogon/HttpRequest.h>
23#include <drogon/HttpTypes.h>
24#include <drogon/HttpViewData.h>
26#include <json/json.h>
27#include <memory>
28#include <string>
29#include <string_view>
30
31namespace drogon
32{
34class HttpResponse;
35using HttpResponsePtr = std::shared_ptr<HttpResponse>;
36
41template <typename T>
43{
44 LOG_ERROR
45 << "You must specialize the fromResponse template for the type of "
46 << DrClassMap::demangle(typeid(T).name());
47 exit(1);
48}
49
55template <typename T>
56HttpResponsePtr toResponse(T &&)
57{
58 LOG_ERROR << "You must specialize the toResponse template for the type of "
59 << DrClassMap::demangle(typeid(T).name());
60 exit(1);
61}
62
63template <>
64HttpResponsePtr toResponse<const Json::Value &>(const Json::Value &pJson);
65template <>
66HttpResponsePtr toResponse(Json::Value &&pJson);
67
68template <>
69inline HttpResponsePtr toResponse<Json::Value &>(Json::Value &pJson)
70{
71 return toResponse((const Json::Value &)pJson);
72}
73
74class DROGON_EXPORT ResponseStream
75{
76 public:
77 explicit ResponseStream(trantor::AsyncStreamPtr asyncStream)
78 : asyncStream_(std::move(asyncStream))
79 {
80 }
81
82 ~ResponseStream()
83 {
84 close();
85 }
86
87 bool send(const std::string &data)
88 {
89 if (!asyncStream_)
90 {
91 return false;
92 }
93 std::ostringstream oss;
94 oss << std::hex << data.length() << "\r\n";
95 oss << data << "\r\n";
96 return asyncStream_->send(oss.str());
97 }
98
99 void close()
100 {
101 if (asyncStream_)
102 {
103 static std::string closeStream{"0\r\n\r\n"};
104 asyncStream_->send(closeStream);
105 asyncStream_->close();
106 asyncStream_.reset();
107 }
108 }
109
110 private:
111 trantor::AsyncStreamPtr asyncStream_;
112};
113
114using ResponseStreamPtr = std::unique_ptr<ResponseStream>;
115
116class DROGON_EXPORT HttpResponse
117{
118 public:
131 template <typename T>
132 operator T() const
133 {
134 return fromResponse<T>(*this);
135 }
136
141 template <typename T>
142 T as() const
143 {
144 return fromResponse<T>(*this);
145 }
146
148 virtual HttpStatusCode statusCode() const = 0;
149
150 HttpStatusCode getStatusCode() const
151 {
152 return statusCode();
153 }
154
156 virtual void setStatusCode(HttpStatusCode code) = 0;
157
158 void setCustomStatusCode(int code,
159 std::string_view message = std::string_view{})
160 {
161 setCustomStatusCode(code, message.data(), message.length());
162 }
163
165 virtual void setAllowCompression(bool allow) = 0;
166
168 virtual bool allowCompression() const = 0;
169
171 virtual const trantor::Date &creationDate() const = 0;
172
173 const trantor::Date &getCreationDate() const
174 {
175 return creationDate();
176 }
177
179 virtual void setVersion(const Version v) = 0;
180
182
188 virtual void setCloseConnection(bool on) = 0;
189
191 virtual bool ifCloseConnection() const = 0;
192
196 virtual void setContentTypeCode(ContentType type) = 0;
197
201 void setContentTypeString(const std::string_view &typeString)
202 {
203 setContentTypeString(typeString.data(), typeString.size());
204 }
205
210 const std::string_view &typeString)
211 {
213 typeString.data(),
214 typeString.length());
215 }
216
217 template <int N>
218 void setContentTypeCodeAndCustomString(ContentType type,
219 const char (&typeString)[N])
220 {
221 assert(N > 0);
222 setContentTypeCodeAndCustomString(type, typeString, N - 1);
223 }
224
228
230 virtual ContentType contentType() const = 0;
231
232 ContentType getContentType() const
233 {
234 return contentType();
235 }
236
238
243 virtual const std::string &getHeader(std::string key) const = 0;
244
250 virtual void removeHeader(std::string key) = 0;
251
253 virtual const SafeStringMap<std::string> &headers() const = 0;
254
256 const SafeStringMap<std::string> &getHeaders() const
257 {
258 return headers();
259 }
260
268 virtual void addHeader(std::string field, const std::string &value) = 0;
269 virtual void addHeader(std::string field, std::string &&value) = 0;
270
272 virtual void addCookie(const std::string &key,
273 const std::string &value) = 0;
274
276 virtual void addCookie(const Cookie &cookie) = 0;
277 virtual void addCookie(Cookie &&cookie) = 0;
278
281 virtual const Cookie &getCookie(const std::string &key) const = 0;
282
284 virtual const SafeStringMap<Cookie> &cookies() const = 0;
285
287 const SafeStringMap<Cookie> &getCookies() const
288 {
289 return cookies();
290 }
291
293 virtual void removeCookie(const std::string &key) = 0;
294
296
299 virtual void setBody(const std::string &body) = 0;
300
302 virtual void setBody(std::string &&body) = 0;
303
305 template <int N>
306 void setBody(const char (&body)[N])
307 {
308 assert(strnlen(body, N) == N - 1);
309 setBody(body, N - 1);
310 }
311
313 std::string_view body() const
314 {
315 return std::string_view{getBodyData(), getBodyLength()};
316 }
317
319 std::string_view getBody() const
320 {
321 return body();
322 }
323
326 virtual const char *versionString() const = 0;
327
328 const char *getVersionString() const
329 {
330 return versionString();
331 }
332
334
338 virtual Version version() const = 0;
339
341 Version getVersion() const
342 {
343 return version();
344 }
345
347 virtual void clear() = 0;
348
352 virtual void setExpiredTime(ssize_t expiredTime) = 0;
353
355 virtual ssize_t expiredTime() const = 0;
356
357 ssize_t getExpiredTime() const
358 {
359 return expiredTime();
360 }
361
365 virtual const std::shared_ptr<Json::Value> &jsonObject() const = 0;
366
367 const std::shared_ptr<Json::Value> &getJsonObject() const
368 {
369 return jsonObject();
370 }
371
380 virtual const std::string &getJsonError() const = 0;
381
391 virtual void setPassThrough(bool flag) = 0;
392
397 virtual const trantor::CertificatePtr &peerCertificate() const = 0;
398
399 const trantor::CertificatePtr &getPeerCertificate() const
400 {
401 return peerCertificate();
402 }
403
404 /* The following methods are a series of factory methods that help users
405 * create response objects. */
406
409 static HttpResponsePtr newHttpResponse();
411 static HttpResponsePtr newHttpResponse(HttpStatusCode code,
412 ContentType type);
414 static HttpResponsePtr newNotFoundResponse(
415 const HttpRequestPtr &req = HttpRequestPtr());
418 static HttpResponsePtr newHttpJsonResponse(const Json::Value &data);
421 static HttpResponsePtr newHttpJsonResponse(Json::Value &&data);
424
429 static HttpResponsePtr newHttpViewResponse(
430 const std::string &viewName,
431 const HttpViewData &data = HttpViewData(),
432 const HttpRequestPtr &req = HttpRequestPtr());
433
436
441 static HttpResponsePtr newRedirectionResponse(
442 const std::string &location,
443 HttpStatusCode status = k302Found);
444
446
455 static HttpResponsePtr newFileResponse(
456 const std::string &fullPath,
457 const std::string &attachmentFileName = "",
458 ContentType type = CT_NONE,
459 const std::string &typeString = "",
460 const HttpRequestPtr &req = HttpRequestPtr());
461
463
479 static HttpResponsePtr newFileResponse(
480 const std::string &fullPath,
481 size_t offset,
482 size_t length,
483 bool setContentRange = true,
484 const std::string &attachmentFileName = "",
485 ContentType type = CT_NONE,
486 const std::string &typeString = "",
487 const HttpRequestPtr &req = HttpRequestPtr());
488
491
501 static HttpResponsePtr newFileResponse(
502 const unsigned char *pBuffer,
503 size_t bufferLength,
504 const std::string &attachmentFileName = "",
505 ContentType type = CT_NONE,
506 const std::string &typeString = "");
507
510
526 static HttpResponsePtr newStreamResponse(
527 const std::function<std::size_t(char *, std::size_t)> &callback,
528 const std::string &attachmentFileName = "",
529 ContentType type = CT_NONE,
530 const std::string &typeString = "",
531 const HttpRequestPtr &req = HttpRequestPtr());
532
535
547 static HttpResponsePtr newAsyncStreamResponse(
548 const std::function<void(ResponseStreamPtr)> &callback,
549 bool disableKickoffTimeout = false);
550
555 template <typename T>
556 static HttpResponsePtr newCustomHttpResponse(T &&obj)
557 {
558 return toResponse(std::forward<T>(obj));
559 }
560
619 static HttpResponsePtr newOptionsResponse(
620 const HttpRequestPtr &request,
621 const std::function<bool(std::string_view)> &originValidator = nullptr,
622 bool allowNullOrigin = false,
623 bool allowCredentials = false,
624 bool allowPNA = true,
625 std::optional<unsigned int> maxAgeSeconds = {},
626 const std::optional<std::set<std::string_view>> &allowedHeaders =
627 std::nullopt);
628
637 inline static HttpResponsePtr newOptionsResponse(
638 const HttpRequestPtr &request,
639 const std::set<std::string_view> &allowedHeaders,
640 const std::function<bool(std::string_view)> &originValidator = nullptr,
641 bool allowNullOrigin = false,
642 bool allowCredentials = false,
643 bool allowPNA = true,
644 std::optional<unsigned int> maxAgeSeconds = {})
645 {
646 return newOptionsResponse(request,
647 originValidator,
648 allowNullOrigin,
649 allowCredentials,
650 allowPNA,
651 maxAgeSeconds,
652 allowedHeaders);
653 }
654
692 void addCorsHeaders(const HttpRequestPtr &request,
693 const std::set<std::string_view> &exposedHeaders = {},
694 const std::optional<bool> &allowCredentials = {});
695
701 virtual const std::string &sendfileName() const = 0;
702
708 using SendfileRange = std::pair<size_t, size_t>; // { offset, length }
709 virtual const SendfileRange &sendfileRange() const = 0;
710
716 virtual const std::function<std::size_t(char *, std::size_t)> &
717 streamCallback() const = 0;
718
723 virtual const std::function<void(ResponseStreamPtr)> &asyncStreamCallback()
724 const = 0;
725
729 virtual std::string contentTypeString() const = 0;
730
731 virtual ~HttpResponse()
732 {
733 }
734
735 private:
736 virtual void setBody(const char *body, size_t len) = 0;
737 virtual const char *getBodyData() const = 0;
738 virtual size_t getBodyLength() const = 0;
739 virtual void setContentTypeCodeAndCustomString(ContentType type,
740 const char *typeString,
741 size_t typeStringLength) = 0;
742 virtual void setContentTypeString(const char *typeString,
743 size_t typeStringLength) = 0;
744 virtual void setCustomStatusCode(int code,
745 const char *message,
746 size_t messageLength) = 0;
747};
748
749template <>
750inline HttpResponsePtr toResponse<const Json::Value &>(const Json::Value &pJson)
751{
753}
754
755template <>
756inline HttpResponsePtr toResponse(Json::Value &&pJson)
757{
758 return HttpResponse::newHttpJsonResponse(std::move(pJson));
759}
760
761template <>
762inline std::shared_ptr<Json::Value> fromResponse(const HttpResponse &resp)
763{
764 return resp.getJsonObject();
765}
766} // namespace drogon
this class represents a cookie entity.
Definition Cookie.h:32
static std::string demangle(const char *mangled_name)
demangle the type name which is returned by typeid(T).name().
Definition DrClassMap.h:116
Definition HttpResponse.h:117
virtual void setBody(std::string &&body)=0
Set the response body(content).
virtual void clear()=0
Reset the response object to its initial state.
Version getVersion() const
Return the enum type version of the response.
Definition HttpResponse.h:341
virtual const trantor::Date & creationDate() const =0
Get the creation timestamp of the response.
void addCorsHeaders(const HttpRequestPtr &request, const std::set< std::string_view > &exposedHeaders={}, const std::optional< bool > &allowCredentials={})
Add CORS headers to a response.
virtual void setBody(const std::string &body)=0
Set the response body(content).
std::string_view getBody() const
Get the response body.
Definition HttpResponse.h:319
virtual bool allowCompression() const =0
Get whether the response allow compression.
static HttpResponsePtr newOptionsResponse(const HttpRequestPtr &request, const std::set< std::string_view > &allowedHeaders, const std::function< bool(std::string_view)> &originValidator=nullptr, bool allowNullOrigin=false, bool allowCredentials=false, bool allowPNA=true, std::optional< unsigned int > maxAgeSeconds={})
Create an OPTIONS or CORS pre-flight response.
Definition HttpResponse.h:637
static HttpResponsePtr newCustomHttpResponse(T &&obj)
Create a custom HTTP response object. For using this template, users must specialize the toResponse t...
Definition HttpResponse.h:556
virtual ContentType contentType() const =0
Get the response content type.
std::pair< size_t, size_t > SendfileRange
Returns the range of the file response as a pair of size_t (offset, length). Length of 0 means the en...
Definition HttpResponse.h:708
virtual const SafeStringMap< std::string > & headers() const =0
Get all headers of the response.
virtual void addHeader(std::string field, const std::string &value)=0
Set the header string identified by the field parameter.
virtual const SafeStringMap< Cookie > & cookies() const =0
Get all cookies.
virtual const Cookie & getCookie(const std::string &key) const =0
virtual const std::shared_ptr< Json::Value > & jsonObject() const =0
std::string_view body() const
Get the response body.
Definition HttpResponse.h:313
virtual void setContentTypeCode(ContentType type)=0
virtual ssize_t expiredTime() const =0
Get the expiration time of the response.
const SafeStringMap< Cookie > & getCookies() const
Get all cookies.
Definition HttpResponse.h:287
static HttpResponsePtr newHttpViewResponse(const std::string &viewName, const HttpViewData &data=HttpViewData(), const HttpRequestPtr &req=HttpRequestPtr())
virtual HttpStatusCode statusCode() const =0
Get the status code such as 200, 404.
static HttpResponsePtr newHttpResponse()
virtual void removeHeader(std::string key)=0
Remove the header identified by the key parameter.
virtual const char * versionString() const =0
virtual void removeCookie(const std::string &key)=0
Remove the cookie identified by the key parameter.
virtual void addCookie(const Cookie &cookie)=0
Add a cookie.
static HttpResponsePtr newHttpJsonResponse(const Json::Value &data)
static HttpResponsePtr newStreamResponse(const std::function< std::size_t(char *, std::size_t)> &callback, const std::string &attachmentFileName="", ContentType type=CT_NONE, const std::string &typeString="", const HttpRequestPtr &req=HttpRequestPtr())
static HttpResponsePtr newFileResponse(const std::string &fullPath, size_t offset, size_t length, bool setContentRange=true, const std::string &attachmentFileName="", ContentType type=CT_NONE, const std::string &typeString="", const HttpRequestPtr &req=HttpRequestPtr())
Create a response that returns part of a file to the client.
static HttpResponsePtr newFileResponse(const std::string &fullPath, const std::string &attachmentFileName="", ContentType type=CT_NONE, const std::string &typeString="", const HttpRequestPtr &req=HttpRequestPtr())
Create a response that returns a file to the client.
virtual const std::string & sendfileName() const =0
If the response is a file response (i.e. created by newFileResponse) returns the path on the filesyst...
virtual bool ifCloseConnection() const =0
Get the status set by the setCloseConnection() method.
virtual const std::string & getHeader(std::string key) const =0
Get the header string identified by the key parameter.
static HttpResponsePtr newRedirectionResponse(const std::string &location, HttpStatusCode status=k302Found)
virtual void setExpiredTime(ssize_t expiredTime)=0
virtual Version version() const =0
Return the enum type version of the response.
static HttpResponsePtr newHttpResponse(HttpStatusCode code, ContentType type)
Create a response with a status code and a content type.
virtual void setVersion(const Version v)=0
Set the http version, http1.0 or http1.1.
static HttpResponsePtr newHttpJsonResponse(Json::Value &&data)
static HttpResponsePtr newOptionsResponse(const HttpRequestPtr &request, const std::function< bool(std::string_view)> &originValidator=nullptr, bool allowNullOrigin=false, bool allowCredentials=false, bool allowPNA=true, std::optional< unsigned int > maxAgeSeconds={}, const std::optional< std::set< std::string_view > > &allowedHeaders=std::nullopt)
Create an OPTIONS or CORS pre-flight response.
virtual void setAllowCompression(bool allow)=0
Set whether the response should be compress.
virtual void setStatusCode(HttpStatusCode code)=0
Set the status code of the response.
void setContentTypeString(const std::string_view &typeString)
Definition HttpResponse.h:201
T as() const
This template enables explicit type conversion, see the above template.
Definition HttpResponse.h:142
static HttpResponsePtr newAsyncStreamResponse(const std::function< void(ResponseStreamPtr)> &callback, bool disableKickoffTimeout=false)
static HttpResponsePtr newFileResponse(const unsigned char *pBuffer, size_t bufferLength, const std::string &attachmentFileName="", ContentType type=CT_NONE, const std::string &typeString="")
virtual const std::function< void(ResponseStreamPtr)> & asyncStreamCallback() const =0
If the response is a async stream response (i.e. created by asyncStreamCallback) returns the stream p...
void setBody(const char(&body)[N])
Set the response body(content).
Definition HttpResponse.h:306
virtual const trantor::CertificatePtr & peerCertificate() const =0
Get the certificate of the peer, if any.
static HttpResponsePtr newNotFoundResponse(const HttpRequestPtr &req=HttpRequestPtr())
Create a response which returns a 404 page.
virtual void setPassThrough(bool flag)=0
Set the response object to the pass-through mode or not. It's not by default when a new response obje...
virtual std::string contentTypeString() const =0
Returns the content type associated with the response.
const SafeStringMap< std::string > & getHeaders() const
Get all headers of the response.
Definition HttpResponse.h:256
void setContentTypeCodeAndCustomString(ContentType type, const std::string_view &typeString)
Definition HttpResponse.h:209
virtual const std::function< std::size_t(char *, std::size_t)> & streamCallback() const =0
If the response is a stream response (i.e. created by newStreamResponse) returns the callback functio...
virtual void addCookie(const std::string &key, const std::string &value)=0
Add a cookie.
virtual const std::string & getJsonError() const =0
Get the error message of parsing the JSON body received from peer. This method usually is called afte...
virtual void setCloseConnection(bool on)=0
Set if close the connection after the request is sent.
This class represents the data set displayed in views.
Definition HttpViewData.h:33
Drogon Test is a minimal effort test framework developed because the major C++ test frameworks doesn'...
Definition Attribute.h:23
T fromResponse(const HttpResponse &)
This template is used to convert a response object to a custom type object. Users must specialize the...
Definition HttpResponse.h:42
HttpResponsePtr toResponse(T &&)
This template is used to create a response object from a custom type object by calling the newCustomH...
Definition HttpResponse.h:56