📄 sbinethttpstream.cpp
字号:
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 + -