25#ifndef JOIN_SERVICES_HTTPSERVER_HPP
26#define JOIN_SERVICES_HTTPSERVER_HPP
32#include <join/version.hpp>
37#include <sys/eventfd.h>
61 template <
class Protocol>
64 using Handler = std::function<void (
typename Protocol::Worker*)>;
65 using Access = std::function<bool (
const std::string&,
const std::string&, std::error_code&)>;
79 template <
class Protocol>
143 std::stringstream gmt;
144 std::time_t ti = std::time (
nullptr);
145 gmt << std::put_time (std::gmtime (&ti),
"%a, %d %b %Y %H:%M:%S GMT");
156 std::stringstream keepAlive;
170 this->
_response.
header (
"Strict-Transport-Security",
"max-age=31536000; includeSubDomains; preload");
175 "Content-Security-Policy",
176 "default-src 'self'; object-src 'none'; script-src 'self'; style-src 'self'; img-src 'self'");
210 void sendError (
const std::string& status,
const std::string& reason)
232 void sendRedirect (
const std::string& status,
const std::string& reason,
const std::string& location = {})
240 if (!location.empty ())
244 payload +=
"<meta http-equiv=\"content-type\" content=\"text/html;charset=utf-8\">";
245 payload +=
"<title>" + status +
" " + reason +
"</title>";
246 payload +=
"</head>";
248 payload +=
"<h1>" + status +
" " + reason +
"</h1>";
249 payload +=
"The document has moved <a href=\"" + location +
"\">here</a>";
250 payload +=
"</body>";
251 payload +=
"</html>";
257 this->
_response.
header (
"Content-Length", std::to_string (payload.size ()));
268 this->write (payload.c_str (), payload.size ());
285 if (addr ==
nullptr || S_ISDIR (sbuf.st_mode))
292 std::stringstream modifTime;
293 modifTime << std::put_time (std::gmtime (&sbuf.st_ctime),
"%a, %d %b %Y %H:%M:%S GMT");
304 this->
_response.
header (
"Content-Length", std::to_string (sbuf.st_size));
315 this->write (
static_cast<char*
> (addr), sbuf.st_size);
337 std::string
header (
const std::string& name)
const
356 void header (
const std::string& name,
const std::string& val)
381 fd_set fdset = setfd;
382 int nset = ::select (fdmax + 1, &fdset,
nullptr,
nullptr,
nullptr);
388 [[maybe_unused]] ssize_t bytes = ::read (this->
_server->
_event, &val, sizeof (uint64_t));
421 }
while ((this->
_max < 0) || (--this->
_max != 0));
447 this->
sendError (
"405",
"Method Not Allowed");
451 this->
sendError (
"494",
"Request Header Too Large");
482 if (content ==
nullptr)
488 if (content->
access !=
nullptr)
497 if (!content->
access (this->_request.auth (), this->_request.credentials (), err))
511 std::string alias (content->
alias);
533 if (content->
handler ==
nullptr)
535 this->
sendError (
"500",
"Internal Server Error");
544 this->
sendRedirect (
"307",
"Temporary Redirect", alias);
577 for (
auto const& encoding : encodings)
579 if (encoding.find (
"gzip") != std::string::npos)
584 else if (encoding.find (
"deflate") != std::string::npos)
589 else if (encoding.find (
"chunked") != std::string::npos)
641 template <
class Protocol>
650 using Socket =
typename Protocol::Socket;
658 :
_event (eventfd (0, EFD_NONBLOCK | EFD_CLOEXEC | EFD_SEMAPHORE))
663 [[maybe_unused]]
int res = chdir (this->
_baseLocation.c_str ());
709 if (this->
_acceptor.create (endpoint) == -1)
714 for (
size_t nworkers = 0; nworkers < this->
_nworkers; ++nworkers)
728 [[maybe_unused]] ssize_t bytes = ::write (this->
_event, &val,
sizeof (uint64_t));
755 [[maybe_unused]]
int res = chdir (this->
_baseLocation.c_str ());
772 void keepAlive (std::chrono::seconds timeout,
int max = 1000)
815 if (newEntry !=
nullptr)
820 newEntry->
name = name;
822 newEntry->
access = access;
837 Content*
addAlias (
const std::string& dir,
const std::string& name,
const std::string& alias,
838 const Access& access =
nullptr)
841 if (newEntry !=
nullptr)
846 newEntry->
name = name;
847 newEntry->
alias = alias;
849 newEntry->
access = access;
869 if (newEntry !=
nullptr)
874 newEntry->
name = name;
876 newEntry->
access = access;
892 const Access& access =
nullptr)
895 if (newEntry !=
nullptr)
900 newEntry->
name = name;
901 newEntry->
alias = location;
903 newEntry->
access = access;
922 for (
auto const& content : this->
_contents)
924 if (content->methods & method)
926 if (fnmatch (content->directory.c_str (), directory.c_str (), FNM_CASEFOLD) == 0)
928 if (fnmatch (content->name.c_str (), name.c_str (), FNM_CASEFOLD) == 0)
930 return content.get ();
976 template <
class Protocol>
985 using Socket =
typename Protocol::Socket;
1034 return this->
_acceptor.acceptEncrypted ();
1055 return this->
_acceptor.setCaCertificate (caFile);
1065 return this->
_acceptor.setVerify (verify, depth);
1075 return this->
_acceptor.setCipher (cipher);
1085 return this->
_acceptor.setCipher_1_3 (cipher);
1088#if OPENSSL_VERSION_NUMBER >= 0x30000000L
1094 int setCurve (
const std::string& curves)
1096 return this->
_acceptor.setCurve (curves);
basic HTTPS server.
Definition httpserver.hpp:978
BasicHttpSecureServer(size_t workers=std::thread::hardware_concurrency())
create the HTTPS server instance.
Definition httpserver.hpp:992
typename Protocol::Acceptor Acceptor
Definition httpserver.hpp:986
typename Protocol::Endpoint Endpoint
Definition httpserver.hpp:984
int setCertificate(const std::string &cert, const std::string &key="")
set the certificate and the private key.
Definition httpserver.hpp:1043
typename Content::Handler Handler
Definition httpserver.hpp:982
friend Worker
friendship with worker.
Definition httpserver.hpp:1110
BasicHttpSecureServer(const BasicHttpSecureServer &other)=delete
create instance by copy.
int setCaCertificate(const std::string &caFile)
Set the location of the trusted CA certificate.
Definition httpserver.hpp:1053
typename Protocol::Socket Socket
Definition httpserver.hpp:985
BasicHttpSecureServer & operator=(const BasicHttpSecureServer &other)=delete
assign instance by copy.
int setCipher(const std::string &cipher)
set the cipher list (TLSv1.2 and below).
Definition httpserver.hpp:1073
Socket accept() const override
accept new connection and fill in the client object with connection parameters.
Definition httpserver.hpp:1032
virtual ~BasicHttpSecureServer()=default
destroy the HTTPS server.
typename Content::Access Access
Definition httpserver.hpp:983
virtual std::string scheme() const override
get scheme.
Definition httpserver.hpp:1104
void setVerify(bool verify, int depth=-1)
Enable/Disable the verification of the peer certificate.
Definition httpserver.hpp:1063
BasicHttpSecureServer(BasicHttpSecureServer &&other)=delete
create instance by move.
int setCipher_1_3(const std::string &cipher)
set the cipher list (TLSv1.3).
Definition httpserver.hpp:1083
basic HTTP server.
Definition httpserver.hpp:643
BasicHttpServer(size_t workers=std::thread::hardware_concurrency())
create the HTTP server instance.
Definition httpserver.hpp:657
typename Content::Handler Handler
Definition httpserver.hpp:647
typename Protocol::Socket Socket
Definition httpserver.hpp:650
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 httpserver.hpp:837
typename Content::Access Access
Definition httpserver.hpp:648
std::vector< std::unique_ptr< Worker > > _workers
workers.
Definition httpserver.hpp:949
std::string _baseLocation
base location.
Definition httpserver.hpp:958
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 httpserver.hpp:865
void keepAlive(std::chrono::seconds timeout, int max=1000)
set HTTP keep alive.
Definition httpserver.hpp:772
const std::string & baseLocation() const
get file base location.
Definition httpserver.hpp:762
typename Protocol::Endpoint Endpoint
Definition httpserver.hpp:649
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 httpserver.hpp:891
Acceptor _acceptor
acceptor.
Definition httpserver.hpp:940
void baseLocation(const std::string &path)
set file base location.
Definition httpserver.hpp:746
int _keepMax
keep alive max.
Definition httpserver.hpp:964
typename Protocol::Acceptor Acceptor
Definition httpserver.hpp:651
virtual Socket accept() const
accept new connection.
Definition httpserver.hpp:737
void close() noexcept
close server.
Definition httpserver.hpp:725
virtual ~BasicHttpServer()
destroy the HTTP server.
Definition httpserver.hpp:695
Content * findContent(HttpMethod method, const std::string &path) const
find content.
Definition httpserver.hpp:917
Cache _cache
file cache.
Definition httpserver.hpp:967
std::vector< std::unique_ptr< Content > > _contents
contents.
Definition httpserver.hpp:955
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 httpserver.hpp:812
friend Worker
friendship with worker.
Definition httpserver.hpp:970
int keepAliveMax() const
get HTTP keep alive max.
Definition httpserver.hpp:791
int _event
gracefully stop all workers.
Definition httpserver.hpp:943
int create(const Endpoint &endpoint) noexcept
create server.
Definition httpserver.hpp:707
BasicHttpContent< Protocol > Content
Definition httpserver.hpp:646
std::chrono::seconds keepAliveTimeout() const
get HTTP keep alive timeout.
Definition httpserver.hpp:782
size_t _nworkers
number of workers.
Definition httpserver.hpp:946
std::chrono::seconds _keepTimeout
keep alive timeout.
Definition httpserver.hpp:961
BasicHttpServer(BasicHttpServer &&other)=delete
create instance by move.
Mutex _mutex
accept protection mutex.
Definition httpserver.hpp:952
BasicHttpServer(const BasicHttpServer &other)=delete
create instance by copy.
virtual std::string scheme() const
get scheme.
Definition httpserver.hpp:800
basic HTTP worker.
Definition httpserver.hpp:81
void setEncoding(const std::vector< std::string > &encodings)
set stream encoding.
Definition httpserver.hpp:575
void clearEncoding()
clear stream encoding.
Definition httpserver.hpp:602
std::string header(const std::string &name) const
get HTTP request header by name.
Definition httpserver.hpp:337
std::streambuf * _streambuf
HTTP stream buffer.
Definition httpserver.hpp:626
bool hasHeader(const std::string &name) const
checks if there is a HTTP request header with the specified name.
Definition httpserver.hpp:327
BasicHttpWorker(BasicHttpWorker &&other)=delete
create instance by move.
HttpRequest _request
HTTP request.
Definition httpserver.hpp:620
void sendHeaders()
send headers.
Definition httpserver.hpp:135
void writeResponse()
write the HTTP response.
Definition httpserver.hpp:479
void sendFile(const std::string &path)
send a file.
Definition httpserver.hpp:279
void header(const std::string &name, const std::string &val)
add header to the HTTP response.
Definition httpserver.hpp:356
int _max
max requests.
Definition httpserver.hpp:617
BasicHttpWorker(const BasicHttpWorker &other)=delete
create instance by copy.
void cleanUp()
clean all.
Definition httpserver.hpp:556
BasicHttpWorker & operator=(const BasicHttpWorker &other)=delete
assign instance by copy.
bool _wrapped
HTTP stream status.
Definition httpserver.hpp:629
void sendRedirect(const std::string &status, const std::string &reason, const std::string &location={})
send redirect message.
Definition httpserver.hpp:232
void endRequest()
end the HTTP request.
Definition httpserver.hpp:565
HttpResponse _response
HTTP response.
Definition httpserver.hpp:623
Server * _server
HTTP server.
Definition httpserver.hpp:632
int readRequest()
read the HTTP request.
Definition httpserver.hpp:430
void processRequest()
process the HTTP request.
Definition httpserver.hpp:407
virtual ~BasicHttpWorker()
destroy worker thread.
Definition httpserver.hpp:127
Thread _thread
thread.
Definition httpserver.hpp:635
void sendError(const std::string &status, const std::string &reason)
send error message.
Definition httpserver.hpp:210
void work()
worker thread routine.
Definition httpserver.hpp:365
size_t contentLength() const
get content length.
Definition httpserver.hpp:346
BasicHttpWorker(Server *server)
create the worker instance.
Definition httpserver.hpp:90
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:52
chunk stream buffer.
Definition chunkstream.hpp:37
size_t contentLength() const
get content length.
Definition httpmessage.cpp:283
const std::string & version() const
get HTTP version.
Definition httpmessage.cpp:185
virtual int readHeaders(std::istream &in)
read HTTP header from the given input stream.
Definition httpmessage.cpp:304
bool hasHeader(const std::string &name) const
checks if there is a header with the specified name.
Definition httpmessage.cpp:203
std::string header(const std::string &name) const
get header by name.
Definition httpmessage.cpp:212
HTTP request.
Definition httpmessage.hpp:353
const std::string & path() const
get path.
Definition httpmessage.cpp:483
std::string urn() const
get URN.
Definition httpmessage.cpp:601
HttpMethod method() const
get request method.
Definition httpmessage.cpp:442
virtual void clear() override
clear HTTP message.
Definition httpmessage.cpp:654
std::string host() const
get host.
Definition httpmessage.cpp:610
std::string query() const
get query.
Definition httpmessage.cpp:585
HTTP response.
Definition httpmessage.hpp:559
void response(const std::string &status, const std::string &reason={})
set HTTP response status.
Definition httpmessage.cpp:961
virtual int writeHeaders(std::ostream &out) const override
write HTTP headers to the given output stream.
Definition httpmessage.cpp:982
virtual void clear() override
clear HTTP message.
Definition httpmessage.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:148
void join() noexcept
block the current thread until the running thread finishes its execution.
Definition thread.cpp:251
@ Deflate
Definition zstream.hpp:128
@ Gzip
Definition zstream.hpp:130
zlib stream buffer.
Definition zstream.hpp:40
const std::string key(65, 'a')
key.
Definition acceptor.hpp:32
HttpMethod
enumeration of HTTP methods.
Definition httpmessage.hpp:112
@ Post
Definition httpmessage.hpp:116
@ Put
Definition httpmessage.hpp:115
@ Delete
Definition httpmessage.hpp:118
@ Head
Definition httpmessage.hpp:113
@ Get
Definition httpmessage.hpp:114
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:196
HttpContentType
HTTP content Type.
Definition httpserver.hpp:51
@ Root
Definition httpserver.hpp:52
@ Alias
Definition httpserver.hpp:53
@ Exec
Definition httpserver.hpp:54
@ Redirect
Definition httpserver.hpp:55
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:283
std::string & replaceAll(std::string &str, const std::string &toReplace, const std::string &by)
replace all occurrences of a substring.
Definition utils.hpp:240
basic HTTP content.
Definition httpserver.hpp:63
std::string directory
Definition httpserver.hpp:69
std::string alias
Definition httpserver.hpp:71
HttpContentType type
Definition httpserver.hpp:68
HttpMethod methods
Definition httpserver.hpp:67
std::function< void(typename Protocol::Worker *)> Handler
Definition httpserver.hpp:64
Handler handler
Definition httpserver.hpp:72
std::function< bool(const std::string &, const std::string &, std::error_code &)> Access
Definition httpserver.hpp:65
std::string name
Definition httpserver.hpp:70
Access access
Definition httpserver.hpp:73
uint16_t port
Definition tcpacceptor_test.cpp:36
std::string path
Definition unixstreamacceptor_test.cpp:34