join 1.0
lightweight network framework library
Loading...
Searching...
No Matches
http_server.hpp
Go to the documentation of this file.
1
25#ifndef JOIN_SERVICES_HTTP_SERVER_HPP
26#define JOIN_SERVICES_HTTP_SERVER_HPP
27
28// libjoin.
30#include <join/http_message.hpp>
31#include <join/chunk_stream.hpp>
32#include <join/filesystem.hpp>
33#include <join/tls_stream.hpp>
34#include <join/acceptor.hpp>
35#include <join/version.hpp>
36#include <join/zstream.hpp>
37#include <join/thread.hpp>
38#include <join/cache.hpp>
39
40// C++.
41#include <sys/eventfd.h>
42#include <thread>
43#include <memory>
44#include <vector>
45
46// C.
47#include <fnmatch.h>
48
49namespace join
50{
61
65 template <class Protocol>
67 {
68 using Handler = std::function<void (typename Protocol::Worker*)>;
69 using Access = std::function<bool (const std::string&, const std::string&, std::error_code&)>;
70
73 std::string directory;
74 std::string name;
75 std::string alias;
78 };
79
83 template <class Protocol>
84 class BasicHttpWorker : public Protocol::Stream
85 {
86 public:
89
95 : _server (server)
96 , _thread ([this] () {
97 work ();
98 })
99 {
100 }
101
106 BasicHttpWorker (const BasicHttpWorker& other) = delete;
107
114
120
127
132 {
133 this->_thread.join ();
134 }
135
140 {
141 // restore concrete stream.
142 this->clearEncoding ();
143
144 // set missing response headers.
145 if (!this->_response.hasHeader ("Date"))
146 {
147 std::stringstream gmt;
148 std::time_t ti = std::time (nullptr);
149 gmt << std::put_time (std::gmtime (&ti), "%a, %d %b %Y %H:%M:%S GMT");
150 this->_response.header ("Date", gmt.str ());
151 }
152 if (!this->_response.hasHeader ("Server"))
153 {
154 this->_response.header ("Server", "join/" JOIN_VERSION);
155 }
156 if (!this->_response.hasHeader ("Connection"))
157 {
158 if (this->_max && compareNoCase (this->_request.header ("Connection"), "keep-alive"))
159 {
160 std::stringstream keepAlive;
161 keepAlive << "timeout=" << this->_server->keepAliveTimeout ().count ()
162 << ", max=" << this->_server->keepAliveMax ();
163 this->_response.header ("Keep-Alive", keepAlive.str ());
164 this->_response.header ("Connection", "Keep-Alive");
165 }
166 else
167 {
168 this->_response.header ("Connection", "close");
169 this->_max = 0;
170 }
171 }
172 if ((this->_server->scheme () == "https") && !this->_response.hasHeader ("Strict-Transport-Security"))
173 {
174 this->_response.header ("Strict-Transport-Security", "max-age=31536000; includeSubDomains; preload");
175 }
176 if (!this->_response.hasHeader ("Content-Security-Policy"))
177 {
178 this->_response.header (
179 "Content-Security-Policy",
180 "default-src 'self'; object-src 'none'; script-src 'self'; style-src 'self'; img-src 'self'");
181 }
182 if (!this->_response.hasHeader ("X-XSS-Protection"))
183 {
184 this->_response.header ("X-XSS-Protection", "1; mode=block");
185 }
186 if (!this->_response.hasHeader ("X-Content-Type-Options"))
187 {
188 this->_response.header ("X-Content-Type-Options", "nosniff");
189 }
190 if (!this->_response.hasHeader ("X-Frame-Options"))
191 {
192 this->_response.header ("X-Frame-Options", "SAMEORIGIN");
193 }
194
195 // write response headers.
196 this->_response.writeHeaders (*this);
197
198 // set encoding.
199 if (this->_response.hasHeader ("Transfer-Encoding"))
200 {
201 this->setEncoding (join::rsplit (this->_response.header ("Transfer-Encoding"), ","));
202 }
203 if (this->_response.hasHeader ("Content-Encoding"))
204 {
205 this->setEncoding (join::rsplit (this->_response.header ("Content-Encoding"), ","));
206 }
207 }
208
214 void sendError (const std::string& status, const std::string& reason)
215 {
216 // set error response.
217 this->_response.response (status, reason);
218
219 // stop keepalive.
220 this->_response.header ("Connection", "close");
221 this->_max = 0;
222
223 // send headers.
224 this->sendHeaders ();
225
226 // flush data.
227 this->flush ();
228 }
229
236 void sendRedirect (const std::string& status, const std::string& reason, const std::string& location = {})
237 {
238 std::string payload;
239
240 // set redirect response.
241 this->_response.response (status, reason);
242
243 // set redirect message payload.
244 if (!location.empty ())
245 {
246 payload += "<html>";
247 payload += "<head>";
248 payload += "<meta http-equiv=\"content-type\" content=\"text/html;charset=utf-8\">";
249 payload += "<title>" + status + " " + reason + "</title>";
250 payload += "</head>";
251 payload += "<body>";
252 payload += "<h1>" + status + " " + reason + "</h1>";
253 payload += "The document has moved <a href=\"" + location + "\">here</a>";
254 payload += "</body>";
255 payload += "</html>";
256 }
257
258 // set content.
259 if (payload.size ())
260 {
261 this->_response.header ("Content-Length", std::to_string (payload.size ()));
262 this->_response.header ("Content-Type", "text/html");
263 this->_response.header ("Cache-Control", "no-cache");
264 }
265
266 // send headers.
267 this->sendHeaders ();
268
269 // send payload.
270 if (payload.size ())
271 {
272 this->write (payload.c_str (), payload.size ());
273 }
274
275 // flush data.
276 this->flush ();
277 }
278
283 void sendFile (const std::string& path)
284 {
285 struct stat sbuf;
286
287 // get file.
288 void* addr = this->_server->_cache.get (path, sbuf);
289 if (addr == nullptr || S_ISDIR (sbuf.st_mode))
290 {
291 this->sendError ("404", "Not Found");
292 return;
293 }
294
295 // check modif time.
296 std::stringstream modifTime;
297 modifTime << std::put_time (std::gmtime (&sbuf.st_ctime), "%a, %d %b %Y %H:%M:%S GMT");
298 if (compareNoCase (this->_request.header ("If-Modified-Since"), modifTime.str ()))
299 {
300 this->sendRedirect ("304", "Not Modified");
301 return;
302 }
303
304 // set modif time.
305 this->_response.header ("Last-Modified", modifTime.str ());
306
307 // set content.
308 this->_response.header ("Content-Length", std::to_string (sbuf.st_size));
309 this->_response.header ("Content-Type", join::mime (path));
310 this->_response.header ("Cache-Control", "no-cache");
311
312 // send headers.
313 this->sendHeaders ();
314
315 // check method.
316 if (this->_request.method () == HttpMethod::Get)
317 {
318 // send file.
319 this->write (static_cast<char*> (addr), sbuf.st_size);
320 }
321
322 // flush data.
323 this->flush ();
324 }
325
331 bool hasHeader (const std::string& name) const
332 {
333 return this->_request.hasHeader (name);
334 }
335
341 std::string header (const std::string& name) const
342 {
343 return this->_request.header (name);
344 }
345
350 size_t contentLength () const
351 {
352 return this->_request.contentLength ();
353 }
354
360 void header (const std::string& name, const std::string& val)
361 {
362 return this->_response.header (name, val);
363 }
364
365 protected:
369 void work ()
370 {
371 fd_set setfd;
372 FD_ZERO (&setfd);
373 int fdmax = -1;
374
375 FD_SET (this->_server->_event, &setfd);
376 fdmax = std::max (fdmax, this->_server->_event);
377 FD_SET (this->_server->_acceptor.handle (), &setfd);
378 fdmax = std::max (fdmax, this->_server->_acceptor.handle ());
379
380 for (;;)
381 {
382 {
383 ScopedLock<Mutex> lock (this->_server->_mutex);
384
385 fd_set fdset = setfd;
386 int nset = ::select (fdmax + 1, &fdset, nullptr, nullptr, nullptr);
387 if (nset > 0)
388 {
389 if (FD_ISSET (this->_server->_event, &fdset))
390 {
391 uint64_t val = 0;
392 [[maybe_unused]] ssize_t bytes = ::read (this->_server->_event, &val, sizeof (uint64_t));
393 return;
394 }
395
396 if (FD_ISSET (this->_server->_acceptor.handle (), &fdset))
397 {
398 this->_sockbuf.socket () = this->_server->accept ();
399 this->_sockbuf.timeout (this->_server->keepAliveTimeout ());
400 }
401 }
402 }
403
404 this->processRequest ();
405 }
406 }
407
412 {
413 this->_max = this->_server->keepAliveMax ();
414
415 do
416 {
417 if (this->readRequest () == -1)
418 {
419 this->cleanUp ();
420 break;
421 }
422
423 this->writeResponse ();
424 this->cleanUp ();
425 }
426 while ((this->_max < 0) || (--this->_max != 0));
427
428 this->endRequest ();
429 }
430
436 {
437 // restore concrete stream.
438 this->clearEncoding ();
439
440 // prepare a standard response.
441 this->_response.response ("200", "OK");
442
443 // read request headers.
444 if (this->_request.readHeaders (*this) == -1)
445 {
447 {
448 this->sendError ("400", "Bad Request");
449 }
451 {
452 this->sendError ("405", "Method Not Allowed");
453 }
455 {
456 this->sendError ("494", "Request Header Too Large");
457 }
458 return -1;
459 }
460
461 // check host.
462 if (this->_request.host ().empty ())
463 {
464 this->sendError ("400", "Bad Request");
465 return -1;
466 }
467
468 // set encoding.
469 if (this->_request.hasHeader ("Transfer-Encoding"))
470 {
471 this->setEncoding (join::rsplit (this->_request.header ("Transfer-Encoding"), ","));
472 }
473 if (this->_request.hasHeader ("Content-Encoding"))
474 {
475 this->setEncoding (join::rsplit (this->_request.header ("Content-Encoding"), ","));
476 }
477
478 return 0;
479 }
480
485 {
486 Content* content = this->_server->findContent (this->_request.method (), this->_request.path ());
487 if (content == nullptr)
488 {
489 this->sendError ("404", "Not Found");
490 return;
491 }
492
493 if (content->access != nullptr)
494 {
495 if (!this->_request.hasHeader ("Authorization"))
496 {
497 this->sendError ("401", "Unauthorized");
498 return;
499 }
500
501 std::error_code err;
502 if (!content->access (this->_request.auth (), this->_request.credentials (), err))
503 {
504 if (err == HttpErrc::Unauthorized)
505 {
506 this->sendError ("401", "Unauthorized");
507 }
508 else if (err == HttpErrc::Forbidden)
509 {
510 this->sendError ("403", "Forbidden");
511 }
512 return;
513 }
514 }
515
516 std::string alias (content->alias);
517 if (!alias.empty ())
518 {
519 join::replaceAll (alias, "$root", this->_server->baseLocation ());
520 join::replaceAll (alias, "$scheme", this->_server->scheme ());
521 join::replaceAll (alias, "$host", this->_request.host ());
522 join::replaceAll (alias, "$port", std::to_string (this->localEndpoint ().port ()));
523 join::replaceAll (alias, "$path", this->_request.path ());
524 join::replaceAll (alias, "$query", this->_request.query ());
525 join::replaceAll (alias, "$urn", this->_request.urn ());
526 }
527
528 if (content->type == HttpContentType::Root)
529 {
530 this->sendFile (this->_server->baseLocation () + this->_request.path ());
531 }
532 else if (content->type == HttpContentType::Alias)
533 {
534 this->sendFile (alias);
535 }
536 else if (content->type == HttpContentType::Exec)
537 {
538 if (content->handler == nullptr)
539 {
540 this->sendError ("500", "Internal Server Error");
541 return;
542 }
543 content->handler (this);
544 }
545 else if (content->type == HttpContentType::Redirect)
546 {
547 if (this->_request.version () == "HTTP/1.1")
548 {
549 this->sendRedirect ("307", "Temporary Redirect", alias);
550 }
551 else
552 {
553 this->sendRedirect ("302", "Found", alias);
554 }
555 }
556 }
557
561 void cleanUp ()
562 {
563 this->_request.clear ();
564 this->_response.clear ();
565 }
566
571 {
572 this->disconnect ();
573 this->close ();
574 }
575
580 void setEncoding (const std::vector<std::string>& encodings)
581 {
582 for (auto const& encoding : encodings)
583 {
584 if (encoding.find ("gzip") != std::string::npos)
585 {
586 this->_streambuf = new Zstreambuf (this->_streambuf, Zstream::Gzip, this->_wrapped);
587 this->_wrapped = true;
588 }
589 else if (encoding.find ("deflate") != std::string::npos)
590 {
591 this->_streambuf = new Zstreambuf (this->_streambuf, Zstream::Deflate, this->_wrapped);
592 this->_wrapped = true;
593 }
594 else if (encoding.find ("chunked") != std::string::npos)
595 {
596 this->_streambuf = new Chunkstreambuf (this->_streambuf, this->_wrapped);
597 this->_wrapped = true;
598 }
599 }
600
601 this->set_rdbuf (this->_streambuf);
602 }
603
608 {
609 if (this->_wrapped && this->_streambuf)
610 {
611 delete this->_streambuf;
612 this->_streambuf = nullptr;
613 }
614
615 this->_streambuf = &this->_sockbuf;
616 this->_wrapped = false;
617
618 this->set_rdbuf (this->_streambuf);
619 }
620
622 int _max = 0;
623
626
629
631 std::streambuf* _streambuf = nullptr;
632
634 bool _wrapped = false;
635
638
641 };
642
646 template <class Protocol>
648 {
649 public:
652 using Handler = typename Content::Handler;
653 using Access = typename Content::Access;
654 using Endpoint = typename Protocol::Endpoint;
655 using Socket = typename Protocol::Socket;
656 using Acceptor = typename Protocol::Acceptor;
657
662 BasicHttpServer (size_t workers = std::thread::hardware_concurrency ())
663 : _event (eventfd (0, EFD_NONBLOCK | EFD_CLOEXEC | EFD_SEMAPHORE))
664 , _nworkers (workers)
665 , _baseLocation ("/var/www")
666 , _keepTimeout (10)
667 {
668 [[maybe_unused]] int res = chdir (this->_baseLocation.c_str ());
669 }
670
675 BasicHttpServer (const BasicHttpServer& other) = delete;
676
683
689
696
701 {
702 this->_acceptor.close ();
703 this->_contents.clear ();
704 ::close (this->_event);
705 }
706
712 int create (const Endpoint& endpoint) noexcept
713 {
714 if (this->_acceptor.create (endpoint) == -1)
715 {
716 return -1;
717 }
718
719 for (size_t nworkers = 0; nworkers < this->_nworkers; ++nworkers)
720 {
721 this->_workers.emplace_back (new Worker (this));
722 }
723
724 return 0;
725 }
726
730 void close () noexcept
731 {
732 uint64_t val = this->_nworkers;
733 [[maybe_unused]] ssize_t bytes = ::write (this->_event, &val, sizeof (uint64_t));
734 this->_workers.clear ();
735 this->_acceptor.close ();
736 }
737
742 virtual Socket accept () const
743 {
744 return Socket (this->_acceptor.accept ());
745 }
746
751 void baseLocation (const std::string& path)
752 {
753 this->_baseLocation = path;
754
755 if (*this->_baseLocation.rbegin () == '/')
756 {
757 this->_baseLocation.pop_back ();
758 }
759
760 [[maybe_unused]] int res = chdir (this->_baseLocation.c_str ());
761 }
762
767 const std::string& baseLocation () const
768 {
769 return this->_baseLocation;
770 }
771
777 void keepAlive (std::chrono::seconds timeout, int max = 1000)
778 {
779 this->_keepTimeout = timeout;
780 this->_keepMax = max;
781 }
782
787 std::chrono::seconds keepAliveTimeout () const
788 {
789 return this->_keepTimeout;
790 }
791
796 int keepAliveMax () const
797 {
798 return this->_keepMax;
799 }
800
805 virtual std::string scheme () const
806 {
807 return "http";
808 }
809
817 Content* addDocumentRoot (const std::string& dir, const std::string& name, const Access& access = nullptr)
818 {
819 Content* newEntry = new Content;
820 if (newEntry != nullptr)
821 {
822 newEntry->methods = Head | Get;
823 newEntry->type = Root;
824 newEntry->directory = dir;
825 newEntry->name = name;
826 newEntry->handler = nullptr;
827 newEntry->access = access;
828 this->_contents.emplace_back (newEntry);
829 }
830
831 return newEntry;
832 }
833
842 Content* addAlias (const std::string& dir, const std::string& name, const std::string& alias,
843 const Access& access = nullptr)
844 {
845 Content* newEntry = new Content;
846 if (newEntry != nullptr)
847 {
848 newEntry->methods = Head | Get;
849 newEntry->type = Alias;
850 newEntry->directory = dir;
851 newEntry->name = name;
852 newEntry->alias = alias;
853 newEntry->handler = nullptr;
854 newEntry->access = access;
855 this->_contents.emplace_back (newEntry);
856 }
857
858 return newEntry;
859 }
860
870 Content* addExecute (const HttpMethod methods, const std::string& dir, const std::string& name,
871 const Handler& handler, const Access& access = nullptr)
872 {
873 Content* newEntry = new Content;
874 if (newEntry != nullptr)
875 {
876 newEntry->methods = methods;
877 newEntry->type = Exec;
878 newEntry->directory = dir;
879 newEntry->name = name;
880 newEntry->handler = handler;
881 newEntry->access = access;
882 this->_contents.emplace_back (newEntry);
883 }
884
885 return newEntry;
886 }
887
896 Content* addRedirect (const std::string& dir, const std::string& name, const std::string& location,
897 const Access& access = nullptr)
898 {
899 Content* newEntry = new Content;
900 if (newEntry != nullptr)
901 {
902 newEntry->methods = Head | Get | Put | Post | Delete;
903 newEntry->type = Redirect;
904 newEntry->directory = dir;
905 newEntry->name = name;
906 newEntry->alias = location;
907 newEntry->handler = nullptr;
908 newEntry->access = access;
909 this->_contents.emplace_back (newEntry);
910 }
911
912 return newEntry;
913 }
914
915 protected:
922 Content* findContent (HttpMethod method, const std::string& path) const
923 {
924 std::string directory = join::base (path);
925 std::string name = join::filename (path);
926
927 for (auto const& content : this->_contents)
928 {
929 if (content->methods & method)
930 {
931 if (fnmatch (content->directory.c_str (), directory.c_str (), FNM_CASEFOLD) == 0)
932 {
933 if (fnmatch (content->name.c_str (), name.c_str (), FNM_CASEFOLD) == 0)
934 {
935 return content.get ();
936 }
937 }
938 }
939 }
940
941 return nullptr;
942 }
943
946
948 int _event = -1;
949
951 size_t _nworkers;
952
954 std::vector<std::unique_ptr<Worker>> _workers;
955
958
960 std::vector<std::unique_ptr<Content>> _contents;
961
963 std::string _baseLocation;
964
966 std::chrono::seconds _keepTimeout;
967
969 int _keepMax = 1000;
970
973
975 friend Worker;
976 };
977
981 template <class Protocol>
982 class BasicHttpSecureServer : public BasicHttpServer<Protocol>
983 {
984 public:
986 using Socket = typename Protocol::Socket;
987
993 BasicHttpSecureServer (TlsContext ctx, size_t workers = std::thread::hardware_concurrency ())
994 : BasicHttpServer<Protocol> (workers)
995 , _ctx (std::move (ctx))
996 {
997 }
998
1004
1011
1017
1024
1029 {
1030 // join the workers while the context they use is still alive.
1031 this->close ();
1032 }
1033
1038 Socket accept () const override
1039 {
1040 Socket sock (this->_acceptor.accept (), this->_ctx);
1041 if (sock.deferHandshake () == -1)
1042 {
1043 sock.close ();
1044 }
1045 return sock;
1046 }
1047
1052 virtual std::string scheme () const override
1053 {
1054 return "https";
1055 }
1056
1059
1061 friend Worker;
1062 };
1063}
1064
1065#endif
basic HTTPS server.
Definition http_server.hpp:983
TlsContext _ctx
TLS context used to wrap the accepted connections.
Definition http_server.hpp:1058
friend Worker
friendship with worker.
Definition http_server.hpp:1061
BasicHttpSecureServer(const BasicHttpSecureServer &other)=delete
create instance by copy.
typename Protocol::Socket Socket
Definition http_server.hpp:986
virtual ~BasicHttpSecureServer()
destroy the HTTPS server.
Definition http_server.hpp:1028
BasicHttpSecureServer & operator=(const BasicHttpSecureServer &other)=delete
assign instance by copy.
Socket accept() const override
accept new connection and fill in the client object with connection parameters.
Definition http_server.hpp:1038
virtual std::string scheme() const override
get scheme.
Definition http_server.hpp:1052
BasicHttpSecureServer(TlsContext ctx, size_t workers=std::thread::hardware_concurrency())
create the HTTPS server instance using the given context.
Definition http_server.hpp:993
BasicHttpSecureServer(BasicHttpSecureServer &&other)=delete
create instance by move.
basic HTTP server.
Definition http_server.hpp:648
BasicHttpServer(size_t workers=std::thread::hardware_concurrency())
create the HTTP server instance.
Definition http_server.hpp:662
typename Content::Handler Handler
Definition http_server.hpp:652
typename Protocol::Socket Socket
Definition http_server.hpp:655
Content * addAlias(const std::string &dir, const std::string &name, const std::string &alias, const Access &access=nullptr)
map an URL to filesystem replacing URL path by the specified path.
Definition http_server.hpp:842
typename Content::Access Access
Definition http_server.hpp:653
std::vector< std::unique_ptr< Worker > > _workers
workers.
Definition http_server.hpp:954
std::string _baseLocation
base location.
Definition http_server.hpp:963
Content * addExecute(const HttpMethod methods, const std::string &dir, const std::string &name, const Handler &handler, const Access &access=nullptr)
map an URL to a callback.
Definition http_server.hpp:870
void keepAlive(std::chrono::seconds timeout, int max=1000)
set HTTP keep alive.
Definition http_server.hpp:777
const std::string & baseLocation() const
get file base location.
Definition http_server.hpp:767
typename Protocol::Endpoint Endpoint
Definition http_server.hpp:654
Content * addRedirect(const std::string &dir, const std::string &name, const std::string &location, const Access &access=nullptr)
map an URL to a redirection.
Definition http_server.hpp:896
Acceptor _acceptor
acceptor.
Definition http_server.hpp:945
void baseLocation(const std::string &path)
set file base location.
Definition http_server.hpp:751
int _keepMax
keep alive max.
Definition http_server.hpp:969
typename Protocol::Acceptor Acceptor
Definition http_server.hpp:656
virtual Socket accept() const
accept new connection.
Definition http_server.hpp:742
void close() noexcept
close server.
Definition http_server.hpp:730
virtual ~BasicHttpServer()
destroy the HTTP server.
Definition http_server.hpp:700
Content * findContent(HttpMethod method, const std::string &path) const
find content.
Definition http_server.hpp:922
Cache _cache
file cache.
Definition http_server.hpp:972
std::vector< std::unique_ptr< Content > > _contents
contents.
Definition http_server.hpp:960
BasicHttpServer & operator=(const BasicHttpServer &other)=delete
assign instance by copy.
Content * addDocumentRoot(const std::string &dir, const std::string &name, const Access &access=nullptr)
map an URL to filesystem adding URL path to the base location.
Definition http_server.hpp:817
friend Worker
friendship with worker.
Definition http_server.hpp:975
int keepAliveMax() const
get HTTP keep alive max.
Definition http_server.hpp:796
int _event
gracefully stop all workers.
Definition http_server.hpp:948
int create(const Endpoint &endpoint) noexcept
create server.
Definition http_server.hpp:712
BasicHttpContent< Protocol > Content
Definition http_server.hpp:651
std::chrono::seconds keepAliveTimeout() const
get HTTP keep alive timeout.
Definition http_server.hpp:787
size_t _nworkers
number of workers.
Definition http_server.hpp:951
std::chrono::seconds _keepTimeout
keep alive timeout.
Definition http_server.hpp:966
BasicHttpServer(BasicHttpServer &&other)=delete
create instance by move.
Mutex _mutex
accept protection mutex.
Definition http_server.hpp:957
BasicHttpServer(const BasicHttpServer &other)=delete
create instance by copy.
virtual std::string scheme() const
get scheme.
Definition http_server.hpp:805
basic HTTP worker.
Definition http_server.hpp:85
void setEncoding(const std::vector< std::string > &encodings)
set stream encoding.
Definition http_server.hpp:580
void clearEncoding()
clear stream encoding.
Definition http_server.hpp:607
std::string header(const std::string &name) const
get HTTP request header by name.
Definition http_server.hpp:341
std::streambuf * _streambuf
HTTP stream buffer.
Definition http_server.hpp:631
bool hasHeader(const std::string &name) const
checks if there is a HTTP request header with the specified name.
Definition http_server.hpp:331
BasicHttpWorker(BasicHttpWorker &&other)=delete
create instance by move.
HttpRequest _request
HTTP request.
Definition http_server.hpp:625
void sendHeaders()
send headers.
Definition http_server.hpp:139
void writeResponse()
write the HTTP response.
Definition http_server.hpp:484
void sendFile(const std::string &path)
send a file.
Definition http_server.hpp:283
void header(const std::string &name, const std::string &val)
add header to the HTTP response.
Definition http_server.hpp:360
int _max
max requests.
Definition http_server.hpp:622
BasicHttpWorker(const BasicHttpWorker &other)=delete
create instance by copy.
void cleanUp()
clean all.
Definition http_server.hpp:561
BasicHttpWorker & operator=(const BasicHttpWorker &other)=delete
assign instance by copy.
bool _wrapped
HTTP stream status.
Definition http_server.hpp:634
void sendRedirect(const std::string &status, const std::string &reason, const std::string &location={})
send redirect message.
Definition http_server.hpp:236
void endRequest()
end the HTTP request.
Definition http_server.hpp:570
HttpResponse _response
HTTP response.
Definition http_server.hpp:628
Server * _server
HTTP server.
Definition http_server.hpp:637
int readRequest()
read the HTTP request.
Definition http_server.hpp:435
void processRequest()
process the HTTP request.
Definition http_server.hpp:411
virtual ~BasicHttpWorker()
destroy worker thread.
Definition http_server.hpp:131
Thread _thread
thread.
Definition http_server.hpp:640
void sendError(const std::string &status, const std::string &reason)
send error message.
Definition http_server.hpp:214
void work()
worker thread routine.
Definition http_server.hpp:369
size_t contentLength() const
get content length.
Definition http_server.hpp:350
BasicHttpWorker(Server *server)
create the worker instance.
Definition http_server.hpp:94
File cache.
Definition cache.hpp:45
void * get(const std::string &fileName, struct stat &sbuf)
get or create the cache entry for the given file.
Definition cache.cpp:51
chunk stream buffer.
Definition chunk_stream.hpp:41
size_t contentLength() const
get content length.
Definition http_message.cpp:283
const std::string & version() const
get HTTP version.
Definition http_message.cpp:185
virtual int readHeaders(std::istream &in)
read HTTP header from the given input stream.
Definition http_message.cpp:304
bool hasHeader(const std::string &name) const
checks if there is a header with the specified name.
Definition http_message.cpp:203
std::string header(const std::string &name) const
get header by name.
Definition http_message.cpp:212
HTTP request.
Definition http_message.hpp:352
const std::string & path() const
get path.
Definition http_message.cpp:483
std::string urn() const
get URN.
Definition http_message.cpp:601
HttpMethod method() const
get request method.
Definition http_message.cpp:442
virtual void clear() override
clear HTTP message.
Definition http_message.cpp:654
std::string host() const
get host.
Definition http_message.cpp:610
std::string query() const
get query.
Definition http_message.cpp:585
HTTP response.
Definition http_message.hpp:558
void response(const std::string &status, const std::string &reason={})
set HTTP response status.
Definition http_message.cpp:961
virtual int writeHeaders(std::ostream &out) const override
write HTTP headers to the given output stream.
Definition http_message.cpp:982
virtual void clear() override
clear HTTP message.
Definition http_message.cpp:971
class used to protect shared data from being simultaneously accessed by multiple threads.
Definition mutex.hpp:37
class owning a mutex for the duration of a scoped block.
Definition mutex.hpp:246
thread class.
Definition thread.hpp:147
void join() noexcept
block the current thread until the running thread finishes its execution.
Definition thread.cpp:252
TLS/DTLS context.
Definition tls_context.hpp:42
@ Deflate
Definition zstream.hpp:132
@ Gzip
Definition zstream.hpp:134
zlib stream buffer.
Definition zstream.hpp:44
Definition acceptor.hpp:32
HttpMethod
enumeration of HTTP methods.
Definition http_message.hpp:111
@ Post
Definition http_message.hpp:115
@ Put
Definition http_message.hpp:114
@ Delete
Definition http_message.hpp:117
@ Head
Definition http_message.hpp:112
@ Get
Definition http_message.hpp:113
std::string base(const std::string &filepath)
get base path of the specified file.
Definition filesystem.hpp:41
std::string filename(const std::string &filepath)
get file name of the specified file.
Definition filesystem.hpp:56
std::string mime(const std::string &filepath)
get mime type of the specified file.
Definition filesystem.hpp:86
bool compareNoCase(const std::string &a, const std::string &b)
case insensitive string comparison.
Definition utils.hpp:195
HttpContentType
HTTP content Type.
Definition http_server.hpp:55
@ Root
Definition http_server.hpp:56
@ Alias
Definition http_server.hpp:57
@ Exec
Definition http_server.hpp:58
@ Redirect
Definition http_server.hpp:59
thread_local std::error_code lastError
last error.
Definition error.cpp:32
std::vector< std::string > rsplit(const std::string &in, const std::string &delim)
split a string in reverse order using a delimiter.
Definition utils.hpp:282
std::string & replaceAll(std::string &str, const std::string &toReplace, const std::string &by)
replace all occurrences of a substring.
Definition utils.hpp:239
Definition error.hpp:144
basic HTTP content.
Definition http_server.hpp:67
std::string directory
Definition http_server.hpp:73
std::string alias
Definition http_server.hpp:75
HttpContentType type
Definition http_server.hpp:72
HttpMethod methods
Definition http_server.hpp:71
std::function< void(typename Protocol::Worker *)> Handler
Definition http_server.hpp:68
Handler handler
Definition http_server.hpp:76
std::function< bool(const std::string &, const std::string &, std::error_code &)> Access
Definition http_server.hpp:69
std::string name
Definition http_server.hpp:74
Access access
Definition http_server.hpp:77
uint16_t port
Definition tcp_acceptor_test.cpp:36
std::string path
Definition unix_acceptor_test.cpp:37