Skip to content

Commit

Permalink
fix #109: enable http 1.0 requests
Browse files Browse the repository at this point in the history
  • Loading branch information
tjanczuk committed Jan 4, 2012
1 parent 179e0cb commit 9335de0
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 23 deletions.
6 changes: 5 additions & 1 deletion src/iisnode/chttpprotocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ HRESULT CHttpProtocol::ParseResponseStatusLine(CNodeHttpStoredContext* context)
}

ErrorIf(count >= dataSize, ERROR_MORE_DATA);
ErrorIf(0 != memcmp(tmp1, data, count), ERROR_BAD_FORMAT);
ErrorIf(0 != memcmp(tmp1, data, 5), ERROR_BAD_FORMAT);
offset += count;

// Status-Code[.Sub-Status-Code] SP
Expand Down Expand Up @@ -449,6 +449,10 @@ HRESULT CHttpProtocol::ParseResponseHeaders(CNodeHttpStoredContext* context)

CheckError(response->SetHeader(data + offset, data + nameEndOffset, valueEndOffset - nameEndOffset, TRUE));
}
else if ((valueEndOffset - nameEndOffset) >= 5 && 0 == memcmp((void*)(data + valueEndOffset - 5), "close", 5))
{
context->SetCloseConnection(TRUE);
}

// adjust offsets

Expand Down
13 changes: 12 additions & 1 deletion src/iisnode/cnodehttpstoredcontext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ CNodeHttpStoredContext::CNodeHttpStoredContext(CNodeApplication* nodeApplication
: nodeApplication(nodeApplication), context(context), process(NULL), buffer(NULL), bufferSize(0), dataSize(0), parsingOffset(0),
chunkLength(0), chunkTransmitted(0), isChunked(FALSE), pipe(INVALID_HANDLE_VALUE), result(S_OK), isLastChunk(FALSE),
requestNotificationStatus(RQ_NOTIFICATION_PENDING), connectionRetryCount(0), pendingAsyncOperationCount(1),
targetUrl(NULL), targetUrlLength(0), childContext(NULL), isConnectionFromPool(FALSE), expectResponseBody(TRUE)
targetUrl(NULL), targetUrlLength(0), childContext(NULL), isConnectionFromPool(FALSE), expectResponseBody(TRUE),
closeConnection(FALSE)
{
IHttpTraceContext* tctx;
LPCGUID pguid;
Expand Down Expand Up @@ -273,3 +274,13 @@ BOOL CNodeHttpStoredContext::GetExpectResponseBody()
{
return this->expectResponseBody;
}

void CNodeHttpStoredContext::SetCloseConnection(BOOL close)
{
this->closeConnection = close;
}

BOOL CNodeHttpStoredContext::GetCloseConnection()
{
return this->closeConnection;
}
3 changes: 3 additions & 0 deletions src/iisnode/cnodehttpstoredcontext.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class CNodeHttpStoredContext : public IHttpStoredContext
BOOL isLastChunk;
BOOL isConnectionFromPool;
BOOL expectResponseBody;
BOOL closeConnection;

public:

Expand Down Expand Up @@ -85,6 +86,8 @@ class CNodeHttpStoredContext : public IHttpStoredContext
void SetIsConnectionFromPool(BOOL fromPool);
void SetExpectResponseBody(BOOL expect);
BOOL GetExpectResponseBody();
void SetCloseConnection(BOOL close);
BOOL GetCloseConnection();

static CNodeHttpStoredContext* Get(LPOVERLAPPED overlapped);

Expand Down
75 changes: 54 additions & 21 deletions src/iisnode/cprotocolbridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -794,6 +794,12 @@ void CProtocolBridge::ContinueReadResponse(CNodeHttpStoredContext* context)
WINEVENT_LEVEL_VERBOSE,
&activityId);
}
else if (ERROR_BROKEN_PIPE == hr && context->GetCloseConnection())
{
// Termination of a connection indicates the end of the response body if Connection: close response header was present

CProtocolBridge::FinalizeResponse(context);
}
else
{
// error
Expand Down Expand Up @@ -874,28 +880,38 @@ void WINAPI CProtocolBridge::ProcessResponseHeaders(DWORD error, DWORD bytesTran
}
else
{
contentLength = ctx->GetHttpContext()->GetResponse()->GetHeader(HttpHeaderContentLength, &contentLengthLength);
if (0 == contentLengthLength)
if (ctx->GetCloseConnection())
{
ctx->SetIsChunked(TRUE);
ctx->SetNextProcessor(CProtocolBridge::ProcessChunkHeader);
ctx->SetIsChunked(FALSE);
ctx->SetChunkLength(MAXLONGLONG);
ctx->SetIsLastChunk(TRUE);
ctx->SetNextProcessor(CProtocolBridge::ProcessResponseBody);
}
else
else
{
LONGLONG length = 0;
int i = 0;
contentLength = ctx->GetHttpContext()->GetResponse()->GetHeader(HttpHeaderContentLength, &contentLengthLength);
if (0 == contentLengthLength)
{
ctx->SetIsChunked(TRUE);
ctx->SetNextProcessor(CProtocolBridge::ProcessChunkHeader);
}
else
{
LONGLONG length = 0;
int i = 0;

// skip leading white space
while (i < contentLengthLength && (contentLength[i] < '0' || contentLength[i] > '9'))
i++;
// skip leading white space
while (i < contentLengthLength && (contentLength[i] < '0' || contentLength[i] > '9'))
i++;

while (i < contentLengthLength && contentLength[i] >= '0' && contentLength[i] <= '9')
length = length * 10 + contentLength[i++] - '0';
while (i < contentLengthLength && contentLength[i] >= '0' && contentLength[i] <= '9')
length = length * 10 + contentLength[i++] - '0';

ctx->SetIsChunked(FALSE);
ctx->SetIsLastChunk(TRUE);
ctx->SetChunkLength(length);
ctx->SetNextProcessor(CProtocolBridge::ProcessResponseBody);
ctx->SetIsChunked(FALSE);
ctx->SetIsLastChunk(TRUE);
ctx->SetChunkLength(length);
ctx->SetNextProcessor(CProtocolBridge::ProcessResponseBody);
}
}

ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
Expand Down Expand Up @@ -1009,7 +1025,7 @@ void WINAPI CProtocolBridge::ProcessResponseBody(DWORD error, DWORD bytesTransfe
chunk,
1,
TRUE,
!ctx->GetIsLastChunk(),
!ctx->GetIsLastChunk() || remainingChunkSize > bytesToSend,
&bytesSent,
&completionExpected));

Expand Down Expand Up @@ -1051,9 +1067,18 @@ void WINAPI CProtocolBridge::ProcessResponseBody(DWORD error, DWORD bytesTransfe
return;
Error:

ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
L"iisnode failed to send http response body chunk", WINEVENT_LEVEL_ERROR, ctx->GetActivityId());
CProtocolBridge::SendEmptyResponse(ctx, 500, _T("Internal Server Error"), hr);
if (ERROR_BROKEN_PIPE == hr && ctx->GetCloseConnection())
{
// Termination of a connection indicates the end of the response body if Connection: close response header was present

CProtocolBridge::FinalizeResponse(ctx);
}
else
{
ctx->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
L"iisnode failed to send http response body chunk", WINEVENT_LEVEL_ERROR, ctx->GetActivityId());
CProtocolBridge::SendEmptyResponse(ctx, 500, _T("Internal Server Error"), hr);
}

return;
}
Expand Down Expand Up @@ -1124,7 +1149,15 @@ void CProtocolBridge::FinalizeResponse(CNodeHttpStoredContext* context)
context->GetNodeApplication()->GetApplicationManager()->GetEventProvider()->Log(
L"iisnode finished processing http request/response", WINEVENT_LEVEL_VERBOSE, context->GetActivityId());

context->GetNodeProcess()->GetConnectionPool()->Return(context->GetPipe());
if (context->GetCloseConnection())
{
CloseHandle(context->GetPipe());
}
else
{
context->GetNodeProcess()->GetConnectionPool()->Return(context->GetPipe());
}

context->SetPipe(INVALID_HANDLE_VALUE);
CProtocolBridge::FinalizeResponseCore(
context,
Expand Down
3 changes: 3 additions & 0 deletions src/iisnode/iisnode.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ copy /y $(ProjectDir)\..\config\* $(ProjectDir)\..\..\build\$(Configuration)\$(P
<None Include="..\..\test\functional\tests\111_node_env.js" />
<None Include="..\..\test\functional\tests\112_dev_errors.js" />
<None Include="..\..\test\functional\tests\113_encoding.js" />
<None Include="..\..\test\functional\tests\115_customheaders.js" />
<None Include="..\..\test\functional\tests\200_samples.bat" />
<None Include="..\..\test\functional\tests\node_modules\iisnodeassert.js" />
<None Include="..\..\test\functional\tests\parts\106_autoupdate_first.js" />
Expand Down Expand Up @@ -285,6 +286,8 @@ copy /y $(ProjectDir)\..\config\* $(ProjectDir)\..\..\build\$(Configuration)\$(P
<None Include="..\..\test\functional\www\112_dev_errors\on\web.config" />
<None Include="..\..\test\functional\www\113_encoding\hello.js" />
<None Include="..\..\test\functional\www\113_encoding\web.config" />
<None Include="..\..\test\functional\www\115_customheaders\hello.js" />
<None Include="..\..\test\functional\www\115_customheaders\web.config" />
<None Include="..\..\test\performance\client.bat" />
<None Include="..\..\test\performance\localRun.bat" />
<None Include="..\..\test\performance\readme.txt" />
Expand Down
12 changes: 12 additions & 0 deletions src/iisnode/iisnode.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@
<Filter Include="Tests\functional\www\113_encoding">
<UniqueIdentifier>{5e0f95ef-1256-4223-a412-f5146a7713cc}</UniqueIdentifier>
</Filter>
<Filter Include="Tests\functional\www\115_customheaders">
<UniqueIdentifier>{994959e7-12c0-43f7-a10b-24899813a857}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp">
Expand Down Expand Up @@ -480,6 +483,15 @@
<None Include="..\..\test\functional\tests\113_encoding.js">
<Filter>Tests\functional\tests</Filter>
</None>
<None Include="..\..\test\functional\tests\115_customheaders.js">
<Filter>Tests\functional\tests</Filter>
</None>
<None Include="..\..\test\functional\www\115_customheaders\hello.js">
<Filter>Tests\functional\www\115_customheaders</Filter>
</None>
<None Include="..\..\test\functional\www\115_customheaders\web.config">
<Filter>Tests\functional\www\115_customheaders</Filter>
</None>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="iisnode.rc" />
Expand Down
2 changes: 2 additions & 0 deletions test/functional/tests/106_autoupdate.bat
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ if %ERRORLEVEL% neq 0 del /q %www%\106_autoupdate\hello.js & exit /b -1
copy /y %www%\106_autoupdate\hello_second.js %www%\106_autoupdate\hello.js
if %ERRORLEVEL% neq 0 del /q %www%\106_autoupdate\hello.js & exit /b -1

timeout /T 5 /NOBREAK

call %this%scripts\runNodeTest.bat parts\106_autoupdate_second.js
if %ERRORLEVEL% neq 0 del /q %www%\106_autoupdate\hello.js & exit /b -1

Expand Down

0 comments on commit 9335de0

Please sign in to comment.