📄 sbinethttpstream.cpp
字号:
// Skip comma, or if at end of string, stop parsing.
if (*value)
value++;
else
break;
}
}
void SBinetHttpStream::defaultHeaderHandler(HeaderInfo *headerInfo,
const char *value,
SBinetHttpStream *httpStream,
VXIMap *streamInfo)
{
VXIValue* vxi_value = NULL;
bool listF = (headerInfo->value_type & HANDLER_LIST) == HANDLER_LIST;
int value_type = headerInfo->value_type & ~HANDLER_LIST;
const VXIchar *property = NULL;
SBinetString *propTmp = NULL;
if (headerInfo->inet_property != NULL)
{
property = headerInfo->inet_property;
}
else
{
propTmp = new SBinetString(headerInfo->header);
property = propTmp->c_str();
}
switch (value_type)
{
case HANDLER_INT:
vxi_value = (VXIValue *) VXIIntegerCreate(atoi(value));
break;
case HANDLER_STRING:
if (listF)
{
const VXIchar *v = SBinetUtils::getString(streamInfo, property);
if (v != NULL)
{
SBinetString tmp = v;
tmp += L", ";
tmp += value;
vxi_value = (VXIValue *) VXIStringCreate(tmp.c_str());
}
}
if (vxi_value == NULL)
{
vxi_value = (VXIValue *) VXIStringCreate(SBinetString(value).c_str());
}
break;
case HANDLER_DATE:
{
// FIXME: Portability issue. This code assumes that a time_t can be
// stored in a VXIint32 without losing any information. Two possible
// options: extend VXIValue with a VXILong type or use VXIContent.
time_t timestamp = ap_parseHTTPdate(value);
vxi_value = (VXIValue *) VXIIntegerCreate(timestamp);
}
break;
case HANDLER_CONTENT:
if (listF)
{
const char *content;
VXIulong contentLength;
if (SBinetUtils::getContent(streamInfo, property, content, contentLength))
{
SBinetNString tmp = content;
tmp += ", ";
tmp += value;
vxi_value = (VXIValue *) SBinetUtils::createContent(tmp.c_str());
}
}
if (vxi_value == NULL)
{
vxi_value = (VXIValue *) SBinetUtils::createContent(value);
}
break;
default:
break;
}
if (vxi_value != NULL)
{
VXIMapSetProperty(streamInfo, property, vxi_value);
}
else
{
httpStream->Diag(MODULE_SBINET_STREAM_TAGID,
L"SBinetHttpStream::defaultHeaderHandler",
L"Could not create VXI value, header: <%S>, value: <%S>",
headerInfo->header,
value);
}
delete propTmp;
}
SBinetHttpStream::HeaderInfo *SBinetHttpStream::findHeaderInfo(const char *header)
{
for (int i = 0; headerInfoMap[i].header != NULL; i++)
{
if (::strcasecmp(headerInfoMap[i].header, header) == 0)
{
return &headerInfoMap[i];
}
}
return NULL;
}
void SBinetHttpStream::processHeader(const char *header,
const char *value,
VXIMap* streamInfo)
{
HeaderInfo *headerInfo = findHeaderInfo(header);
// If it is not found, we ignore it.
if (headerInfo == NULL) return;
HeaderHandler handler = headerInfo->handler;
if (handler == NULL) handler = defaultHeaderHandler;
(*handler)(headerInfo, value, this, streamInfo);
}
static const unsigned long BREAK_AT_INITIAL_NEWLINE = 0x01;
static const unsigned long CONTINUE_AT_NEWLINE = 0x02;
int SBinetHttpStream::getValue(char *&value, unsigned long mask)
{
char c;
bool done = false;
// skip white spaces.
for (;;)
{
if ((c = _channel->readChar(_inputStream)) < 0)
return -8;
if (!ap_isspace(c))
break;
switch (c)
{
case '\r':
if ((c = _channel->readChar(_inputStream)) != '\n')
return -5;
// no break: intentional
case '\n':
if (mask & BREAK_AT_INITIAL_NEWLINE)
{
if ((c = _inputStream->peek()) < 0) return -6;
if (!ap_isspace(c)) done = true;
}
if (done)
{
value = new char[2];
*value = '\0';
Diag(MODULE_SBINET_STREAM_TAGID,
L"SBinetHttpStream::getValue",
L"value = '%S'", value);
return 0;
}
break;
default:
break;
}
}
int len = 0;
int bufSize = 32;
value = new char[bufSize];
for (;;)
{
if (len == bufSize)
{
int newBufSize = (bufSize << 1);
char *new_value = ::strncpy(new char[newBufSize], value, bufSize);
delete [] value;
value = new_value;
bufSize = newBufSize;
}
if (c == '\r')
{
if ((c = _channel->readChar(_inputStream)) != '\n')
break;
}
// We need to verify if the value continues on the next line.
if (c == '\n')
{
if (mask & CONTINUE_AT_NEWLINE)
{
if ((c = _inputStream->peek()) < 0)
break;
if (!ap_isspace(c) || c == '\r' || c == '\n')
done = true;
}
else
done = true;
if (done)
{
// remove trailing blanks and terminate string.
while (len > 0 && ap_isspace(value[len-1])) len--;
value[len] = '\0';
Diag(MODULE_SBINET_STREAM_TAGID,
L"SBinetHttpStream::getValue",
L"value = '%S'", value);
return 0;
}
}
value[len++] = c;
if ((c = _channel->readChar(_inputStream)) < 0)
break;
}
// If we get here, we got an error parsing the line.
delete [] value;
value = NULL;
return -7;
}
int SBinetHttpStream::getHeader(char *&header, char delimiter)
{
int c;
if ((c = _channel->readChar(_inputStream)) < 0)
return -1;
// Check for end of headers.
if (c == '\r')
{
if ((c = _channel->readChar(_inputStream)) != '\n')
return -2;
return 1;
}
if (c == '\n') return 2;
if (ap_isspace(c) || c == (unsigned char) delimiter)
return -3;
int len = 0;
int bufSize = 32;
header = new char[bufSize];
for (;;)
{
if (len == bufSize)
{
int newBufSize = bufSize << 1;
char *new_header = ::strncpy(new char[newBufSize], header, bufSize);
delete [] header;
header = new_header;
bufSize = newBufSize;
}
if (c == (unsigned char) delimiter)
{
header[len++] = '\0';
Diag(MODULE_SBINET_STREAM_TAGID,
L"SBinetHttpStream::getHeader",
L"header = '%S'", header);
return 0;
}
header[len++] = c;
if ((c = _channel->readChar(_inputStream)) < 0 || ap_isspace(c))
break;
}
delete [] header;
header = NULL;
return -4;
}
int SBinetHttpStream::getHeaderValue(char *&header, char *&value)
{
int rc = getHeader(header, ':');
if (rc == 0)
{
rc = getValue(value, CONTINUE_AT_NEWLINE | BREAK_AT_INITIAL_NEWLINE);
if (rc != 0)
{
Error(250, NULL);
delete [] header;
header = NULL;
}
}
else if (rc < 0)
Error(250, NULL);
return rc;
}
VXIinetResult SBinetHttpStream::parseHeaders(VXIMap* streamInfo)
{
char *header = NULL;
char *value = NULL;
VXIinetResult rc1;
int rc2;
while (((rc1 = waitStreamReady()) == VXIinet_RESULT_SUCCESS) &&
((rc2 = getHeaderValue(header, value)) == 0))
{
if (streamInfo) processHeader(header, value, streamInfo);
delete [] header;
delete [] value;
}
if (rc1 == VXIinet_RESULT_SUCCESS && rc2 < 0)
{
Diag(MODULE_SBINET_STREAM_TAGID,
L"SBinetHttpStream::parseHeaders",
L"Error in parsing header line: URL = <%s>, METHOD = %s, rc2 = %d",
_url->getAbsolute(),
_method == GET_METHOD ? L"GET" : L"POST",
rc2);
rc1 = VXIinet_RESULT_NON_FATAL_ERROR;
}
return rc1;
}
void SBinetHttpStream::processHeaderInfo(VXIMap *streamInfo)
{
// Extract the content-length to find out how many bytes are left to be
// read from the stream. If the stream is chunked, ignore
// content-length from the server. If we don't have the content, we
// have to set the property to 0.
VXIulong contentSize = (_chunked || _leftToRead == ~0) ? 0 : _leftToRead;
VXIMapSetProperty(streamInfo, INET_INFO_SIZE_BYTES,
(VXIValue *) VXIIntegerCreate((int) contentSize));
const VXIchar *tmp = _url->getAbsolute();
if (tmp != NULL)
{
Diag(MODULE_SBINET_STREAM_TAGID,
L"SBinetHttpStream::processHeaderInfo", L"%s%s",
L"absolute", tmp);
VXIMapSetProperty(streamInfo,
INET_INFO_ABSOLUTE_NAME,
(VXIValue*)VXIStringCreate(tmp));
}
const VXIString *contentType =
(const VXIString *) VXIMapGetProperty(streamInfo, INET_INFO_MIME_TYPE);
tmp = contentType != NULL ? VXIStringCStr(contentType) : NULL;
if (!tmp || !*tmp
|| ::wcscmp(tmp, _channel->getDefaultMimeType()) == 0)
{
VXIString *newContentType = _url->getContentTypeFromUrl();
if (newContentType != NULL)
{
Error (300, L"%s%s%s%s",
L"URL", _url->getAbsolute(),
L"mime-type", VXIStringCStr(newContentType));
}
else
{
newContentType = VXIStringCreate(_channel->getDefaultMimeType());
Error (301, L"%s%s", L"URL", _url->getAbsolute());
}
VXIMapSetProperty(streamInfo, INET_INFO_MIME_TYPE,
(VXIValue *) newContentType);
}
}
void SBinetHttpStream::setValidatorInfo(VXIMap *streamInfo, time_t requestTime)
{
_validator = new SBinetValidator(GetLog(), GetDiagBase());
if (_validator->Create(_url->getAbsolute(), requestTime, streamInfo) == VXIinet_RESULT_SUCCESS)
{
SBinetUtils::setValidatorInfo(streamInfo, _validator);
}
}
VXIinetResult SBinetHttpStream::getHeaderInfo(VXIMap* streamInfo)
{
SWITimeWatch timeWatch;
timeWatch.start();
VXIinetResult rc = getStatus();
Diag(MODULE_SBINET_TIMING_TAGID, L"SBinetHttpStream::getStatus",
L"%i msecs, Wait for HTTP response", timeWatch.getElapsed());
if (rc == VXIinet_RESULT_SUCCESS)
{
rc = parseHeaders(streamInfo);
}
Diag(MODULE_SBINET_STREAM_TAGID, L"SBinetHttpStream::getHeaderInfo",
L"rc = %d, HttpStatus = %d", rc, _HttpStatus);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -