forked from RipcordSoftware/libhttpserver
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathresponse.h
More file actions
172 lines (131 loc) · 5.13 KB
/
Copy pathresponse.h
File metadata and controls
172 lines (131 loc) · 5.13 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
#ifndef RS_LIBHTTPSERVER_RESPONSE_H
#define RS_LIBHTTPSERVER_RESPONSE_H
#include <string>
#include <map>
#include <iostream>
#include <boost/noncopyable.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>
#include "types.h"
#include "response_stream.h"
#include "null_stream.h"
#include "chunked_response_stream.h"
#include "gzip_response_stream.h"
#include "multipart_response_stream.h"
#include "header_key_comparer.h"
#include "headers.h"
#include "request.h"
#include "mime_types.h"
#include "response_headers.h"
namespace rs {
namespace httpserver {
class Response final : public boost::enable_shared_from_this<Response>, private boost::noncopyable {
public:
~Response() noexcept {}
static response_ptr Create(socket_ptr socket, request_ptr request) {
return response_ptr(new Response(socket, request));
}
int getStatusCode() {
return statusCode_;
}
Response& setStatusCode(int statusCode) {
statusCode_ = statusCode;
return *this;
}
Response& setStatusDescription(const std::string& statusDescription) {
statusDescription_ = statusDescription;
return *this;
}
Response& setContentType(const MimeTypes::Item& item) {
return setContentType(item.getType(), item.getCompressible());
}
Response& setContentType(const std::string& contentType = emptyValue_, bool compress = true) {
compress_ = compress & request_->ClientAcceptsGzip();
return setHeader(Headers::ContentType, contentType);
}
Response& setContentEncoding(const std::string& contentEncoding = emptyValue_) {
return setHeader(Headers::ContentEncoding, contentEncoding);
}
Response& setContentLength(int contentLength) {
return setHeader(Headers::ContentLength, boost::lexical_cast<std::string>(contentLength));
}
Response& setLocation(const std::string& location) {
return setHeader(Headers::Location, location);
}
Response& setLastModified(std::time_t lastModifiedTime);
Response& setLastModified(const std::string& lastModifiedTime);
Response& setETag(const std::string& etag);
Response& setNoCache();
Response& setContentRange(const std::string& range);
Response& setHeader(const std::string& key, const std::string& value = emptyValue_) {
if (value.length() > 0) {
headers_[key] = value;
} else {
headers_.erase(key);
}
return *this;
}
Response& ResetHeaders() {
headers_.clear();
statusCode_ = Headers::DefaultStatusCode;
statusDescription_ = Headers::DefaultStatusDescription;
version_ = Headers::DefaultVersion;
return *this;
}
void ForceClose() {
forceClose_ = true;
}
bool ShouldClose() {
auto connection = headers_.find(Headers::Connection);
return connection != headers_.cend() ? boost::iequals(connection->second, "close") : false;
}
bool HasResponded() {
return socket_->getTotalBytesSent() != (socketBytesSentWatermark_ + socketBytesSentContinue_);
}
void Send();
void Send(const std::string& data);
void Send(Stream& stream);
void Send(std::iostream& stream);
void SendContinue(bool kontinue);
Stream& getResponseStream();
MultipartResponseStream& getMultiResponseStream();
void Redirect(const std::string& location);
static std::string FormatLastModifiedTime(std::time_t lastModifiedTime);
private:
Response(socket_ptr socket, request_ptr request) : socket_(socket), request_(request),
responseStream_(socket_), chunkedStream_(responseStream_), zStream_(chunkedStream_),
multiStream_(responseStream_),
statusCode_(Headers::DefaultStatusCode), version_(Headers::DefaultVersion),
statusDescription_(Headers::DefaultStatusDescription), headers_(),
socketBytesSentWatermark_(socket->getTotalBytesSent()), socketBytesSentContinue_(0),
compress_(false), forceClose_(false) {}
void SerializeHeaders(std::stringstream& sout);
bool HasContentLength() {
return headers_.find(Headers::ContentLength) != headers_.cend();
}
bool IsChunkEncoded() {
auto encoding = headers_.find(Headers::TransferEncoding);
return encoding != headers_.cend() ? boost::iequals(encoding->second, "chunked") : false;
}
socket_ptr socket_;
request_ptr request_;
ResponseHeaders headers_;
NullStream nullStream_;
ResponseStream responseStream_;
ChunkedResponseStream chunkedStream_;
GzipResponseStream zStream_;
MultipartResponseStream multiStream_;
int statusCode_;
std::string statusDescription_;
std::string version_;
bool compress_;
bool forceClose_;
const std::size_t socketBytesSentWatermark_;
std::size_t socketBytesSentContinue_;
const static std::string emptyValue_;
const static std::string keepAliveHeaderValue_;
};
}}
#endif /* RS_LIBHTTPSERVER_RESPONSE_H */