25#ifndef __JOIN_HTTP_SERVER_HPP__
26#define __JOIN_HTTP_SERVER_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>
83 using Content = BasicHttpContent <Protocol>;
84 using Server = BasicHttpServer <Protocol>;
141 std::stringstream gmt;
142 std::time_t ti = std::time (
nullptr);
143 gmt << std::put_time (std::gmtime (&ti),
"%a, %d %b %Y %H:%M:%S GMT");
154 std::stringstream keepAlive;
167 this->
_response.
header (
"Strict-Transport-Security",
"max-age=31536000; includeSubDomains; preload");
171 this->
_response.
header (
"Content-Security-Policy",
"default-src 'self'; object-src 'none'; script-src 'self'; style-src 'self'; img-src 'self'");
205 void sendError (
const std::string& status,
const std::string& reason)
227 void sendRedirect (
const std::string& status,
const std::string& reason,
const std::string& location = {})
235 if (!location.empty ())
239 payload +=
"<meta http-equiv=\"content-type\" content=\"text/html;charset=utf-8\">";
240 payload +=
"<title>" + status +
" " + reason +
"</title>";
241 payload +=
"</head>";
243 payload +=
"<h1>" + status +
" " + reason +
"</h1>";
244 payload +=
"The document has moved <a href=\"" + location +
"\">here</a>";
245 payload +=
"</body>";
246 payload +=
"</html>";
252 this->
_response.
header (
"Content-Length", std::to_string (payload.size ()));
263 this->write (payload.c_str (), payload.size ());
280 if (addr ==
nullptr || S_ISDIR (sbuf.st_mode))
287 std::stringstream modifTime;
288 modifTime << std::put_time (std::gmtime (&sbuf.st_ctime),
"%a, %d %b %Y %H:%M:%S GMT");
299 this->
_response.
header (
"Content-Length", std::to_string (sbuf.st_size));
310 this->write (
static_cast <char *
> (addr), sbuf.st_size);
332 std::string
header (
const std::string& name)
const
351 void header (
const std::string& name,
const std::string& val)
376 fd_set fdset = setfd;
377 int nset = ::select (fdmax + 1, &fdset,
nullptr,
nullptr,
nullptr);
383 [[maybe_unused]] ssize_t bytes = ::read (this->
_server->
_event, &val, sizeof (uint64_t));
417 while ((this->
_max < 0) || (--this->
_max != 0));
443 this->
sendError (
"405",
"Method Not Allowed");
447 this->
sendError (
"494",
"Request Header Too Large");
478 if (content ==
nullptr)
484 if (content->
access !=
nullptr)
493 if (!content->
access (this->_request.auth (), this->_request.credentials (), err))
507 std::string alias (content->
alias);
529 if (content->
handler ==
nullptr)
531 this->
sendError (
"500",
"Internal Server Error");
540 this->
sendRedirect (
"307",
"Temporary Redirect", alias);
573 for (
auto const& encoding : encodings)
575 if (encoding.find (
"gzip") != std::string::npos)
580 else if (encoding.find (
"deflate") != std::string::npos)
585 else if (encoding.find (
"chunked") != std::string::npos)
637 template <
class Protocol>
641 using Worker = BasicHttpWorker <Protocol>;
646 using Socket =
typename Protocol::Socket;
654 :
_event (eventfd (0, EFD_NONBLOCK | EFD_CLOEXEC | EFD_SEMAPHORE)),
659 [[maybe_unused]]
int res = chdir (this->
_baseLocation.c_str ());
705 if (this->
_acceptor.create (endpoint) == -1)
710 for (
size_t nworkers = 0; nworkers < this->
_nworkers; ++nworkers)
724 [[maybe_unused]] ssize_t bytes = ::write (this->
_event, &val,
sizeof (uint64_t));
751 [[maybe_unused]]
int res = chdir (this->
_baseLocation.c_str ());
768 void keepAlive (std::chrono::seconds timeout,
int max = 1000)
811 if (newEntry !=
nullptr)
816 newEntry->
name = name;
818 newEntry->
access = access;
833 Content*
addAlias (
const std::string& dir,
const std::string& name,
const std::string& alias,
const Access& access =
nullptr)
836 if (newEntry !=
nullptr)
841 newEntry->
name = name;
842 newEntry->
alias = alias;
844 newEntry->
access = access;
863 if (newEntry !=
nullptr)
868 newEntry->
name = name;
870 newEntry->
access = access;
885 Content*
addRedirect (
const std::string& dir,
const std::string& name,
const std::string& location,
const Access& access =
nullptr)
888 if (newEntry !=
nullptr)
893 newEntry->
name = name;
894 newEntry->
alias = location;
896 newEntry->
access = access;
915 for (
auto const& content : this->
_contents)
917 if (content->methods & method)
919 if (fnmatch (content->directory.c_str (), directory.c_str (), FNM_CASEFOLD) == 0)
921 if (fnmatch (content->name.c_str (), name.c_str (), FNM_CASEFOLD) == 0)
923 return content.get ();
969 template <
class Protocol>
973 using Worker = BasicHttpWorker <Protocol>;
978 using Socket =
typename Protocol::Socket;
1027 return this->
_acceptor.acceptEncrypted ();
1048 return this->
_acceptor.setCaCertificate (caFile);
1058 return this->
_acceptor.setVerify (verify, depth);
1068 return this->
_acceptor.setCipher (cipher);
1078 return this->
_acceptor.setCipher_1_3 (cipher);
1081#if OPENSSL_VERSION_NUMBER >= 0x30000000L
1087 int setCurve (
const std::string &curves)
1089 return this->
_acceptor.setCurve (curves);
basic HTTPS server.
Definition httpserver.hpp:971
BasicHttpSecureServer(size_t workers=std::thread::hardware_concurrency())
create the HTTPS server instance.
Definition httpserver.hpp:985
typename Protocol::Acceptor Acceptor
Definition httpserver.hpp:979
typename Protocol::Endpoint Endpoint
Definition httpserver.hpp:977
int setCertificate(const std::string &cert, const std::string &key="")
set the certificate and the private key.
Definition httpserver.hpp:1036
typename Content::Handler Handler
Definition httpserver.hpp:975
friend Worker
friendship with worker.
Definition httpserver.hpp:1103
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:1046
typename Protocol::Socket Socket
Definition httpserver.hpp:978
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:1066
Socket accept() const override
accept new connection and fill in the client object with connection parameters.
Definition httpserver.hpp:1025
virtual ~BasicHttpSecureServer()=default
destroy the HTTPS server.
typename Content::Access Access
Definition httpserver.hpp:976
virtual std::string scheme() const override
get scheme.
Definition httpserver.hpp:1097
void setVerify(bool verify, int depth=-1)
Enable/Disable the verification of the peer certificate.
Definition httpserver.hpp:1056
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:1076
basic HTTP server.
Definition httpserver.hpp:639
BasicHttpServer(size_t workers=std::thread::hardware_concurrency())
create the HTTP server instance.
Definition httpserver.hpp:653
typename Content::Handler Handler
Definition httpserver.hpp:643
typename Protocol::Socket Socket
Definition httpserver.hpp:646
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:833
typename Content::Access Access
Definition httpserver.hpp:644
std::string _baseLocation
base location.
Definition httpserver.hpp:951
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:860
void keepAlive(std::chrono::seconds timeout, int max=1000)
set HTTP keep alive.
Definition httpserver.hpp:768
BasicHttpContent< Protocol > Content
Definition httpserver.hpp:642
const std::string & baseLocation() const
get file base location.
Definition httpserver.hpp:758
typename Protocol::Endpoint Endpoint
Definition httpserver.hpp:645
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:885
Acceptor _acceptor
acceptor.
Definition httpserver.hpp:933
void baseLocation(const std::string &path)
set file base location.
Definition httpserver.hpp:742
int _keepMax
keep alive max.
Definition httpserver.hpp:957
typename Protocol::Acceptor Acceptor
Definition httpserver.hpp:647
virtual Socket accept() const
accept new connection.
Definition httpserver.hpp:733
void close() noexcept
close server.
Definition httpserver.hpp:721
virtual ~BasicHttpServer()
destroy the HTTP server.
Definition httpserver.hpp:691
Content * findContent(HttpMethod method, const std::string &path) const
find content.
Definition httpserver.hpp:910
Cache _cache
file cache.
Definition httpserver.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 httpserver.hpp:808
friend Worker
friendship with worker.
Definition httpserver.hpp:963
int keepAliveMax() const
get HTTP keep alive max.
Definition httpserver.hpp:787
int _event
gracefully stop all workers.
Definition httpserver.hpp:936
int create(const Endpoint &endpoint) noexcept
create server.
Definition httpserver.hpp:703
std::vector< std::unique_ptr< Content > > _contents
contents.
Definition httpserver.hpp:948
std::chrono::seconds keepAliveTimeout() const
get HTTP keep alive timeout.
Definition httpserver.hpp:778
std::vector< std::unique_ptr< Worker > > _workers
workers.
Definition httpserver.hpp:942
size_t _nworkers
number of workers.
Definition httpserver.hpp:939
std::chrono::seconds _keepTimeout
keep alive timeout.
Definition httpserver.hpp:954
BasicHttpServer(BasicHttpServer &&other)=delete
create instance by move.
Mutex _mutex
accept protection mutex.
Definition httpserver.hpp:945
BasicHttpServer(const BasicHttpServer &other)=delete
create instance by copy.
virtual std::string scheme() const
get scheme.
Definition httpserver.hpp:796
basic HTTP worker.
Definition httpserver.hpp:81
void setEncoding(const std::vector< std::string > &encodings)
set stream encoding.
Definition httpserver.hpp:571
void clearEncoding()
clear stream encoding.
Definition httpserver.hpp:598
std::string header(const std::string &name) const
get HTTP request header by name.
Definition httpserver.hpp:332
std::streambuf * _streambuf
HTTP stream buffer.
Definition httpserver.hpp:622
bool hasHeader(const std::string &name) const
checks if there is a HTTP request header with the specified name.
Definition httpserver.hpp:322
BasicHttpWorker(BasicHttpWorker &&other)=delete
create instance by move.
HttpRequest _request
HTTP request.
Definition httpserver.hpp:616
void sendHeaders()
send headers.
Definition httpserver.hpp:133
void writeResponse()
write the HTTP response.
Definition httpserver.hpp:475
void sendFile(const std::string &path)
send a file.
Definition httpserver.hpp:274
void header(const std::string &name, const std::string &val)
add header to the HTTP response.
Definition httpserver.hpp:351
int _max
max requests.
Definition httpserver.hpp:613
BasicHttpWorker(const BasicHttpWorker &other)=delete
create instance by copy.
void cleanUp()
clean all.
Definition httpserver.hpp:552
BasicHttpWorker & operator=(const BasicHttpWorker &other)=delete
assign instance by copy.
bool _wrapped
HTTP stream status.
Definition httpserver.hpp:625
void sendRedirect(const std::string &status, const std::string &reason, const std::string &location={})
send redirect message.
Definition httpserver.hpp:227
void endRequest()
end the HTTP request.
Definition httpserver.hpp:561
HttpResponse _response
HTTP response.
Definition httpserver.hpp:619
Server * _server
HTTP server.
Definition httpserver.hpp:628
int readRequest()
read the HTTP request.
Definition httpserver.hpp:426
void processRequest()
process the HTTP request.
Definition httpserver.hpp:402
virtual ~BasicHttpWorker()
destroy worker thread.
Definition httpserver.hpp:125
Thread _thread
thread.
Definition httpserver.hpp:631
void sendError(const std::string &status, const std::string &reason)
send error message.
Definition httpserver.hpp:205
void work()
worker thread routine.
Definition httpserver.hpp:360
size_t contentLength() const
get content length.
Definition httpserver.hpp:341
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:338
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:544
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
thread class.
Definition thread.hpp:138
void join()
block the current thread until the running thread finishes its execution.
Definition thread.cpp:123
@ 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:117
@ Head
Definition httpmessage.hpp:113
@ Get
Definition httpmessage.hpp:114
__inline__ std::string filename(const std::string &filepath)
get file name of the specified file.
Definition filesystem.hpp:53
__inline__ std::string & replaceAll(std::string &str, const std::string &toReplace, const std::string &by)
replace all occurrences of a substring.
Definition utils.hpp:231
__inline__ 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:274
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
__inline__ bool compareNoCase(const std::string &a, const std::string &b)
case insensitive string comparison.
Definition utils.hpp:188
thread_local std::error_code lastError
last error.
Definition error.cpp:32
__inline__ std::string mime(const std::string &filepath)
get mime type of the specified file.
Definition filesystem.hpp:83
__inline__ std::string base(const std::string &filepath)
get base path of the specified file.
Definition filesystem.hpp:38
basic HTTP content.
Definition httpserver.hpp:63
std::string directory
Definition httpserver.hpp:69
std::function< bool(const std::string &, const std::string &, std::error_code &)> Access
Definition httpserver.hpp:65
std::string alias
Definition httpserver.hpp:71
HttpContentType type
Definition httpserver.hpp:68
HttpMethod methods
Definition httpserver.hpp:67
Handler handler
Definition httpserver.hpp:72
std::function< void(typename Protocol::Worker *)> Handler
Definition httpserver.hpp:64
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