REQUEST_NOTIFICATION_STATUS CNodeHttpModule::OnExecuteRequestHandler( IN IHttpContext* pHttpContext, IN IHttpEventProvider* pProvider) { UNREFERENCED_PARAMETER( pProvider ); // Create an HRESULT to receive return values from methods. HRESULT hr; // Retrieve a pointer to the response. IHttpResponse * pHttpResponse = pHttpContext->GetResponse(); // Test for an error. if (pHttpResponse != NULL) { // Clear the existing response. pHttpResponse->Clear(); // Set the MIME type to plain text. pHttpResponse->SetHeader( HttpHeaderContentType,"text/plain", (USHORT)strlen("text/plain"),TRUE); // Create a string with the response. PCSTR pszBuffer = "Hello World!"; // Create a data chunk. HTTP_DATA_CHUNK dataChunk; // Set the chunk to a chunk in memory. dataChunk.DataChunkType = HttpDataChunkFromMemory; // Buffer for bytes written of data chunk. DWORD cbSent; // Set the chunk to the buffer. dataChunk.FromMemory.pBuffer = (PVOID) pszBuffer; // Set the chunk size to the buffer size. dataChunk.FromMemory.BufferLength = (USHORT) strlen(pszBuffer); // Insert the data chunk into the response. hr = pHttpResponse->WriteEntityChunks( &dataChunk,1,FALSE,TRUE,&cbSent); // Test for an error. if (FAILED(hr)) { // Set the HTTP status. pHttpResponse->SetStatus(500,"Server Error",0,hr); } // End additional processing. return RQ_NOTIFICATION_FINISH_REQUEST; } // Return processing to the pipeline. return RQ_NOTIFICATION_CONTINUE; }
HRESULT CHttpProtocol::ParseResponseStatusLine(CNodeHttpStoredContext* context) { HRESULT hr; char* data = (char*)context->GetBuffer() + context->GetParsingOffset(); DWORD dataSize = context->GetDataSize() - context->GetParsingOffset(); DWORD offset = 0; USHORT major, minor; DWORD count, newOffset; char tmp[256]; USHORT statusCode, subStatusCode = 0; // HTTP-Version SP context->GetHttpContext()->GetRequest()->GetHttpVersion(&major, &minor); sprintf(tmp, "HTTP/%d.%d ", major, minor); count = strlen(tmp); ErrorIf(count >= dataSize, ERROR_MORE_DATA); ErrorIf(0 != memcmp(tmp, data, count), ERROR_BAD_FORMAT); offset += count; // Status-Code[.Sub-Status-Code] SP statusCode = 0; while (offset < dataSize && data[offset] >= '0' && data[offset] <= '9') { statusCode = statusCode * 10 + data[offset++] - '0'; } ErrorIf(offset == dataSize, ERROR_MORE_DATA); if ('.' == data[offset]) { // Sub-Status-Code offset++; while (offset < dataSize && data[offset] >= '0' && data[offset] <= '9') { subStatusCode = subStatusCode * 10 + data[offset++] - '0'; } ErrorIf(offset == dataSize, ERROR_MORE_DATA); } ErrorIf(' ' != data[offset], ERROR_BAD_FORMAT); offset++; // Reason-Phrase CRLF newOffset = offset; while (newOffset < (dataSize - 1) && data[newOffset] != 0x0D) { newOffset++; } ErrorIf(newOffset == dataSize - 1, ERROR_MORE_DATA); ErrorIf(0x0A != data[newOffset + 1], ERROR_BAD_FORMAT); // set HTTP response status line data[newOffset] = 0; // zero-terminate the reason phrase to reuse it without copying IHttpResponse* response = context->GetHttpContext()->GetResponse(); response->Clear(); response->SetStatus(statusCode, data + offset, subStatusCode); // adjust buffers context->SetParsingOffset(context->GetParsingOffset() + newOffset + 2); return S_OK; Error: return hr; }
HRESULT CHttpProtocol::ParseResponseStatusLine(CNodeHttpStoredContext* context) { HRESULT hr; char* data = (char*)context->GetBuffer() + context->GetParsingOffset(); DWORD dataSize = context->GetDataSize() - context->GetParsingOffset(); DWORD offset = 0; USHORT major, minor; DWORD count, newOffset; char tmp[256]; char* tmp1; USHORT statusCode, subStatusCode = 0; // HTTP-Version SP context->GetHttpContext()->GetRequest()->GetHttpVersion(&major, &minor); if (1 == major && 1 == minor) { tmp1 = "HTTP/1.1 "; count = 9; } else if (1 == major && 0 == minor) { tmp1 = "HTTP/1.0 "; count = 9; } else { sprintf(tmp, "HTTP/%d.%d ", major, minor); count = strlen(tmp); tmp1 = tmp; } ErrorIf(count >= dataSize, ERROR_MORE_DATA); ErrorIf(0 != memcmp(tmp1, data, 5), ERROR_BAD_FORMAT); offset += count; // Status-Code[.Sub-Status-Code] SP statusCode = 0; while (offset < dataSize && data[offset] >= '0' && data[offset] <= '9') { statusCode = statusCode * 10 + data[offset++] - '0'; } ErrorIf(offset == dataSize, ERROR_MORE_DATA); if ('.' == data[offset]) { // Sub-Status-Code offset++; while (offset < dataSize && data[offset] >= '0' && data[offset] <= '9') { subStatusCode = subStatusCode * 10 + data[offset++] - '0'; } ErrorIf(offset == dataSize, ERROR_MORE_DATA); } ErrorIf(' ' != data[offset], ERROR_BAD_FORMAT); offset++; // Determine whether to expect response entity body // http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.4 if (statusCode >= 100 && statusCode < 200 || statusCode == 204 || statusCode == 304) { context->SetExpectResponseBody(FALSE); } // Reason-Phrase CRLF newOffset = offset; while (newOffset < (dataSize - 1) && data[newOffset] != 0x0D) { newOffset++; } ErrorIf(newOffset == dataSize - 1, ERROR_MORE_DATA); ErrorIf(0x0A != data[newOffset + 1], ERROR_BAD_FORMAT); // set HTTP response status line data[newOffset] = 0; // zero-terminate the reason phrase to reuse it without copying IHttpResponse* response = context->GetHttpContext()->GetResponse(); response->Clear(); response->SetStatus(statusCode, data + offset, subStatusCode); // adjust buffers context->SetParsingOffset(context->GetParsingOffset() + newOffset + 2); return S_OK; Error: if (ERROR_MORE_DATA != hr) { context->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log( L"iisnode failed to parse response status line", WINEVENT_LEVEL_ERROR, context->GetActivityId()); } return hr; }