48 # define STDOUT_FILENO 1
52 #define NCBI_USE_ERRCODE_X Cgi_Response
81 return ::memcmp(&date, &
kZeroTime,
sizeof(tm)) == 0;
87 m_IsMultipart(eMultipart_none),
88 m_BetweenParts(
false),
91 m_HeaderWritten(
false),
92 m_RequireWriteHeader(
true),
95 m_DisableTrackingCookie(
false),
97 m_ChunkedTransfer(
false)
134 if (name.find(
"\n", 0) !=
NPOS) {
138 size_t pos =
value.find(
"\n", 0);
139 while (pos !=
NPOS) {
141 if (pos >=
value.size())
break;
142 if (
value[pos] !=
' ' &&
value[pos] !=
'\t') {
145 pos =
value.find(
"\n", pos);
153 if (
value.empty() ) {
161 "CCgiResponse::SetHeaderValue() -- "
162 "invalid header name or value: " +
177 if ( !::strftime(buff,
sizeof(buff),
178 "%a, %d %b %Y %H:%M:%S GMT", &date) ) {
180 "CCgiResponse::SetHeaderValue() -- strftime() failed");
201 "CCgiResponse::SetStatus() -- code too small, below 100");
205 "CCgiResponse::SetStatus() -- code too big, exceeds 999");
234 m_Output->exceptions(IOS_BASE::badbit | IOS_BASE::failbit);
241 bool client_int_ok = TClientConnIntOk::GetDefault() ||
247 (
m_Output->rdstate() & (IOS_BASE::badbit | IOS_BASE::failbit)) != 0 &&
250 "CCgiResponse::GetOutput() -- output stream is in bad state");
260 THROW1_TRACE(runtime_error,
"CCgiResponse::out() on NULL out.stream");
271 "CCgiResponse::WriteHeader() -- called more than once");
279 bool skip_status =
false;
282 if ( status.empty() ) {
287 os <<
"HTTP/1.1 " << status <<
HTTP_EOL;
304 self->m_JQuery_Callback.erase();
345 self->SetHeaderValue(TCGI_TrackingTagName::GetDefault(),
361 "Cache-Control already set to 'public', "
362 "switching to 'private'");
366 cc.append(
", private");
386 os <<
i->first <<
": " <<
i->second <<
HTTP_EOL;
389 if ( chunked_transfer ) {
391 os <<
"Transfer-Encoding: chunked" <<
HTTP_EOL;
396 if ( !trailer.empty() ) {
397 trailer.append(
", ");
399 trailer.append(it->first);
401 os <<
"Trailer: " << trailer <<
HTTP_EOL;
415 os << it->first <<
": " << it->second <<
HTTP_EOL;
443 else if ( chunked_transfer ) {
461 ERR_POST_X(5,
"CCgiResponse::WriteHeader() has not been called - "
462 "HTTP header can be missing.");
474 disposition +=
"; size=";
489 string type = type_in;
496 if ( !name.empty() ) {
500 os <<
"; size=" <<
size;
532 if (!os || !os->good()) {
540 const string& domain,
const string& path,
541 const CTime& exp_time)
566 if (
m_Output && throw_on_bad_output) {
568 m_Output->exceptions(IOS_BASE::badbit | IOS_BASE::failbit);
603 ctx.GetValues(values);
635 return TCGI_ChunkSize::GetDefault();
642 const string& protocol =
env.Get(
"SERVER_PROTOCOL");
649 switch ( TCGI_ChunkedTransfer::GetDefault() ) {
668 ERR_POST_X(6,
"Attempt to enable chunked transfer after writing "
706 ITERATE(list<string>, it, parts) {
746 ERR_POST_X(7,
"Can not set trailer not announced in HTTP header: "
755 "CCgiResponse::SetTrailerValue() -- "
756 "invalid trailer name or value: " +
Exception classes used by the NCBI CGI framework.
API to store CGI session data between Web requests.
CCgiResponseException –.
CRetryContext – Retry context.
container_type::const_iterator const_iterator
const_iterator end() const
const_iterator lower_bound(const key_type &key) const
const_iterator find(const key_type &key) const
#define ITERATE(Type, Var, Cont)
ITERATE macro to sequence through container elements.
void AbortChunkedTransfer(void)
EStreamMode GetWriterMode(void)
void SetWriterMode(EStreamMode mode)
void FinishChunkedTransfer(const TTrailer *trailer)
#define NCBI_CGI_THROW_WITH_STATUS(exception, err_code, message, status)
static string GetStdStatusMessage(EStatusCode code)
EStatusCode
HTTP status codes.
bool HaveContentRange(void) const
Check if 'Content-Range' header is set.
static const char * sm_HTTPStatusName
const CCgiRequest * m_Request
unique_ptr< bool > m_TrailerEnabled
void SetSecure(bool secure)
static const char * sm_ContentRange
void RemoveTrailer(const string &name)
Remove trailer. Must be called before WriteHeader().
bool CanSendTrailer(void) const
Check if trailer can be sent: chunked transfer must be enabled and the request's TE header must inclu...
static const char * sm_CacheControl
void AbortChunkedTransfer(void)
Abort chunked transfer, block any writes to the output stream.
void SetHeaderValue(const string &name, const string &value)
string GetTrailerValue(const string &name) const
Get current trailer value.
unique_ptr< CCgiCookie > m_TrackingCookie
void SetChunkedTransferEnabled(bool value)
void x_RestoreOutputExceptions(void)
static const char * sm_AcceptRanges
CCgiRequest::ERequestMethod m_RequestMethod
void SetThrowOnBadOutput(bool throw_on_bad_output)
If set to TRUE then the writes to a "bad" output stream will throw exceptions of type std::ios_base::...
static const char * sm_ContentTypeMixed
static const char * sm_ContentTypeDefault
void Flush(void) const
Flush output stream.
bool m_RequireWriteHeader
void SetExceptionAfterHEAD(bool expt_after_head)
static const char * sm_FilenamePrefix
static const char * sm_ContentTypeName
CNcbiOstream::iostate m_OutputExpt
CNcbiOstream & out(void) const
Get output stream. Throw exception if GetOutput() is NULL.
void AddTrailer(const string &name)
Prepare to send trailer.
static const char * sm_ContentTypeRelated
void SetFilename(const string &name, size_t size=0)
static const char * sm_ContentDispoName
void SetStatus(unsigned int code, const string &reason=kEmptyStr)
EMultipartMode m_IsMultipart
CCgiResponse(CNcbiOstream *os=NULL, int ofd=-1)
void SetTrackingCookie(const string &name, const string &value, const string &domain, const string &path, const CTime &exp_time=CTime())
const CNcbiEnvironment & GetEnvironment() const
static bool x_ClientSupportsChunkedTransfer(const CNcbiEnvironment &env)
void SetOutput(CNcbiOstream *os, int fd=-1)
Set output stream (NULL here means "no output stream").
void SetHttpOnly(bool http_only)
bool m_DisableTrackingCookie
static const char * sm_HTTPStatusDefault
CCgiCookie * Add(const string &name, const string &value, const string &domain=kEmptyStr, const string &path=kEmptyStr, EOnBadCookie on_bad_cookie=eOnBadCookie_SkipAndError)
All Add() functions: if the added cookie has the same {name, domain, path} as an already existing one...
static size_t GetChunkSize(void)
void Finalize(void) const
Called by the CGI framework after a ProcessRequest(), unless the latter threw an exception.
bool HaveTrailer(const string &name) const
Check if trailer has been added and its value can be set.
static const char * sm_LocationName
bool AcceptRangesBytes(void) const
Check if 'Accept-Ranges' header is set to 'bytes'.
string GetHeaderValue(const string &name) const
const string & GetRandomProperty(const string &key, bool http=true) const
Get value of a random client property; if "http" is TRUE then add prefix "HTTP_" to the property name...
void SetRetryContext(const CRetryContext &ctx)
Set retry headers from the context.
bool HaveHeaderValue(const string &name) const
bool x_ValidateHeader(const string &name, const string &value) const
bool GetAllCookiesSecure(void) const
void SetTrailerValue(const string &name, const string &value)
Set trailer value.
void FinishChunkedTransfer(void)
Finish chunked transfer, append zero chunk and trailers, if any.
CNcbiOstream & WriteHeader(void) const
Write HTTP response header to the output stream.
bool IsRawCgi(void) const
void InitCORSHeaders(const string &origin, const string &jquery_callback=kEmptyStr)
This method is called automatically by CCgiContext.
bool GetAllCookiesHttpOnly(void) const
void RemoveHeaderValue(const string &name)
static const char * sm_AcceptRangesBytes
const CCgiSession * m_Session
CNcbiOstream * GetOutput(void) const
Get output stream (NULL here means "no output stream").
static const char * sm_ContentTypeXMR
TCGI_ThrowOnBadOutput m_ThrowOnBadOutput
bool GetChunkedTransferEnabled(void) const
Check/change chunked transfer encoding status.
bool Empty(void) const
Return TRUE if this set contains no cookies.
static const char * sm_BoundaryPrefix
void BeginPart(const string &name, const string &type, size_t size=0)
void DisableTrackingCookie(void)
TCGI_ExceptionAfterHEAD m_ExceptionAfterHEAD
const CCgiCookie * GetSessionCookie(void) const
Get a cookie pertaining to the session.
@ eEngine_IE
Microsoft Internet Explorer (Trident and etc)
int GetRequestStatus(void) const
Request exit status.
CDiagContext & GetDiagContext(void)
Get diag context instance.
const string & GetNextSubHitID(CTempString prefix=CTempString())
Get current hit id appended with auto-incremented sub-hit id.
#define ERR_POST_X_ONCE(err_subcode, message)
Error posting only once during program execution with default error code and given error subcode.
static CRequestContext & GetRequestContext(void)
Shortcut to CDiagContextThreadData::GetThreadData().GetRequestContext()
void SetRequestStatus(int status)
#define ERR_POST_X(err_subcode, message)
Error posting with default error code and given error subcode.
#define NCBI_THROW(exception_class, err_code, message)
Generic macro to throw an exception, given the exception class, error code and message string.
void Warning(CExceptionArgs_Base &args)
#define THROW1_TRACE(exception_class, exception_arg)
Throw trace.
@ eParam_NoThread
Do not use per-thread values.
#define END_NCBI_SCOPE
End previously defined NCBI scope.
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
string Printable(char c)
Convert one single character to a "printable" form.
IO_PREFIX::ostream CNcbiOstream
Portable alias for ostream.
static string SizetToString(size_t value, TNumToStringFlags flags=0, int base=10)
Convert size_t to string.
static string PrintableString(const CTempString str, TPrintableMode mode=fNewLine_Quote|fNonAscii_Passthru)
Get a printable version of the specified string.
static list< string > & Split(const CTempString str, const CTempString delim, list< string > &arr, TSplitFlags flags=0, vector< SIZE_TYPE > *token_pos=NULL)
Split a string using specified delimiters.
static SIZE_TYPE FindNoCase(const CTempString str, const CTempString pattern, SIZE_TYPE start, SIZE_TYPE end, EOccurrence which=eFirst)
Find the pattern in the specified range of a string using a case insensitive search.
static string UIntToString(unsigned int value, TNumToStringFlags flags=0, int base=10)
Convert UInt to string.
static bool StartsWith(const CTempString str, const CTempString start, ECase use_case=eCase)
Check if a string starts with a specified prefix value.
static bool EqualNocase(const CTempString s1, SIZE_TYPE pos, SIZE_TYPE n, const char *s2)
Case-insensitive equality of a substring with another string.
static string & ReplaceInPlace(string &src, const string &search, const string &replace, SIZE_TYPE start_pos=0, SIZE_TYPE max_replace=0, SIZE_TYPE *num_replace=0)
Replace occurrences of a substring within a string.
static string TruncateSpaces(const string &str, ETrunc where=eTrunc_Both)
Truncate spaces in a string.
@ fSplit_MergeDelimiters
Merge adjacent delimiters.
@ eNocase
Case insensitive compare.
string AsString(const CTimeFormat &format=kEmptyStr, TSeconds out_tz=eCurrentTimeZone) const
Transform time to string.
bool IsEmpty(void) const
Is time object empty (date and time)?
CTime & AddYear(int years=1, EDaylight adl=eDaylightDefault)
Add specified years and adjust for daylight saving time.
CTime GetGmtTime(void) const
@ eCurrent
Use current time. See also CCurrentTime.
@ eGmt
GMT (Greenwich Mean Time)
Definition of all error codes used in cgi (xcgi.lib).
pair< int, int > ChunkSize(const CSpliced_exon_chunk &chunk)
const struct ncbi::grid::netcache::search::fields::SIZE size
Static variables safety - create on demand, destroy on application termination.
static const tm kZeroTime
NCBI_PARAM_DEF_EX(size_t, CGI, ChunkSize, 4096, eParam_NoThread, CGI_CHUNK_SIZE)
NCBI_PARAM_ENUM_ARRAY(ECgiChunkedTransfer, CGI, ChunkedTransfer)
typedef NCBI_PARAM_TYPE(CGI, ChunkedTransfer) TCGI_ChunkedTransfer
NCBI_PARAM_DEF_IN_SCOPE(bool, CGI, ThrowOnBadOutput, true, CCgiResponse)
NCBI_PARAM_DECL(size_t, CGI, ChunkSize)
NCBI_PARAM_ENUM_DEF_EX(ECgiChunkedTransfer, CGI, ChunkedTransfer, eChunked_Default, eParam_NoThread, CGI_CHUNKED_TRANSFER)
NCBI_PARAM_ENUM_DECL(ECgiChunkedTransfer, CGI, ChunkedTransfer)
bool s_ZeroTime(const tm &date)
static SQLCHAR output[256]
Defines CRequestContext class for NCBI C++ diagnostic API.