25#ifndef JOIN_SERVICES_HTTP_SERVER_HPP
26#define JOIN_SERVICES_HTTP_SERVER_HPP
35#include <join/version.hpp>
41#include <sys/eventfd.h>
65 template <
class Protocol>
68 using Handler = std::function<void (
typename Protocol::Worker*)>;
69 using Access = std::function<bool (
const std::string&,
const std::string&, std::error_code&)>;
83 template <
class Protocol>
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");
160 std::stringstream keepAlive;
172 if ((this->
_server->
scheme () ==
"https") && !this->_response.hasHeader (
"Strict-Transport-Security"))
174 this->
_response.
header (
"Strict-Transport-Security",
"max-age=31536000; includeSubDomains; preload");
179 "Content-Security-Policy",
180 "default-src 'self'; object-src 'none'; script-src 'self'; style-src 'self'; img-src 'self'");
214 void sendError (
const std::string& status,
const std::string& reason)
236 void sendRedirect (
const std::string& status,
const std::string& reason,
const std::string& location = {})
244 if (!location.empty ())
248 payload +=
"<meta http-equiv=\"content-type\" content=\"text/html;charset=utf-8\">";
249 payload +=
"<title>" + status +
" " + reason +
"</title>";
250 payload +=
"</head>";
252 payload +=
"<h1>" + status +
" " + reason +
"</h1>";
253 payload +=
"The document has moved <a href=\"" + location +
"\">here</a>";
254 payload +=
"</body>";
255 payload +=
"</html>";
261 this->
_response.
header (
"Content-Length", std::to_string (payload.size ()));
272 this->write (payload.c_str (), payload.size ());
289 if (addr ==
nullptr || S_ISDIR (sbuf.st_mode))
296 std::stringstream modifTime;
297 modifTime << std::put_time (std::gmtime (&sbuf.st_ctime),
"%a, %d %b %Y %H:%M:%S GMT");
308 this->
_response.
header (
"Content-Length", std::to_string (sbuf.st_size));
319 this->write (
static_cast<char*
> (addr), sbuf.st_size);
341 std::string
header (
const std::string& name)
const
360 void header (
const std::string& name,
const std::string& val)
385 fd_set fdset = setfd;
386 int nset = ::select (fdmax + 1, &fdset,
nullptr,
nullptr,
nullptr);
392 [[maybe_unused]] ssize_t bytes = ::read (this->
_server->
_event, &val, sizeof (uint64_t));
426 while ((this->
_max < 0) || (--this->
_max != 0));
452 this->
sendError (
"405",
"Method Not Allowed");
456 this->
sendError (
"494",
"Request Header Too Large");
487 if (content ==
nullptr)
493 if (content->
access !=
nullptr)
502 if (!content->
access (this->_request.auth (), this->_request.credentials (), err))
516 std::string alias (content->
alias);
538 if (content->
handler ==
nullptr)
540 this->
sendError (
"500",
"Internal Server Error");
549 this->
sendRedirect (
"307",
"Temporary Redirect", alias);
582 for (
auto const& encoding : encodings)
584 if (encoding.find (
"gzip") != std::string::npos)
589 else if (encoding.find (
"deflate") != std::string::npos)
594 else if (encoding.find (
"chunked") != std::string::npos)
646 template <
class Protocol>
655 using Socket =
typename Protocol::Socket;
663 :
_event (eventfd (0, EFD_NONBLOCK | EFD_CLOEXEC | EFD_SEMAPHORE))
668 [[maybe_unused]]
int res = chdir (this->
_baseLocation.c_str ());
714 if (this->
_acceptor.create (endpoint) == -1)
719 for (
size_t nworkers = 0; nworkers < this->
_nworkers; ++nworkers)
733 [[maybe_unused]] ssize_t bytes = ::write (this->
_event, &val,
sizeof (uint64_t));
760 [[maybe_unused]]
int res = chdir (this->
_baseLocation.c_str ());
777 void keepAlive (std::chrono::seconds timeout,
int max = 1000)
820 if (newEntry !=
nullptr)
825 newEntry->
name = name;
827 newEntry->
access = access;
842 Content*
addAlias (
const std::string& dir,
const std::string& name,
const std::string& alias,
843 const Access& access =
nullptr)
846 if (newEntry !=
nullptr)
851 newEntry->
name = name;
852 newEntry->
alias = alias;
854 newEntry->
access = access;
874 if (newEntry !=
nullptr)
879 newEntry->
name = name;
881 newEntry->
access = access;
897 const Access& access =
nullptr)
900 if (newEntry !=
nullptr)
905 newEntry->
name = name;
906 newEntry->
alias = location;
908 newEntry->
access = access;
927 for (
auto const& content : this->
_contents)
929 if (content->methods & method)
931 if (fnmatch (content->directory.c_str (), directory.c_str (), FNM_CASEFOLD) == 0)
933 if (fnmatch (content->name.c_str (), name.c_str (), FNM_CASEFOLD) == 0)
935 return content.get ();
981 template <
class Protocol>
986 using Socket =
typename Protocol::Socket;
1041 if (sock.deferHandshake () == -1)
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
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