Skip to content

Commit

Permalink
fix #128: graceful failure on configuration errors
Browse files Browse the repository at this point in the history
  • Loading branch information
tjanczuk committed Jan 4, 2012
1 parent 9335de0 commit cc77a36
Show file tree
Hide file tree
Showing 10 changed files with 115 additions and 8 deletions.
5 changes: 3 additions & 2 deletions src/iisnode/cmoduleconfiguration.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ class CModuleConfiguration : public IHttpStoredContext
static HRESULT GetConfigSection(IHttpContext* context, IAppHostElement** section, OLECHAR* configElement = L"system.webServer/iisnode");
static HRESULT GetString(IAppHostElement* section, LPCWSTR propertyName, LPWSTR* value);
static HRESULT GetBOOL(IAppHostElement* section, LPCWSTR propertyName, BOOL* value);
static HRESULT GetDWORD(IAppHostElement* section, LPCWSTR propertyName, DWORD* value);
static HRESULT GetConfig(IHttpContext* context, CModuleConfiguration** config);
static HRESULT GetDWORD(IAppHostElement* section, LPCWSTR propertyName, DWORD* value);

CModuleConfiguration();
~CModuleConfiguration();
Expand All @@ -47,6 +46,8 @@ class CModuleConfiguration : public IHttpStoredContext

static HRESULT Initialize(IHttpServer* server, HTTP_MODULE_ID moduleId);

static HRESULT GetConfig(IHttpContext* context, CModuleConfiguration** config);

static DWORD GetAsyncCompletionThreadCount(IHttpContext* ctx);
static DWORD GetNodeProcessCountPerApplication(IHttpContext* ctx);
static LPCTSTR GetNodeProcessCommandLine(IHttpContext* ctx);
Expand Down
20 changes: 14 additions & 6 deletions src/iisnode/cnodeapplicationmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,25 @@ CNodeApplicationManager::CNodeApplicationManager(IHttpServer* server, HTTP_MODUL
HRESULT CNodeApplicationManager::Initialize(IHttpContext* context)
{
HRESULT hr = S_OK;
CModuleConfiguration *config;

if (!this->initialized)
{
ENTER_SRW_EXCLUSIVE(this->srwlock)
if (S_OK != CModuleConfiguration::GetConfig(context, &config))
{
hr = IISNODE_ERROR_UNABLE_TO_READ_CONFIGURATION;
}
else
{
ENTER_SRW_EXCLUSIVE(this->srwlock)

if (!this->initialized)
{
hr = this->InitializeCore(context);
}
if (!this->initialized)
{
hr = this->InitializeCore(context);
}

LEAVE_SRW_EXCLUSIVE(this->srwlock)
LEAVE_SRW_EXCLUSIVE(this->srwlock)
}
}

return hr;
Expand Down
56 changes: 56 additions & 0 deletions src/iisnode/cprotocolbridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,64 @@ HRESULT CProtocolBridge::PostponeProcessing(CNodeHttpStoredContext* context, DWO
return async->SetTimer(context->GetAsyncContext(), &delay);
}

#define LOCAL127 0x0100007F // 127.0.0.1

BOOL CProtocolBridge::IsLocalCall(IHttpContext* ctx)
{
PSOCKADDR src = ctx->GetRequest()->GetRemoteAddress();
PSOCKADDR dest = ctx->GetRequest()->GetLocalAddress();

if (AF_INET == src->sa_family && AF_INET == dest->sa_family)
{
DWORD srcAddress = ntohl(((PSOCKADDR_IN)src)->sin_addr.s_addr);
DWORD destAddress = ntohl(((PSOCKADDR_IN)dest)->sin_addr.s_addr);

return srcAddress == destAddress || LOCAL127 == srcAddress || LOCAL127 == destAddress;
}
else if (AF_INET6 == src->sa_family && AF_INET6 == dest->sa_family)
{
IN6_ADDR* srcAddress = &((PSOCKADDR_IN6)src)->sin6_addr;
IN6_ADDR* destAddress = &((PSOCKADDR_IN6)dest)->sin6_addr;

if (0 == memcmp(srcAddress, destAddress, sizeof IN6_ADDR))
{
return TRUE;
}

if (IN6_IS_ADDR_LOOPBACK(srcAddress) || IN6_IS_ADDR_LOOPBACK(destAddress))
{
return TRUE;
}
}

return FALSE;
}

BOOL CProtocolBridge::SendIisnodeError(IHttpContext* httpCtx, HRESULT hr)
{
if (IISNODE_ERROR_UNABLE_TO_READ_CONFIGURATION == hr)
{
if (CProtocolBridge::IsLocalCall(httpCtx))
{
CProtocolBridge::SendSyncResponse(
httpCtx,
200,
"OK",
hr,
TRUE,
"iisnode was unable to read the configuration file. Make sure the web.config file syntax is correct. In particular, verify the "
" <a href=""https://github.com/tjanczuk/iisnode/blob/master/src/samples/configuration/web.config"">"
"iisnode configuration section</a> matches the expected schema. The schema of the iisnode section that your version of iisnode requiries is stored in the "
"%systemroot%\\system32\\inetsrv\\config\\schema\\iisnode_schema.xml file.");

return TRUE;
}
else
{
return FALSE;
}
}

if (!CModuleConfiguration::GetDevErrorsEnabled(httpCtx))
{
return FALSE;
Expand Down
1 change: 1 addition & 0 deletions src/iisnode/cprotocolbridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class CProtocolBridge
static HRESULT PostponeProcessing(CNodeHttpStoredContext* context, DWORD dueTime);
static HRESULT EnsureBuffer(CNodeHttpStoredContext* context);
static HRESULT FinalizeResponseCore(CNodeHttpStoredContext * context, REQUEST_NOTIFICATION_STATUS status, HRESULT error, CNodeEventProvider* log, PCWSTR etw, UCHAR level);
static BOOL IsLocalCall(IHttpContext* ctx);

// processing stages
static void WINAPI ChildContextCompleted(DWORD error, DWORD bytesTransfered, LPOVERLAPPED overlapped);
Expand Down
1 change: 1 addition & 0 deletions src/iisnode/errors.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@
#define IISNODE_ERROR_UNABLE_TO_START_NODE_EXE 1028L
#define IISNODE_ERROR_UNABLE_TO_CREATE_LOG_FILE 1029L
#define IISNODE_ERROR_UNABLE_TO_CREATE_DEBUGGER_FILES 1030L
#define IISNODE_ERROR_UNABLE_TO_READ_CONFIGURATION 1031L

#endif
3 changes: 3 additions & 0 deletions src/iisnode/iisnode.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ copy /y $(ProjectDir)\..\config\* $(ProjectDir)\..\..\build\$(Configuration)\$(P
<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\116_configerror.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 @@ -288,6 +289,8 @@ copy /y $(ProjectDir)\..\config\* $(ProjectDir)\..\..\build\$(Configuration)\$(P
<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\functional\www\116_configerror\hello.js" />
<None Include="..\..\test\functional\www\116_configerror\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 @@ -114,6 +114,9 @@
<Filter Include="Tests\functional\www\115_customheaders">
<UniqueIdentifier>{994959e7-12c0-43f7-a10b-24899813a857}</UniqueIdentifier>
</Filter>
<Filter Include="Tests\functional\www\116_configerror">
<UniqueIdentifier>{500f40cf-c2f5-4264-b061-b4f1e59f50f5}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp">
Expand Down Expand Up @@ -492,6 +495,15 @@
<None Include="..\..\test\functional\www\115_customheaders\web.config">
<Filter>Tests\functional\www\115_customheaders</Filter>
</None>
<None Include="..\..\test\functional\tests\116_configerror.js">
<Filter>Tests\functional\tests</Filter>
</None>
<None Include="..\..\test\functional\www\116_configerror\hello.js">
<Filter>Tests\functional\www\116_configerror</Filter>
</None>
<None Include="..\..\test\functional\www\116_configerror\web.config">
<Filter>Tests\functional\www\116_configerror</Filter>
</None>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="iisnode.rc" />
Expand Down
9 changes: 9 additions & 0 deletions test/functional/tests/116_configerror.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*
Local request to iisnode with a configuration syntax error returns a friendly 200 response
*/

var iisnodeassert = require("iisnodeassert");

iisnodeassert.sequence([
iisnodeassert.get(10000, "/116_configerror/hello.js", 200)
]);
6 changes: 6 additions & 0 deletions test/functional/www/116_configerror/hello.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
var http = require('http');

http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.end('Hello, world!');
}).listen(process.env.PORT);
10 changes: 10 additions & 0 deletions test/functional/www/116_configerror/web.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<configuration>
<system.webServer>
<handlers>
<add name="iisnode" path="hello.js" verb="*" modules="iisnode" />
</handlers>

<iisnode idontexist="12" />

</system.webServer>
</configuration>

0 comments on commit cc77a36

Please sign in to comment.