SNode.C
Loading...
Searching...
No Matches
StaticMiddleware.cpp
Go to the documentation of this file.
1/*
2 * SNode.C - a slim toolkit for network communication
3 * Copyright (C) Volker Christian <me@vchrist.at>
4 * 2020, 2021, 2022, 2023, 2024, 2025
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published
8 * by the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include "express/middleware/StaticMiddleware.h"
21
22#include "core/socket/stream/SocketConnection.h"
23#include "web/http/server/SocketContext.h"
24
25#ifndef DOXYGEN_SHOULD_SKIP_THIS
26
27#include "log/Logger.h"
28
29#include <map>
30
31#endif /* DOXYGEN_SHOULD_SKIP_THIS */
32
33namespace express::middleware {
34
35 StaticMiddleware::StaticMiddleware(const std::string& root)
36 : root(root) {
37 use(
38 [&stdHeaders = this->stdHeaders, &stdCookies = this->stdCookies, &connectionState = this->defaultConnectionState] MIDDLEWARE(
39 req, res, next) {
40 if (req->method == "GET") {
41 LOG(DEBUG) << res->getSocketContext()->getSocketConnection()->getConnectionName()
42 << " Express StaticMiddleware correct method: " << req->method;
43
44 if (connectionState == web::http::ConnectionState::Close) {
45 res->set("Connection", "close");
46 } else if (connectionState == web::http::ConnectionState::Keep) {
47 res->set("Connection", "keep-alive");
48 }
49 res->set(stdHeaders);
50
51 for (auto& [value, options] : stdCookies) {
52 res->cookie(value, options.getValue(), options.getOptions());
53 }
54 next();
55 } else {
56 LOG(ERROR) << res->getSocketContext()->getSocketConnection()->getConnectionName()
57 << " Express StaticMiddleware wrong method: " << req->method;
58
59 if (connectionState == web::http::ConnectionState::Close) {
60 res->set("Connection", "close");
61 } else if (connectionState == web::http::ConnectionState::Keep) {
62 res->set("Connection", "keep-alive");
63 }
64 res->sendStatus(405);
65 }
66 },
67 [] MIDDLEWARE(req, res, next) {
68 if (req->url == "/") {
69 LOG(INFO) << res->getSocketContext()->getSocketConnection()->getConnectionName()
70 << " Express StaticMiddleware Redirecting: " << req->url << " -> " << "/index.html'";
71 res->redirect(308, "/index.html");
72 } else {
73 next();
74 }
75 },
76 [&root = this->root] APPLICATION(req, res) {
77 res->sendFile(root + req->url, [&root, req, res](int ret) {
78 if (ret == 0) {
79 LOG(INFO) << res->getSocketContext()->getSocketConnection()->getConnectionName()
80 << " Express StaticMiddleware: GET " << req->url + " -> " << root + req->url;
81 } else {
82 PLOG(ERROR) << res->getSocketContext()->getSocketConnection()->getConnectionName() << " Express StaticMiddleware "
83 << req->url + " -> " << root + req->url;
84
85 res->status(404).end();
86 }
87 });
88 });
89 }
90
92 this->stdHeaders.clear();
93
94 return *this;
95 }
96
98 this->stdHeaders = stdHeaders;
99
100 return *this;
101 }
102
104 this->stdHeaders.insert(stdHeaders.begin(), stdHeaders.end());
105
106 return *this;
107 }
108
109 class StaticMiddleware& StaticMiddleware::appendStdHeaders(const std::string& field, const std::string& value) {
110 this->stdHeaders[field] = value;
111
112 return *this;
113 }
114
115 class StaticMiddleware& StaticMiddleware::appendStdCookie(const std::string& name,
116 const std::string& value,
117 const std::map<std::string, std::string>& options) {
118 this->stdCookies.insert({name, web::http::CookieOptions(value, options)});
119
120 return *this;
121 }
122
124 this->defaultConnectionState = connectionState;
125
126 return *this;
127 }
128
129 class StaticMiddleware& StaticMiddleware::instance(const std::string& root) {
130 // Keep all created static middlewares alive
131 static std::map<const std::string, std::shared_ptr<class StaticMiddleware>> staticMiddlewares;
132
133 if (!staticMiddlewares.contains(root)) {
134 staticMiddlewares[root] = std::shared_ptr<StaticMiddleware>(new StaticMiddleware(root));
135 }
136
137 return *staticMiddlewares[root];
138 }
139
140 // "Constructor" of StaticMiddleware
141 class StaticMiddleware& StaticMiddleware(const std::string& root) {
142 return StaticMiddleware::instance(root);
143 }
144
145} // namespace express::middleware
#define APPLICATION(req, res)
Definition Router.h:45
#define MIDDLEWARE(req, res, next)
Definition Router.h:40
StaticMiddleware & appendStdHeaders(const std::string &field, const std::string &value)
web::http::ConnectionState defaultConnectionState
StaticMiddleware & setStdHeaders(const std::map< std::string, std::string > &stdHeaders)
StaticMiddleware & appendStdCookie(const std::string &name, const std::string &value, const std::map< std::string, std::string > &options={})
StaticMiddleware & appendStdHeaders(const std::map< std::string, std::string > &stdHeaders)
StaticMiddleware(const std::string &root)
StaticMiddleware & afterResponse(web::http::ConnectionState connectionState)