SNode.C
Loading...
Searching...
No Matches
web::http::server::Response Class Reference

#include <Response.h>

Inheritance diagram for web::http::server::Response:
Collaboration diagram for web::http::server::Response:

Public Member Functions

 Response (SocketContext *socketContext)
 
 Response (Response &)=delete
 
 Response (Response &&) noexcept=delete
 
Responseoperator= (Response &)=delete
 
Responseoperator= (Response &&) noexcept=delete
 
 ~Response () override
 
void stopResponse ()
 
Responsestatus (int statusCode)
 
Responseappend (const std::string &field, const std::string &value)
 
Responseset (const std::string &field, const std::string &value, bool overwrite=true)
 
Responseset (const std::map< std::string, std::string > &headers, bool overwrite=true)
 
Responsetype (const std::string &type)
 
Responsecookie (const std::string &name, const std::string &value, const std::map< std::string, std::string > &options={})
 
ResponseclearCookie (const std::string &name, const std::map< std::string, std::string > &options={})
 
ResponsesetTrailer (const std::string &field, const std::string &value, bool overwrite=true)
 
void send (const char *chunk, std::size_t chunkLen)
 
void send (const std::string &chunk)
 
void sendStatus (int statusCode)
 
void upgrade (const std::shared_ptr< Request > &request, const std::function< void(const std::string &)> &status)
 
void sendFile (const std::string &file, const std::function< void(int)> &callback)
 
void end ()
 
ResponsesendHeader ()
 
ResponsesendFragment (const char *chunk, std::size_t chunkLen)
 
ResponsesendFragment (const std::string &chunk)
 
const std::string & header (const std::string &field)
 
SocketContextgetSocketContext () const
 
- Public Member Functions inherited from core::pipe::Sink
 Sink (Sink &)=delete
 
Sinkoperator= (Sink &)=delete
 

Public Attributes

int statusCode = 200
 
int httpMajor = 1
 
int httpMinor = 1
 

Protected Attributes

web::http::CiStringMap< std::string > headers
 
web::http::CiStringMap< web::http::CookieOptionscookies
 
web::http::CiStringMap< std::string > trailer
 

Private Member Functions

virtual void init ()
 
void sendCompleted ()
 
void onSourceConnect (core::pipe::Source *source) override
 
void onSourceData (const char *chunk, std::size_t chunkLen) override
 
void onSourceEof () override
 
void onSourceError (int errnum) override
 

Private Attributes

std::size_t contentSent = 0
 
std::size_t contentLength = 0
 
SocketContextsocketContext = nullptr
 
core::socket::stream::SocketContextsocketContextUpgrade = nullptr
 
ConnectionState connectionState = ConnectionState::Default
 
TransferEncoding transferEncoding = TransferEncoding::HTTP10
 

Friends

class SocketContext
 

Additional Inherited Members

- Protected Member Functions inherited from core::pipe::Sink
 Sink ()=default
 
 Sink (Sink &&) noexcept=default
 
Sinkoperator= (Sink &&) noexcept=default
 
virtual ~Sink ()
 
bool isStreaming ()
 
void stop ()
 

Detailed Description

Definition at line 51 of file Response.h.

Constructor & Destructor Documentation

◆ Response() [1/3]

web::http::server::Response::Response ( SocketContext * socketContext)
explicit

Definition at line 50 of file Response.cpp.

52 }
SocketContext * socketContext
Definition Response.h:115

References Response().

Referenced by Response().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Response() [2/3]

web::http::server::Response::Response ( Response & )
explicitdelete

◆ Response() [3/3]

web::http::server::Response::Response ( Response && )
explicitdeletenoexcept

◆ ~Response()

web::http::server::Response::~Response ( )
override

Definition at line 54 of file Response.cpp.

54 {
55 if (socketContext != nullptr && Sink::isStreaming()) {
57 }
58
59 delete socketContextUpgrade; // delete of nullptr is valid since C++14!
60 }
core::socket::stream::SocketContext * socketContextUpgrade
Definition Response.h:116

Member Function Documentation

◆ append()

Response & web::http::server::Response::append ( const std::string & field,
const std::string & value )

Definition at line 86 of file Response.cpp.

86 {
87 const std::map<std::string, std::string>::iterator it = headers.find(field);
88
89 if (it != headers.end()) {
90 set(field, it->second.append(", ").append(value));
91 } else {
92 set(field, value);
93 }
94
95 return *this;
96 }
web::http::CiStringMap< std::string > headers
Definition Response.h:107
Response & set(const std::string &field, const std::string &value, bool overwrite=true)
Definition Response.cpp:106

◆ clearCookie()

Response & web::http::server::Response::clearCookie ( const std::string & name,
const std::map< std::string, std::string > & options = {} )

Definition at line 162 of file Response.cpp.

162 {
163 std::map<std::string, std::string> opts = options;
164
165 opts.erase("Max-Age");
166 const time_t time = 0;
167 opts["Expires"] = httputils::to_http_date(utils::system::gmtime(&time));
168
169 return cookie(name, "", opts);
170 }
Response & cookie(const std::string &name, const std::string &value, const std::map< std::string, std::string > &options={})
Definition Response.cpp:156
std::string to_http_date(struct tm *tm)
struct tm * gmtime(const time_t *timep)
Definition time.cpp:40
time_t time(time_t *tloc)
Definition time.cpp:30

◆ cookie()

Response & web::http::server::Response::cookie ( const std::string & name,
const std::string & value,
const std::map< std::string, std::string > & options = {} )

Definition at line 156 of file Response.cpp.

156 {
157 cookies.insert({name, CookieOptions(value, options)});
158
159 return *this;
160 }
web::http::CiStringMap< web::http::CookieOptions > cookies
Definition Response.h:108

◆ end()

void web::http::server::Response::end ( )

Definition at line 305 of file Response.cpp.

305 {
306 send("");
307 }
void send(const char *chunk, std::size_t chunkLen)
Definition Response.cpp:191

◆ getSocketContext()

SocketContext * web::http::server::Response::getSocketContext ( ) const

Definition at line 432 of file Response.cpp.

432 {
433 return socketContext;
434 }

◆ header()

const std::string & web::http::server::Response::header ( const std::string & field)

Definition at line 428 of file Response.cpp.

428 {
429 return headers[field];
430 }

◆ init()

void web::http::server::Response::init ( )
privatevirtual

Definition at line 66 of file Response.cpp.

References httpMajor, httpMinor, and statusCode.

◆ onSourceConnect()

void web::http::server::Response::onSourceConnect ( core::pipe::Source * source)
overrideprivatevirtual

Implements core::pipe::Sink.

Definition at line 391 of file Response.cpp.

391 {
392 if (socketContext != nullptr) {
394 sendHeader();
395
396 source->start();
397 } else {
398 source->stop();
399 }
400 } else {
401 source->stop();
402 }
403 }
Source * source
Definition Sink.h:68
virtual void stop()=0
virtual void start()=0
bool streamToPeer(core::pipe::Source *source) const

References sendHeader(), core::pipe::Source::start(), and core::pipe::Source::stop().

Here is the call graph for this function:

◆ onSourceData()

void web::http::server::Response::onSourceData ( const char * chunk,
std::size_t chunkLen )
overrideprivatevirtual

Implements core::pipe::Sink.

Definition at line 405 of file Response.cpp.

405 {
406 sendFragment(chunk, chunkLen);
407 }
Response & sendFragment(const char *chunk, std::size_t chunkLen)
Definition Response.cpp:346

◆ onSourceEof()

void web::http::server::Response::onSourceEof ( )
overrideprivatevirtual

Implements core::pipe::Sink.

Definition at line 409 of file Response.cpp.

409 {
410 if (socketContext != nullptr) {
412 }
413
415 }

References sendCompleted().

Here is the call graph for this function:

◆ onSourceError()

void web::http::server::Response::onSourceError ( int errnum)
overrideprivatevirtual

Implements core::pipe::Sink.

Definition at line 417 of file Response.cpp.

417 {
418 errno = errnum;
419
420 if (socketContext != nullptr) {
423 }
424
426 }

References sendCompleted().

Here is the call graph for this function:

◆ operator=() [1/2]

Response & web::http::server::Response::operator= ( Response && )
deletenoexcept

◆ operator=() [2/2]

Response & web::http::server::Response::operator= ( Response & )
delete

◆ send() [1/2]

void web::http::server::Response::send ( const char * chunk,
std::size_t chunkLen )

Definition at line 191 of file Response.cpp.

191 {
192 if (chunkLen > 0) {
193 set("Content-Type", "application/octet-stream", false);
194 }
195 set("Content-Length", std::to_string(chunkLen));
196
197 sendHeader();
198 sendFragment(chunk, chunkLen);
200 }

References sendCompleted(), and sendHeader().

Here is the call graph for this function:

◆ send() [2/2]

void web::http::server::Response::send ( const std::string & chunk)

Definition at line 202 of file Response.cpp.

202 {
203 if (!chunk.empty()) {
204 set("Content-Type", "text/html; charset=utf-8", false);
205 }
206
207 send(chunk.data(), chunk.size());
208 }

◆ sendCompleted()

void web::http::server::Response::sendCompleted ( )
private

Definition at line 368 of file Response.cpp.

368 {
370 sendFragment(""); // For transfer encoding chunked. Terminate the chunk sequence.
371
372 if (!trailer.empty()) {
373 for (auto& [field, value] : trailer) {
374 socketContext->sendToPeer(std::string(field).append(":").append(value).append("\r\n"));
375 }
376
377 socketContext->sendToPeer("\r\n");
378 }
379 }
380
381 if (socketContext != nullptr) {
383
384 if (socketContextUpgrade != nullptr) {
386 socketContextUpgrade = nullptr;
387 }
388 }
389 }
virtual void switchSocketContext(SocketContext *newSocketContext)
void sendToPeer(const char *chunk, std::size_t chunkLen) const final
Response & append(const std::string &field, const std::string &value)
Definition Response.cpp:86

Referenced by onSourceEof(), onSourceError(), and send().

Here is the caller graph for this function:

◆ sendFile()

void web::http::server::Response::sendFile ( const std::string & file,
const std::function< void(int)> & callback )

Definition at line 270 of file Response.cpp.

270 {
271 if (socketContext != nullptr) {
272 std::string absolutFileName = file;
273
274 if (std::filesystem::exists(absolutFileName)) {
275 std::error_code ec;
276 absolutFileName = std::filesystem::canonical(absolutFileName);
277
278 if (std::filesystem::is_regular_file(absolutFileName, ec) && !ec) {
279 core::file::FileReader::open(absolutFileName)->pipe(this, [this, &absolutFileName, &callback](int errnum) {
280 callback(errnum);
281
282 if (errnum == 0) {
283 set("Content-Type", web::http::MimeTypes::contentType(absolutFileName), false);
284 set("Last-Modified", httputils::file_mod_http_date(absolutFileName), false);
285 if (httpMajor == 1) {
286 if (httpMinor == 1) {
287 set("Transfer-Encoding", "chunked");
288 } else {
289 set("Content-Length", std::to_string(std::filesystem::file_size(absolutFileName)));
290 }
291 }
292 }
293 });
294 } else {
295 errno = EEXIST;
296 callback(errno);
297 }
298 } else {
299 errno = ENOENT;
300 callback(errno);
301 }
302 }
303 }
static FileReader * open(const std::string &path)
void pipe(Sink *sink, const std::function< void(int)> &callback)
Definition Source.cpp:38
static std::string contentType(const std::string &file)
std::string file_mod_http_date(const std::string &filePath)

◆ sendFragment() [1/2]

Response & web::http::server::Response::sendFragment ( const char * chunk,
std::size_t chunkLen )

Definition at line 346 of file Response.cpp.

346 {
347 if (socketContext != nullptr) {
349 socketContext->sendToPeer(to_hex_str(chunkLen).append("\r\n"));
350 }
351
352 socketContext->sendToPeer(chunk, chunkLen);
353 contentSent += chunkLen;
354
356 socketContext->sendToPeer("\r\n");
357 contentLength += chunkLen;
358 }
359 }
360
361 return *this;
362 }
#define to_hex_str(int_val)
Definition Request.cpp:49

◆ sendFragment() [2/2]

Response & web::http::server::Response::sendFragment ( const std::string & chunk)

Definition at line 364 of file Response.cpp.

364 {
365 return sendFragment(chunk.data(), chunk.size());
366 }

◆ sendHeader()

Response & web::http::server::Response::sendHeader ( )

Definition at line 309 of file Response.cpp.

309 {
310 if (socketContext != nullptr) {
312
313 socketContext->sendToPeer("HTTP/" + std::to_string(httpMajor)
314 .append(".")
315 .append(std::to_string(httpMinor))
316 .append(" ")
317 .append(std::to_string(statusCode))
318 .append(" ")
320 .append("\r\n"));
321 socketContext->sendToPeer("Date: " + httputils::to_http_date() + "\r\n");
322
323 set("X-Powered-By", "snode.c");
324
325 for (const auto& [field, value] : headers) {
326 socketContext->sendToPeer(std::string(field).append(": ").append(value).append("\r\n"));
327 }
328
329 for (const auto& [cookie, cookieValue] : cookies) {
330 const std::string cookieString = std::accumulate(
331 cookieValue.getOptions().begin(),
332 cookieValue.getOptions().end(),
333 cookie + "=" + cookieValue.getValue(),
334 [](const std::string& str, const std::pair<const std::string&, const std::string&> option) -> std::string {
335 return str + "; " + option.first + (!option.second.empty() ? "=" + option.second : "");
336 });
337 socketContext->sendToPeer("Set-Cookie: " + cookieString + "\r\n");
338 }
339
340 socketContext->sendToPeer("\r\n");
341 }
342
343 return *this;
344 }
static std::string reason(int status)

Referenced by onSourceConnect(), and send().

Here is the caller graph for this function:

◆ sendStatus()

void web::http::server::Response::sendStatus ( int statusCode)

Definition at line 210 of file Response.cpp.

210 {
212
214 }
Response & status(int statusCode)
Definition Response.cpp:80

References status().

Here is the call graph for this function:

◆ set() [1/2]

Response & web::http::server::Response::set ( const std::map< std::string, std::string > & headers,
bool overwrite = true )

Definition at line 98 of file Response.cpp.

98 {
99 for (const auto& [field, value] : headers) {
100 set(field, value, overwrite);
101 }
102
103 return *this;
104 }

◆ set() [2/2]

Response & web::http::server::Response::set ( const std::string & field,
const std::string & value,
bool overwrite = true )

Definition at line 106 of file Response.cpp.

106 {
107 if (!value.empty()) {
108 if (overwrite) {
109 headers.insert_or_assign(field, value);
110 } else {
111 headers.insert({field, value});
112 }
113
114 if (web::http::ciEquals(field, "Connection")) {
115 if (web::http::ciContains(headers[field], "keep-alive")) {
117 } else if (web::http::ciContains(headers[field], "close")) {
119 }
120 } else if (web::http::ciEquals(field, "Content-Length")) {
121 contentLength = std::stoul(value);
123 headers.erase("Transfer-Encoding");
124 } else if (web::http::ciEquals(field, "Transfer-Encoding")) {
125 if (web::http::ciContains(headers[field], "chunked")) {
127 headers.erase("Content-Length");
128 }
129 if (web::http::ciContains(headers[field], "compressed")) {
130 }
131 if (web::http::ciContains(headers[field], "deflate")) {
132 }
133 if (web::http::ciContains(headers[field], "gzip")) {
134 }
135 } else if (web::http::ciEquals(field, "Content-Encoding")) {
136 if (web::http::ciContains(headers[field], "compressed")) {
137 }
138 if (web::http::ciContains(headers[field], "deflate")) {
139 }
140 if (web::http::ciContains(headers[field], "gzip")) {
141 }
142 if (web::http::ciContains(headers[field], "br")) {
143 }
144 }
145 } else {
146 headers.erase(field);
147 }
148
149 return *this;
150 }
bool ciEquals(const std::string &str1, const std::string &str2)
bool ciContains(const std::string &str1, const std::string &str2)

◆ setTrailer()

Response & web::http::server::Response::setTrailer ( const std::string & field,
const std::string & value,
bool overwrite = true )

Definition at line 172 of file Response.cpp.

172 {
173 if (!value.empty()) {
174 if (overwrite) {
175 trailer.insert_or_assign(field, value);
176 } else {
177 trailer.insert({field, value});
178 }
179 if (!headers.contains("Trailer")) {
180 set("Trailer", field);
181 } else {
182 headers["Trailer"].append("," + field);
183 }
184 } else {
185 trailer.erase(field);
186 }
187
188 return *this;
189 }

◆ status()

Response & web::http::server::Response::status ( int statusCode)

Definition at line 80 of file Response.cpp.

80 {
81 this->statusCode = statusCode;
82
83 return *this;
84 }

References statusCode.

Referenced by sendStatus().

Here is the caller graph for this function:

◆ stopResponse()

void web::http::server::Response::stopResponse ( )

Definition at line 62 of file Response.cpp.

62 {
63 stop();
64 }
void stop()
Definition Sink.cpp:46

◆ type()

Response & web::http::server::Response::type ( const std::string & type)

Definition at line 152 of file Response.cpp.

152 {
153 return set("Content-Type", type);
154 }
Response & type(const std::string &type)
Definition Response.cpp:152

◆ upgrade()

void web::http::server::Response::upgrade ( const std::shared_ptr< Request > & request,
const std::function< void(const std::string &)> & status )

Sequence diagram of res.upgrade(req).

Definition at line 222 of file Response.cpp.

222 {
223 std::string name;
224
225 if (socketContext != nullptr) {
226 if (request != nullptr) {
227 if (web::http::ciContains(request->get("connection"), "Upgrade")) {
228 web::http::server::SocketContextUpgradeFactory* socketContextUpgradeFactory =
230
231 if (socketContextUpgradeFactory != nullptr) {
232 name = socketContextUpgradeFactory->name();
234 << " HTTP upgrade: SocketContextUpgradeFactory created successful: " << name;
235
236 socketContextUpgrade = socketContextUpgradeFactory->create(socketContext->getSocketConnection());
237
238 if (socketContextUpgrade != nullptr) {
240 << " HTTP upgrade: SocketContextUpgrade created successful: " << name;
241 } else {
243 << " HTTP upgrade: Create SocketContextUpgrade failed: " << name;
244
245 set("Connection", "close").status(404);
246 }
247 } else {
249 << " HTTP upgrade: SocketContextUpgradeFactory not supported: " << request->get("upgrade");
250
251 set("Connection", "close").status(404);
252 }
253 } else {
254 LOG(DEBUG) << socketContext->getSocketConnection()->getConnectionName() << " HTTP upgrade: No upgrade requested";
255
256 set("Connection", "close").status(400);
257 }
258 } else {
259 LOG(ERROR) << socketContext->getSocketConnection()->getConnectionName() << " HTTP upgrade: Request has gone away";
260
261 set("Connection", "close").status(500);
262 }
263 } else {
264 LOG(ERROR) << socketContext->getSocketConnection()->getConnectionName() << " HTTP upgrade: SocketContext has gone away";
265 }
266
267 status(name);
268 }
const std::string & getConnectionName() const
SocketConnection * getSocketConnection() const
virtual SocketContextUpgrade< Request, Response > * create(core::socket::stream::SocketConnection *socketConnection, Request *request, Response *response)=0
SocketContextUpgradeFactory * select(Request &req, Response &res) override

Friends And Related Symbol Documentation

◆ SocketContext

friend class SocketContext
friend

Definition at line 121 of file Response.h.

Member Data Documentation

◆ connectionState

ConnectionState web::http::server::Response::connectionState = ConnectionState::Default
private

Definition at line 118 of file Response.h.

◆ contentLength

std::size_t web::http::server::Response::contentLength = 0
private

Definition at line 113 of file Response.h.

◆ contentSent

std::size_t web::http::server::Response::contentSent = 0
private

Definition at line 112 of file Response.h.

◆ cookies

web::http::CiStringMap<web::http::CookieOptions> web::http::server::Response::cookies
protected

Definition at line 108 of file Response.h.

◆ headers

web::http::CiStringMap<std::string> web::http::server::Response::headers
protected

Definition at line 107 of file Response.h.

◆ httpMajor

int web::http::server::Response::httpMajor = 1

Definition at line 103 of file Response.h.

Referenced by init().

◆ httpMinor

int web::http::server::Response::httpMinor = 1

Definition at line 104 of file Response.h.

Referenced by init().

◆ socketContext

SocketContext* web::http::server::Response::socketContext = nullptr
private

Definition at line 115 of file Response.h.

◆ socketContextUpgrade

core::socket::stream::SocketContext* web::http::server::Response::socketContextUpgrade = nullptr
private

Definition at line 116 of file Response.h.

◆ statusCode

int web::http::server::Response::statusCode = 200

Definition at line 102 of file Response.h.

Referenced by init(), and status().

◆ trailer

web::http::CiStringMap<std::string> web::http::server::Response::trailer
protected

Definition at line 109 of file Response.h.

◆ transferEncoding

TransferEncoding web::http::server::Response::transferEncoding = TransferEncoding::HTTP10
private

Definition at line 119 of file Response.h.


The documentation for this class was generated from the following files: