NCBI C++ ToolKit
ncbicgir.hpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 #ifndef CGI___NCBICGIR__HPP
2 #define CGI___NCBICGIR__HPP
3 
4 /* $Id: ncbicgir.hpp 77710 2017-05-03 12:54:15Z ivanov $
5  * ===========================================================================
6  *
7  * PUBLIC DOMAIN NOTICE
8  * National Center for Biotechnology Information
9  *
10  * This software/database is a "United States Government Work" under the
11  * terms of the United States Copyright Act. It was written as part of
12  * the author's official duties as a United States Government employee and
13  * thus cannot be copyrighted. This software/database is freely available
14  * to the public for use. The National Library of Medicine and the U.S.
15  * Government have not placed any restriction on its use or reproduction.
16  *
17  * Although all reasonable efforts have been taken to ensure the accuracy
18  * and reliability of the software and data, the NLM and the U.S.
19  * Government do not and cannot warrant the performance or results that
20  * may be obtained by using this software or data. The NLM and the U.S.
21  * Government disclaim all warranties, express or implied, including
22  * warranties of performance, merchantability or fitness for any particular
23  * purpose.
24  *
25  * Please cite the author in any work or product based on this material.
26  *
27  * ===========================================================================
28  *
29  * Authors: Eugene Vasilchenko, Denis Vakatov
30  *
31  * File Description:
32  * CCgiResponse -- CGI response generator class
33  *
34  */
35 
36 #include <cgi/ncbicgi.hpp>
37 #include <corelib/ncbitime.hpp>
38 #include <util/retry_ctx.hpp>
39 #include <map>
40 
41 
42 /** @addtogroup CGIReqRes
43  *
44  * @{
45  */
46 
47 
49 
50 class CCgiSession;
51 class CCgiStreamWrapper;
52 
54 {
55 public:
56  /// @note
57  /// By default set output stream to "cout" and file descr to STDOUT_FILENO
58  CCgiResponse(CNcbiOstream* os = NULL, int ofd = -1);
59  //
60  ~CCgiResponse(void);
61 
62  // Set/get the "raw CGI" response type
63  void SetRawCgi(bool is_raw);
64  bool IsRawCgi(void) const;
65 
66  // Set response status.
67  // NOTE: use this method rather than SetHeaderValue("Status", ...)
68  // as it is safer and it works for the "raw CGI" response type, too.
69  void SetStatus(unsigned int code, const string& reason = kEmptyStr);
70 
71  // Header setters
72  void SetHeaderValue (const string& name, const string& value);
73  void SetHeaderValue (const string& name, const struct tm& value);
74  void SetHeaderValue (const string& name, const CTime& value);
75  void RemoveHeaderValue(const string& name);
76 
77  // Header getter
78  string GetHeaderValue (const string& name) const;
79  bool HaveHeaderValue(const string& name) const;
80 
81  /// Set content type (text/html by default if not provided)
82  void SetContentType(const string& type);
83 
84  /// Get content type
85  string GetContentType(void) const;
86 
87  // Set filename for undisplayable content; please include an
88  // appropriate extension, and don't bother with directory
89  // components (which clients generally discard). Add a size
90  // parameter if the corresponding (optional) argument is nonzero.
91  void SetFilename(const string& name, size_t size = 0);
92 
93  /// Set the "Location:" HTTP header
94  void SetLocation(const CUrl& url, const IUrlEncoder* encoder = 0);
95 
96  // Various styles of multipart responses, none of which is
97  // universally supported. :-/
99  {
100  eMultipart_none, // default (just a single part)
103  eMultipart_replace // push-style refreshing
104  };
105  void SetMultipartMode(EMultipartMode mode = eMultipart_mixed);
106  EMultipartMode GetMultipartMode(void);
107 
108  void BeginPart (const string& name, const string& type, size_t size = 0);
109  void EndPart (void);
110  void EndLastPart(void);
111 
112  void BeginPart (const string& name, const string& type, CNcbiOstream& os,
113  size_t size = 0);
114  void EndPart (CNcbiOstream& os);
115  void EndLastPart(CNcbiOstream& os);
116 
117  // Get cookies set
118  const CCgiCookies& Cookies(void) const;
119  CCgiCookies& Cookies(void);
120 
121  /// Set output stream (NULL here means "no output stream").
122  /// This does not flush the previous stream (if any), so some
123  /// data may be lost.
124  void SetOutput(CNcbiOstream* os, int fd = -1);
125 
126  /// Get output stream (NULL here means "no output stream").
127  ///
128  /// @attention
129  /// If the output stream is in a "bad" state and the
130  /// SetThrowOnBadOutput() is set to TRUE, then:
131  /// - a warning will be posted
132  /// - SetThrowOnBadOutput(false) will be called
133  CNcbiOstream* GetOutput(void) const;
134 
135  /// Get file descriptor of the output stream (-1 if not applicable)
136  int GetOutputFD(void) const;
137 
138  /// Get output stream. Throw exception if GetOutput() is NULL.
139  CNcbiOstream& out(void) const;
140 
141  /// Flush output stream
142  void Flush(void) const;
143 
144  /// Write HTTP response header to the output stream
145  CNcbiOstream& WriteHeader(void) const;
146  CNcbiOstream& WriteHeader(CNcbiOstream& os) const;
147  bool IsHeaderWritten() const;
148  /// Define if WriteHeader() must be called or can be skipped.
149  /// @param require
150  /// true - report (to application log) if WriteHeader has not
151  /// been called by the end of ProcessRequest();
152  /// false - allow to skip WriteHeader call (e.g when the user
153  /// writes custom HTTP header directly to the output
154  /// stream).
155  /// The default setting is 'true'.
156  void RequireWriteHeader(bool require);
157 
158  void SetTrackingCookie(const string& name, const string& value,
159  const string& domain, const string& path,
160  const CTime& exp_time = CTime());
161 
162  void DisableTrackingCookie(void);
163 
164  /// If set to TRUE then the writes to a "bad" output stream
165  /// will throw exceptions of type std::ios_base::failure.
166  /// @sa GetOutput()
167  void SetThrowOnBadOutput(bool throw_on_bad_output);
168 
169  // If enabled, HEAD request will cause the application to exit
170  // immediately after writing headers. For this option to work
171  // correctly ProcessRequest must allow CCgiHeadException to
172  // be caught by CCgiApplication::Run().
173  // If the option is disabled, no exception is thrown and the application
174  // continues to run, but the output stream is blocked so that no more data
175  // can be sent to the client.
176  void SetExceptionAfterHEAD(bool expt_after_head);
177 
178  /// Check if 'Accept-Ranges' header is set to 'bytes'.
179  bool AcceptRangesBytes(void) const;
180 
181  /// Check if 'Content-Range' header is set.
182  bool HaveContentRange(void) const;
183 
184  /// This method is called automatically by CCgiContext.
185  /// Initialize cross-origin resource sharing (CORS) headers.
186  /// @param origin
187  /// Must match allowed origins for the CORS to be enabled.
188  /// @param jquery_callback
189  /// Used to enable JQuery JSONP hack to allow cross-origin resource
190  /// sharing for browsers that don't support CORS (e.g. IE versions
191  /// earlier than 11). For more info about this (hopefully temporary) hack
192  /// see the sources.
193  /// @deprecated Use CCgiContext::ProcessCORSRequest
195  void InitCORSHeaders(const string& origin,
196  const string& jquery_callback = kEmptyStr);
197 
198  /// Set HTTP request method.
199  void SetRequestMethod(CCgiRequest::ERequestMethod method);
200 
201  /// Called by the CGI framework after a ProcessRequest(), unless the
202  /// latter threw an exception.
203  /// @note It still gets called if ProcessRequest() returns non-zero code.
204  /// @attention
205  /// Do not call it directly from the user code!
206  void Finalize(void) const;
207 
208  /// Set retry headers from the context.
209  void SetRetryContext(const CRetryContext& ctx);
210 
211  void SetCgiRequest(const CCgiRequest& request);
212 
213  /// Check/change chunked transfer encoding status. This flag is used only
214  /// if CGI_CHUNKED_TRANSFER is not set.
215  bool GetChunkedTransferEnabled(void) const;
216  void SetChunkedTransferEnabled(bool value);
217 
218  static size_t GetChunkSize(void);
219 
220  /// Finish chunked transfer, append zero chunk and trailers, if any.
221  /// All trailers must be set before calling this method.
222  void FinishChunkedTransfer(void);
223  /// Abort chunked transfer, block any writes to the output stream.
224  void AbortChunkedTransfer(void);
225 
226  /// Check if trailer can be sent: chunked transfer must be enabled
227  /// and the request's TE header must include 'trailers'.
228  /// All trailer getters/setters are no-op if this condition is false.
229  /// This will always return false after FinishChunkedTransfer() has been
230  /// called.
231  bool CanSendTrailer(void) const;
232  /// Prepare to send trailer. This must be called before WriteHeader()
233  /// to allow the trailer value to be set later.
234  /// Some fields are not allowed to be sent as trailers - see RFC7230:
235  /// https://tools.ietf.org/html/rfc7230#section-4.1.2
236  void AddTrailer(const string& name);
237  /// Remove trailer. Must be called before WriteHeader().
238  void RemoveTrailer(const string& name);
239  /// Check if trailer has been added and its value can be set.
240  bool HaveTrailer(const string& name) const;
241  /// Get current trailer value.
242  string GetTrailerValue(const string& name) const;
243  /// Set trailer value. The trailer should have been added using
244  /// AddTrailer().
245  void SetTrailerValue(const string& name, const string& value);
246 
247 public:
248  void x_SetSession(const CCgiSession& session);
249 
250 protected:
251  static const char* sm_ContentTypeName; // Content type header name
252  static const char* sm_LocationName; // Location header name
253  static const char* sm_ContentTypeDefault; // Dflt content type: text/html
254  static const char* sm_ContentTypeMixed; // multipart/mixed
255  static const char* sm_ContentTypeRelated; // multipart/related
256  static const char* sm_ContentTypeXMR; // multipart/x-mixed-replace
257  static const char* sm_ContentDispoName; // Content-Disposition
258  static const char* sm_FilenamePrefix; // Syntax preceding the fname
259  static const char* sm_HTTPStatusName; // Status header name: Status
260  static const char* sm_HTTPStatusDefault; // Default HTTP status: 200 OK
261  static const char* sm_BoundaryPrefix; // Start of multipart boundary
262  static const char* sm_CacheControl; // Cache-Control
263  static const char* sm_AcceptRanges; // Accept-Ranges
264  static const char* sm_AcceptRangesBytes; // bytes
265  static const char* sm_ContentRange; // Content-Range
266 
268 
269  bool m_IsRawCgi; // The "raw CGI" flag
270  EMultipartMode m_IsMultipart; // (Three-way) multipart flag
271  bool m_BetweenParts; // Did we already print the boundary?
272  string m_Boundary; // Multipart boundary
273  TMap m_HeaderValues; // Header lines in alphabetical order
274  TMap m_TrailerValues; // Trailer lines (for chunked transfers)
275  CCgiCookies m_Cookies; // Cookies
276  CNcbiOstream* m_Output; // Default output stream
277  int m_OutputFD; // Output file descriptor, if available
278  mutable bool m_HeaderWritten; // Did we already complete the header?
279  bool m_RequireWriteHeader; // Check if WriteHeader was called?
280  CNcbiOstream::iostate m_OutputExpt; // Original output exceptions
281  CCgiRequest::ERequestMethod m_RequestMethod; // Request method from CCgiRequest
282 
283  // Prohibit copy constructor and assignment operator
285  CCgiResponse& operator= (const CCgiResponse&);
286 
287 private:
288  void x_RestoreOutputExceptions(void);
289  bool x_ValidateHeader(const string& name, const string& value) const;
290 
291  static bool x_ClientSupportsChunkedTransfer(const CNcbiEnvironment& env);
292 
294  unique_ptr<CCgiCookie> m_TrackingCookie;
296 
297  NCBI_PARAM_DECL(bool, CGI, ThrowOnBadOutput);
298  typedef NCBI_PARAM_TYPE(CGI, ThrowOnBadOutput) TCGI_ThrowOnBadOutput;
299  TCGI_ThrowOnBadOutput m_ThrowOnBadOutput;
300 
301  NCBI_PARAM_DECL(bool, CGI, ExceptionAfterHEAD);
302  typedef NCBI_PARAM_TYPE(CGI, ExceptionAfterHEAD) TCGI_ExceptionAfterHEAD;
303  TCGI_ExceptionAfterHEAD m_ExceptionAfterHEAD;
304 
307  mutable unique_ptr<bool> m_TrailerEnabled;
308 
309  friend class CCgiContext; // to set m_JQuery_Callback
310  friend class CCgiApplication; // need x_ClientSupportsChunkedTransfer()
311 
313 };
314 
315 
316 
317 /* @} */
318 
319 
320 
321 
322 /////////////////////////////////////////////////////////////////////////////
323 // IMPLEMENTATION of INLINE functions
324 /////////////////////////////////////////////////////////////////////////////
325 
326 
327 inline void CCgiResponse::SetRawCgi(bool is_raw)
328 {
329  m_IsRawCgi = is_raw;
330 }
331 
332 inline bool CCgiResponse::IsRawCgi(void) const
333 {
334  return m_IsRawCgi;
335 }
336 
337 inline void CCgiResponse::SetContentType(const string& type)
338 {
340 }
341 
342 inline string CCgiResponse::GetContentType(void) const
343 {
345 }
346 
347 inline void CCgiResponse::SetLocation(const CUrl& url,
348  const IUrlEncoder* encoder)
349 {
351  url.ComposeUrl(CUrlArgs::eAmp_Char, encoder));
352 }
353 
355 {
358 }
359 
361 {
362  return m_IsMultipart;
363 }
364 
365 inline void CCgiResponse::BeginPart(const string& name, const string& type,
366  size_t /*size*/)
367 {
368  BeginPart(name, type, out());
369 }
370 
371 inline void CCgiResponse::EndPart(void)
372 {
373  EndPart(out());
374 }
375 
376 inline void CCgiResponse::EndLastPart(void)
377 {
378  EndLastPart(out());
379 }
380 
381 inline const CCgiCookies& CCgiResponse::Cookies(void) const
382 {
383  return m_Cookies;
384 }
385 
387 {
388  return m_Cookies;
389 }
390 
391 inline int CCgiResponse::GetOutputFD(void) const
392 {
393  return m_OutputFD;
394 }
395 
397 {
398  return WriteHeader(out());
399 }
400 
401 inline void CCgiResponse::RequireWriteHeader(bool require)
402 {
403  m_RequireWriteHeader = require;
404 }
405 
406 inline bool CCgiResponse::IsHeaderWritten(void) const
407 {
408  return m_HeaderWritten;
409 }
410 
411 inline void CCgiResponse::SetCgiRequest(const CCgiRequest& request)
412 {
413  m_Request = &request;
414 }
415 
416 inline void CCgiResponse::x_SetSession(const CCgiSession& session)
417 {
418  m_Session = &session;
419 }
420 
421 
423 {
424  m_RequestMethod = method;
425 }
426 
427 
429 
430 #endif /* CGI___NCBICGIR__HPP */
CCgiCookies::
Definition: ncbicgi.hpp:219
CCgiRequest::
Definition: ncbicgi.hpp:685
CCgiSession –.
Definition: cgi_session.hpp:62
CNcbiEnvironment –.
Definition: ncbienv.hpp:104
CRetryContext – Retry context.
Definition: retry_ctx.hpp:58
CTime –.
Definition: ncbitime.hpp:296
CUrl –.
Definition: ncbi_url.hpp:353
IUrlEncoder::
Definition: ncbi_url.hpp:57
char value[7]
Definition: config.c:431
CS_CONTEXT * ctx
Definition: t0006.c:12
std::ofstream out("events_result.xml")
main entry point for tests
DisableTrackingCookie
Definition: cgiapp.hpp:685
CGI
Definition: cgiapp.hpp:685
static const char * sm_HTTPStatusName
Definition: ncbicgir.hpp:259
const CCgiRequest * m_Request
Definition: ncbicgir.hpp:305
unique_ptr< bool > m_TrailerEnabled
Definition: ncbicgir.hpp:307
void SetRequestMethod(CCgiRequest::ERequestMethod method)
Set HTTP request method.
Definition: ncbicgir.hpp:422
void EndPart(void)
Definition: ncbicgir.hpp:371
static const char * sm_ContentRange
Definition: ncbicgir.hpp:265
void SetMultipartMode(EMultipartMode mode=eMultipart_mixed)
Definition: ncbicgir.hpp:354
string GetContentType(void) const
Get content type.
Definition: ncbicgir.hpp:342
map< string, string, PNocase > TMap
Definition: ncbicgir.hpp:267
static const char * sm_CacheControl
Definition: ncbicgir.hpp:262
CNcbiOstream * m_Output
Definition: ncbicgir.hpp:276
void SetHeaderValue(const string &name, const string &value)
Definition: ncbicgir.cpp:151
unique_ptr< CCgiCookie > m_TrackingCookie
Definition: ncbicgir.hpp:294
void x_SetSession(const CCgiSession &session)
Definition: ncbicgir.hpp:416
static const char * sm_AcceptRanges
Definition: ncbicgir.hpp:263
CCgiRequest::ERequestMethod m_RequestMethod
Definition: ncbicgir.hpp:281
void SetLocation(const CUrl &url, const IUrlEncoder *encoder=0)
Set the "Location:" HTTP header.
Definition: ncbicgir.hpp:347
NCBI_PARAM_DECL(bool, CGI, ExceptionAfterHEAD)
static const char * sm_ContentTypeMixed
Definition: ncbicgir.hpp:254
static const char * sm_ContentTypeDefault
Definition: ncbicgir.hpp:253
string m_JQuery_Callback
Definition: ncbicgir.hpp:312
void SetRawCgi(bool is_raw)
Definition: ncbicgir.hpp:327
bool m_RequireWriteHeader
Definition: ncbicgir.hpp:279
string m_Boundary
Definition: ncbicgir.hpp:272
static const char * sm_FilenamePrefix
Definition: ncbicgir.hpp:258
static const char * sm_ContentTypeName
Definition: ncbicgir.hpp:251
CNcbiOstream::iostate m_OutputExpt
Definition: ncbicgir.hpp:280
CNcbiOstream & out(void) const
Get output stream. Throw exception if GetOutput() is NULL.
Definition: ncbicgir.cpp:257
TMap m_TrailerValues
Definition: ncbicgir.hpp:274
static const char * sm_ContentTypeRelated
Definition: ncbicgir.hpp:255
static const char * sm_ContentDispoName
Definition: ncbicgir.hpp:257
typedef NCBI_PARAM_TYPE(CGI, ExceptionAfterHEAD) TCGI_ExceptionAfterHEAD
EMultipartMode m_IsMultipart
Definition: ncbicgir.hpp:270
bool m_ChunkedTransfer
Definition: ncbicgir.hpp:306
void SetCgiRequest(const CCgiRequest &request)
Definition: ncbicgir.hpp:411
void RequireWriteHeader(bool require)
Define if WriteHeader() must be called or can be skipped.
Definition: ncbicgir.hpp:401
bool m_DisableTrackingCookie
Definition: ncbicgir.hpp:295
NCBI_PARAM_DECL(bool, CGI, ThrowOnBadOutput)
static const char * sm_HTTPStatusDefault
Definition: ncbicgir.hpp:260
CCgiCookies m_Cookies
Definition: ncbicgir.hpp:275
const CCgiCookies & Cookies(void) const
Definition: ncbicgir.hpp:381
static const char * sm_LocationName
Definition: ncbicgir.hpp:252
TMap m_HeaderValues
Definition: ncbicgir.hpp:273
CCgiResponse(const CCgiResponse &)
bool IsHeaderWritten() const
Definition: ncbicgir.hpp:406
void EndLastPart(void)
Definition: ncbicgir.hpp:376
void SetContentType(const string &type)
Set content type (text/html by default if not provided)
Definition: ncbicgir.hpp:337
string GetHeaderValue(const string &name) const
Definition: ncbicgir.cpp:117
typedef NCBI_PARAM_TYPE(CGI, ThrowOnBadOutput) TCGI_ThrowOnBadOutput
CNcbiOstream & WriteHeader(void) const
Write HTTP response header to the output stream.
Definition: ncbicgir.hpp:396
bool IsRawCgi(void) const
Definition: ncbicgir.hpp:332
ERequestMethod
Standard request methods.
Definition: ncbicgi.hpp:905
static const char * sm_AcceptRangesBytes
Definition: ncbicgir.hpp:264
const CCgiSession * m_Session
Definition: ncbicgir.hpp:293
static const char * sm_ContentTypeXMR
Definition: ncbicgir.hpp:256
TCGI_ThrowOnBadOutput m_ThrowOnBadOutput
Definition: ncbicgir.hpp:299
bool m_BetweenParts
Definition: ncbicgir.hpp:271
static const char * sm_BoundaryPrefix
Definition: ncbicgir.hpp:261
int GetOutputFD(void) const
Get file descriptor of the output stream (-1 if not applicable)
Definition: ncbicgir.hpp:391
bool m_HeaderWritten
Definition: ncbicgir.hpp:278
void BeginPart(const string &name, const string &type, size_t size=0)
Definition: ncbicgir.hpp:365
bool m_IsRawCgi
Definition: ncbicgir.hpp:269
EMultipartMode GetMultipartMode(void)
Definition: ncbicgir.hpp:360
TCGI_ExceptionAfterHEAD m_ExceptionAfterHEAD
Definition: ncbicgir.hpp:303
@ eMultipart_related
Definition: ncbicgir.hpp:102
#define NULL
Definition: ncbistd.hpp:225
string GetStringUID(TUID uid=0) const
Return string representation of UID.
Definition: ncbidiag.cpp:1691
CDiagContext & GetDiagContext(void)
Get diag context instance.
Definition: logging.cpp:818
#define NCBI_DEPRECATED
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
IO_PREFIX::ostream CNcbiOstream
Portable alias for ostream.
Definition: ncbistre.hpp:149
#define kEmptyStr
Definition: ncbistr.hpp:123
string ComposeUrl(CUrlArgs::EAmpEncoding amp_enc, const IUrlEncoder *encoder=0) const
Compose the URL.
Definition: ncbi_url.cpp:568
@ eAmp_Char
Use & to separate arguments.
Definition: ncbi_url.hpp:254
#define NCBI_XCGI_EXPORT
Definition: ncbi_export.h:1097
mdb_mode_t mode
Definition: lmdb++.h:38
const struct ncbi::grid::netcache::search::fields::SIZE size
Defines: CTimeFormat - storage class for time format.
static const GLdouble origin[]
Retry context class.
Definition: inftrees.h:24
Definition: type.c:6
static HENV env
Definition: transaction2.c:38
Modified on Sat Dec 02 09:23:14 2023 by modify_doxy.py rev. 669887