Line data Source code
1 : /**
2 : Copyright (c) 2024 Stappler LLC <admin@stappler.dev>
3 :
4 : Permission is hereby granted, free of charge, to any person obtaining a copy
5 : of this software and associated documentation files (the "Software"), to deal
6 : in the Software without restriction, including without limitation the rights
7 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 : copies of the Software, and to permit persons to whom the Software is
9 : furnished to do so, subject to the following conditions:
10 :
11 : The above copyright notice and this permission notice shall be included in
12 : all copies or substantial portions of the Software.
13 :
14 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 : THE SOFTWARE.
21 : **/
22 :
23 : #ifndef EXTRA_WEBSERVER_WEBSERVER_REQUEST_SPWEBREQUEST_H_
24 : #define EXTRA_WEBSERVER_WEBSERVER_REQUEST_SPWEBREQUEST_H_
25 :
26 : #include "SPWebInfo.h"
27 : #include "SPWebHost.h"
28 : #include "SPPugContext.h"
29 :
30 : namespace STAPPLER_VERSIONIZED stappler::web {
31 :
32 : class Session;
33 : class RequestController;
34 : class InputFilter;
35 :
36 : class Request final : public std::basic_ostream<char, std::char_traits<char>>, public AllocBase {
37 : public:
38 : using char_type = char;
39 : using traits_type = std::char_traits<char>;
40 : using ostream_type = std::basic_ostream<char_type, traits_type>;
41 : using Require = db::InputConfig::Require;
42 :
43 : static Request getCurrent();
44 :
45 : Request();
46 : Request(RequestController *);
47 : Request & operator =(RequestController *);
48 :
49 : Request(Request &&);
50 : Request & operator =(Request &&);
51 :
52 : Request(const Request &);
53 : Request & operator =(const Request &);
54 :
55 6600 : RequestController *getController() const { return _config; }
56 7775 : explicit operator bool () const { return _config != nullptr; }
57 :
58 : const RequestInfo &getInfo() const;
59 :
60 : StringView getRequestHeader(StringView) const;
61 : void foreachRequestHeaders(const Callback<void(StringView, StringView)> &) const;
62 :
63 : StringView getResponseHeader(StringView) const;
64 : void foreachResponseHeaders(const Callback<void(StringView, StringView)> &) const;
65 : void setResponseHeader(StringView, StringView) const;
66 : void clearResponseHeaders() const;
67 :
68 : StringView getErrorHeader(StringView) const;
69 : void foreachErrorHeaders(const Callback<void(StringView, StringView)> &) const;
70 : void setErrorHeader(StringView, StringView) const;
71 : void clearErrorHeaders() const;
72 :
73 : void setRequestHandler(RequestHandler *);
74 : RequestHandler *getRequestHandler() const;
75 :
76 : void writeData(const Value &, bool allowJsonP = false);
77 :
78 : /* request params setters */
79 : void setDocumentRoot(StringView);
80 : void setContentType(StringView);
81 : void setHandler(StringView);
82 : void setContentEncoding(StringView);
83 :
84 : /* set path for file, that should be returned in response via sendfile */
85 : void setFilename(StringView, bool updateStat = true, Time mtime = Time());
86 :
87 : /* set HTTP status code and response status line ("404 NOT FOUND", etc.)
88 : * if no string provided, default status line for code will be used */
89 : void setStatus(Status status, StringView = StringView());
90 :
91 : void setCookie(StringView name, StringView value, TimeInterval maxAge = TimeInterval(), CookieFlags flags = CookieFlags::Default);
92 : void removeCookie(StringView name, CookieFlags flags = CookieFlags::Default);
93 :
94 : // cookies, that will be sent in server response
95 : const Map<StringView, CookieStorageInfo> getResponseCookies() const;
96 :
97 : StringView getCookie(StringView name, bool removeFromHeadersTable = true) const;
98 :
99 : Status redirectTo(StringView location);
100 : Status sendFile(StringView path, size_t cacheTimeInSeconds = maxOf<size_t>());
101 : Status sendFile(StringView path, StringView contentType, size_t cacheTimeInSeconds = maxOf<size_t>());
102 :
103 : Status runPug(const StringView & path, const Function<bool(pug::Context &, const pug::Template &)> & = nullptr);
104 :
105 : String getFullHostname(int port = -1) const;
106 :
107 : // true if successful cache test
108 : bool checkCacheHeaders(Time, const StringView &etag);
109 : bool checkCacheHeaders(Time, uint32_t idHash);
110 :
111 : const db::InputConfig & getInputConfig() const;
112 :
113 : void setInputConfig(const db::InputConfig &);
114 :
115 : // check if request is sent by server/handler administrator
116 : // uses 'User::isAdmin' or tries to authorize admin by cross-server protocol
117 : bool isAdministrative();
118 :
119 : void setUser(db::User *);
120 : void setUser(int64_t);
121 :
122 : // try to get user data from session (by 'getSession' call)
123 : // if session is not existed - returns nullptr
124 : // if session is anonymous - returns nullptr
125 : db::User *getUser();
126 : db::User *getAuthorizedUser() const;
127 :
128 : int64_t getUserId() const;
129 :
130 : bool isSecureConnection() const;
131 :
132 : RequestController *config() const;
133 : Host host() const;
134 : pool_t *pool() const;
135 :
136 : db::AccessRoleId getAccessRole() const;
137 : void setAccessRole(db::AccessRoleId) const;
138 :
139 : db::Transaction acquireDbTransaction() const;
140 :
141 : const Vector<Value> & getDebugMessages() const;
142 : const Vector<Value> & getErrorMessages() const;
143 :
144 : template <typename Source, typename Text>
145 50 : void addError(Source &&source, Text &&text) const {
146 200 : addErrorMessage(Value{
147 100 : std::make_pair("source", Value(std::forward<Source>(source))),
148 100 : std::make_pair("text", Value(std::forward<Text>(text)))
149 : });
150 50 : }
151 :
152 : template <typename Source, typename Text>
153 0 : void addError(Source &&source, Text &&text, Value &&d) const {
154 0 : addErrorMessage(Value{
155 0 : std::make_pair("source", Value(std::forward<Source>(source))),
156 0 : std::make_pair("text", Value(std::forward<Text>(text))),
157 0 : std::make_pair("data", std::move(d))
158 : });
159 0 : }
160 :
161 : template <typename Source, typename Text>
162 25 : void addDebug(Source &&source, Text &&text) const {
163 100 : addDebugMessage(Value{
164 50 : std::make_pair("source", Value(std::forward<Source>(source))),
165 50 : std::make_pair("text", Value(std::forward<Text>(text)))
166 : });
167 25 : }
168 :
169 : template <typename Source, typename Text>
170 : void addDebug(Source &&source, Text &&text, Value &&d) const {
171 : addDebugMessage(Value{
172 : std::make_pair("source", Value(std::forward<Source>(source))),
173 : std::make_pair("text", Value(std::forward<Text>(text))),
174 : std::make_pair("data", std::move(d))
175 : });
176 : }
177 :
178 : void addErrorMessage(Value &&) const;
179 : void addDebugMessage(Value &&) const;
180 :
181 : void addCleanup(Function<void()> &&) const;
182 :
183 : void storeObject(void *ptr, const StringView &key, Function<void()> && = nullptr) const;
184 :
185 : template <typename T = void>
186 75 : T *getObject(const StringView &key) const {
187 75 : return pool::get<T>(pool(), key);
188 : }
189 :
190 : bool performWithStorage(const Callback<bool(const db::Transaction &)> &cb) const;
191 :
192 : Session *getSession();
193 : Session *authorizeUser(db::User *, TimeInterval maxAge);
194 :
195 : void setInputFilter(InputFilter *);
196 : InputFilter *getInputFilter() const;
197 :
198 : protected:
199 : void initScriptContext(pug::Context &ctx);
200 :
201 : /* Buffer class used as basic_streambuf to allow stream writing to request
202 : * like 'request << "String you want to send"; */
203 : class Buffer : public std::basic_streambuf<char, std::char_traits<char>> {
204 : public:
205 : using int_type = typename traits_type::int_type;
206 : using pos_type = typename traits_type::pos_type;
207 : using off_type = typename traits_type::off_type;
208 :
209 : using streamsize = std::streamsize;
210 : using streamoff = std::streamoff;
211 :
212 : using ios_base = std::ios_base;
213 :
214 : Buffer(RequestController *r);
215 : Buffer(Buffer&&);
216 : Buffer& operator=(Buffer&&);
217 :
218 : Buffer(const Buffer&);
219 : Buffer& operator=(const Buffer&);
220 :
221 : protected:
222 : virtual int_type overflow(int_type c = traits_type::eof()) override;
223 :
224 : virtual pos_type seekoff(off_type off, ios_base::seekdir way, ios_base::openmode) override;
225 : virtual pos_type seekpos(pos_type pos, ios_base::openmode mode) override;
226 :
227 : virtual int sync() override;
228 :
229 : virtual streamsize xsputn(const char_type* s, streamsize n) override;
230 :
231 : RequestController *_config = nullptr;
232 : };
233 :
234 : Buffer _buffer;
235 : RequestController *_config = nullptr;
236 : };
237 :
238 : }
239 :
240 : #endif /* EXTRA_WEBSERVER_WEBSERVER_REQUEST_SPWEBREQUEST_H_ */
|