Coverage Report

Created: 2025-11-11 07:02

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wt/src/web/WebRequest.h
Line
Count
Source
1
// This may look like C code, but it's really -*- C++ -*-
2
/*
3
 * Copyright (C) 2008 Emweb bv, Herent, Belgium.
4
 *
5
 * See the LICENSE file for terms of use.
6
 */
7
#ifndef WEB_REQUEST_H_
8
#define WEB_REQUEST_H_
9
10
#include <chrono>
11
#include <cstdint>
12
#include <iostream>
13
#include <Wt/WDllDefs.h>
14
#include <Wt/WGlobal.h>
15
#include <Wt/Http/Request.h>
16
17
#include <boost/utility/string_view.hpp>
18
19
#include <cstdint>
20
#include <functional>
21
22
namespace Wt {
23
24
class Configuration;
25
class EntryPoint;
26
class WebSocketConnection;
27
class WSslInfo;
28
29
/*
30
 * A single, raw, HTTP request/response, which conveys all of the http-related
31
 * information to the application and gathers the response.
32
 */
33
class WT_API WebRequest
34
{
35
public:
36
  WebRequest();
37
38
  void log();
39
40
  enum class ResponseState {
41
    ResponseDone,
42
    ResponseFlush
43
  };
44
45
  enum class ResponseType {
46
    Page,
47
    Script,
48
    Update
49
  };
50
51
  typedef std::function<void(WebWriteEvent)> WriteCallback;
52
  typedef std::function<void(WebReadEvent)> ReadCallback;
53
  typedef std::function<void(void)> DisconnectCallback;
54
  typedef std::function<void(const Http::Request &request, std::shared_ptr<WebSocketConnection>)> WebSocketResourceTransferCallback;
55
56
  /*
57
   * Signal that the response should be flushed.
58
   *
59
   * ResponseDone: flush & close
60
   *
61
   * ResponseFlush: flush what we have so far, do not close
62
   *  - callback must be specified for ResponseFlush, and is called
63
   *    if more data can be written. Until then, you cannot do new
64
   *    writes.
65
   */
66
  virtual void flush(ResponseState state = ResponseState::ResponseDone,
67
                     const WriteCallback& callback = WriteCallback()) = 0;
68
#ifdef WT_TARGET_JAVA
69
  virtual void flushBuffer();
70
#endif
71
  /*
72
   * For a web socket request (isWebSocketRequest()), read a message
73
   * and call the given callback function when done.
74
   *
75
   * The new message is available in in() and has length contentLength()
76
   */
77
  virtual void readWebSocketMessage(const ReadCallback& callback);
78
79
  /*
80
   * For a web socket request (isWebSocketRequest()), returns whether
81
   * more data is available. This is used to defer a response but wait
82
   * for more incoming events.
83
   */
84
  virtual bool webSocketMessagePending() const;
85
86
  /*
87
   * When a connection to a WWebSocketResource is set up, the socket is
88
   * transferred from the http server to the resource using this callback.
89
   *
90
   * Possibly not supported by all front-ends.
91
   */
92
  virtual bool supportsTransferWebSocketResourceSocket() = 0;
93
  void setTransferWebSocketResourceSocketCallBack(WebSocketResourceTransferCallback cb);
94
  bool hasTransferWebSocketResourceSocketCallBack();
95
  void transferWebSocketResourceSocket(const std::shared_ptr<WebSocketConnection> &socket);
96
97
  /*
98
   * Indicate that we're deferring to write a response, but in the mean-time
99
   * we do want to know if there's a disconnect event (by reading from
100
   * the socket).
101
   */
102
  virtual bool detectDisconnect(const DisconnectCallback& callback);
103
104
  /*
105
   * Access the stream that contains the request body (HTTP) or a
106
   * single message (WS)
107
   */
108
  virtual std::istream& in() = 0;
109
110
  /*
111
   * Access the stream to submit the response.
112
   *
113
   * This is either the entire response body (HTTP), or a single response
114
   * message (WS)
115
   */
116
  virtual std::ostream& out() = 0;
117
118
0
  WT_BOSTREAM& bout() { return out(); }
119
120
  /*
121
   * (Not used)
122
   */
123
  virtual std::ostream& err() = 0;
124
125
  /*
126
   * Sets the redirect (instead of anything else).
127
   */
128
  virtual void setRedirect(const std::string& url) = 0;
129
130
  /*
131
   * Sets the status
132
   */
133
  virtual void setStatus(int status) = 0;
134
135
  /*
136
   * returns current status value
137
   */
138
  virtual int status() = 0;
139
140
  /*
141
   * Sets the content-type for a normal response.
142
   */
143
  virtual void setContentType(const std::string& value) = 0;
144
145
  /*
146
   * Sets the content-length for a normal response.
147
   */
148
  virtual void setContentLength(std::int64_t length) = 0;
149
150
  /*
151
   * Adds a header for a normal response.
152
   */
153
  virtual void addHeader(const std::string& name, const std::string& value) = 0;
154
155
  /*
156
   * Inserts a header for a normal response.
157
   *
158
   * Inserting will not always add the header, but can replace an
159
   * existing header value if one with the same name is already created.
160
   */
161
  virtual void insertHeader(const std::string& name, const std::string& value) = 0;
162
163
  /*
164
   * Returns request information, which are not http headers.
165
   */
166
  virtual const char *envValue(const char *name) const = 0;
167
168
  virtual const std::string& serverName() const = 0;
169
  virtual const std::string& serverPort() const = 0;
170
  /*! \internal
171
   * \brief Returns the SCRIPT_NAME
172
   *
173
   * This is equivalent to the SCRIPT_NAME CGI parameter, see:
174
   * https://www.rfc-editor.org/rfc/rfc3875#section-4.1.13
175
   *
176
   * - for wthttp this will be the empty string
177
   * - for wtisapi this will be the path up until the DLL file
178
   * - for wtfcgi this should be set properly in the server configuration,
179
   *   if `^/path(/.*)?$` is routed to the wtfcgi instance, then this should be `/path`.
180
   *   SCRIPT_NAME should be empty or start with a forward slash (`/`).
181
   */
182
  virtual const std::string& scriptName() const = 0;
183
  virtual const char *requestMethod() const = 0;
184
  virtual const std::string& queryString() const = 0;
185
  /*! \internal
186
   * \brief Returns the PATH_INFO
187
   *
188
   * This is equivalent to the PATH_INFO CGI parameter, see:
189
   * https://www.rfc-editor.org/rfc/rfc3875#section-4.1.5
190
   *
191
   * - for wthttp this is the full request path
192
   * - for wtisapi this is the part of the request path after the DLL file
193
   * - for wtfcgi this should be set properly in the server configuration,
194
   *   if `^/path(/.*)?$` is routed to the wtfcgi instance, and the user
195
   *   requests `/path/name` then pathInfo() is `/name`.
196
   *   PATH_INFO should be empty or start with a forward slash (`/`).
197
   */
198
  virtual const std::string& pathInfo() const = 0;
199
  /*! \internal
200
   * \brief Returns the part of pathInfo() that corresponds to the entrypoint
201
   *
202
   * e.g. if `/entry/point` is the request path, and the request matches the entrypoint `/entry`,
203
   * then this will return `/entry`.
204
   *
205
   * If the request did not match an entrypoint (yet), then the result will be the empty string.
206
   */
207
  boost::string_view entryPointPath() const;
208
  /*! \internal
209
   * \brief Returns the full path up to and including the entrypoint
210
   *
211
   * This differs from entryPointPath() in that the scriptName() is prepended.
212
   *
213
   * - for wthttp this is the same as entryPointPath()
214
   * - for wtisapi, if the DLL is deployed at `/hello.dll` and the matched entrypoint is `/entrypoint`,
215
   *   then this returns `/hello.dll/entrypoint`
216
   * - for wtfcgi, if the scriptName is `/hello.wt` and the matched entrypoint is `/entrypoint`,
217
   *   then this returns `/hello.wt/entrypoint`
218
   *
219
   * For JWt, calls to this function are translated to WebRequest#getScriptName(), yielding the full path
220
   * that the servlet is deployed at (context path + servlet path), since JWt has no concept of an "entrypoint".
221
   */
222
  std::string fullEntryPointPath() const;
223
  /*! \internal
224
   * \brief Returns the part of pathInfo() that corresponds to the part after the entrypoint
225
   *
226
   * e.g. if `/entry/point` is the request path, and the request matches the entrypoint `/entry`,
227
   * then this will return `/point`.
228
   *
229
   * If the request did not match an entrypoint (yet), then the result will be the full pathInfo().
230
   *
231
   * For JWt, calls to this function are translated to WebRequest#getPathInfo(), yielding the part of
232
   * the request path that comes after the servlet path, since JWt has no concept of an "entrypoint".
233
   */
234
  boost::string_view extraPathInfo() const;
235
  virtual const std::string& remoteAddr() const = 0;
236
237
  virtual const char *urlScheme() const = 0;
238
239
0
  virtual bool isWebSocketMessage() const { return false; }
240
241
0
  bool isWebSocketRequest() const { return webSocketRequest_; }
242
0
  void setWebSocketRequest(bool ws) { webSocketRequest_ = ws; }
243
244
  /*
245
   * Accesses to cgi environment variables and headers -- rfc2616 name
246
   */
247
  virtual const char *headerValue(const char *name) const = 0;
248
249
  /*
250
   * Accesses to specific header fields (calls headerValue()).
251
   */
252
  const char *userAgent() const;
253
  const char *referer() const;
254
255
#ifndef WT_TARGET_JAVA
256
  virtual std::vector<Wt::Http::Message::Header> headers() const = 0;
257
#endif
258
259
  virtual const char *contentType() const;
260
  virtual ::int64_t contentLength() const;
261
262
#ifdef WT_TARGET_JAVA
263
  /*
264
   * In JavaEE, the servlet determines how session tracking is encoded in
265
   * the URL.
266
   */
267
  std::string encodeURL(const std::string& url) const;
268
#endif // WT_TARGET_JAVA
269
270
  const std::string *getParameter(const std::string& name) const;
271
  const Http::ParameterValues& getParameterValues(const std::string& name)
272
    const;
273
0
  const Http::ParameterMap& getParameterMap() const { return parameters_; }
274
0
  const Http::UploadedFileMap& uploadedFiles() const { return files_; }
275
0
  ::int64_t postDataExceeded() const { return postDataExceeded_; }
276
277
  WLocale parseLocale() const;
278
279
  void setResponseType(ResponseType responseType);
280
0
  ResponseType responseType() const { return responseType_; }
281
282
  /*
283
   * Returns \c nullptr if the request does not have SSL client certificate
284
   * information.
285
   */
286
  virtual std::unique_ptr<WSslInfo> sslInfo(const Configuration & conf) const = 0;
287
288
  virtual const std::vector<std::pair<std::string, std::string> >& urlParams() const;
289
290
  std::string clientAddress(const Configuration & conf) const;
291
292
  std::string hostName(const Configuration & conf) const;
293
294
  std::string urlScheme(const Configuration & conf) const;
295
296
0
  const std::string& nonce() const { return nonce_; }
297
protected:
298
  const EntryPoint *entryPoint_;
299
  std::size_t extraStartIndex_;
300
301
  virtual ~WebRequest();
302
  void reset();
303
304
#ifndef WT_CNOR
305
  struct AsyncEmulation;
306
  AsyncEmulation *async_;
307
308
  void emulateAsync(ResponseState state);
309
  void setAsyncCallback(const WriteCallback& cb);
310
  const WriteCallback& getAsyncCallback();
311
#endif // WT_CNOR
312
313
private:
314
  std::string parsePreferredAcceptValue(const char *value) const;
315
  void addNonce();
316
317
  ::int64_t postDataExceeded_;
318
  Http::ParameterMap parameters_;
319
  Http::UploadedFileMap files_;
320
  ResponseType responseType_;
321
  bool webSocketRequest_;
322
  WebSocketResourceTransferCallback wsResourceTransferCb_;
323
  std::chrono::high_resolution_clock::time_point start_;
324
  std::vector<std::pair<std::string, std::string> > urlParams_;
325
  std::string nonce_;
326
327
  static Http::ParameterValues emptyValues_;
328
329
#ifndef WT_CNOR
330
  WriteCallback asyncCallback_;
331
#endif // WT_CNOR
332
333
  friend class CgiParser;
334
  friend class Http::Request;
335
  friend class WEnvironment;
336
  friend class WebController;
337
};
338
339
class WebResponse : public WebRequest
340
{
341
#ifdef WT_TARGET_JAVA
342
public:
343
  void addCookie(const Http::Cookie& cookie);
344
#endif
345
};
346
347
}
348
349
#endif // WEB_REQUEST_H_