From f85f64ebd08ab7f97c1f9e20f12648974127abfd Mon Sep 17 00:00:00 2001 From: Michael Parque Date: Thu, 6 Apr 2017 08:41:27 -0400 Subject: [PATCH 1/3] Add skipIISCustomErrors switch to iisnode IHTTPResponse::SetStatus needs to be called with fTrySkipCustomErrors flag set in order for iisnode to bypass IIS custom errors when errorMode="Auto" Add opt-in skipIISCustomErrors switch to iisnode configuration. Users can opt into the fTrySkipCustomErrors flag behavior with skipIISCustomErrors="true". If this option is not specified, then the default behavior will match the previous behavior before this change. skipIISCustomErrors behavior was left out of SendEmptyResponse Internal iisnode errors should probably not set fTrySkipCustomErrors since these are just empty status responses. Let IIS capture and replace these responses with more detailed messages depending on the custom error mode. --- src/config/iisnode_dev_x64.xml | 1 + src/config/iisnode_dev_x86_on_x64.xml | 1 + src/config/iisnode_dev_x86_on_x86.xml | 1 + src/config/iisnode_express_schema.xml | 1 + src/config/iisnode_express_schema_x64.xml | 1 + src/config/iisnode_schema.xml | 1 + src/config/iisnode_schema_x64.xml | 1 + src/iisnode/chttpprotocol.cpp | 15 ++++++++++++++- src/iisnode/cmoduleconfiguration.cpp | 10 ++++++++++ src/iisnode/cmoduleconfiguration.h | 2 ++ src/iisnode/cprotocolbridge.cpp | 6 +++++- src/samples/configuration/iisnode.yml | 5 ++++- src/samples/configuration/readme.htm | 9 ++++++++- src/samples/configuration/web.config | 3 +++ 14 files changed, 53 insertions(+), 4 deletions(-) diff --git a/src/config/iisnode_dev_x64.xml b/src/config/iisnode_dev_x64.xml index cab240cf..a8625d4e 100644 --- a/src/config/iisnode_dev_x64.xml +++ b/src/config/iisnode_dev_x64.xml @@ -60,5 +60,6 @@ Details at http://learn.iis.net/page.aspx/241/configuration-extensibility/ + diff --git a/src/config/iisnode_dev_x86_on_x64.xml b/src/config/iisnode_dev_x86_on_x64.xml index aaa0bbc9..44ea9126 100644 --- a/src/config/iisnode_dev_x86_on_x64.xml +++ b/src/config/iisnode_dev_x86_on_x64.xml @@ -60,5 +60,6 @@ Details at http://learn.iis.net/page.aspx/241/configuration-extensibility/ + diff --git a/src/config/iisnode_dev_x86_on_x86.xml b/src/config/iisnode_dev_x86_on_x86.xml index 9606a25e..2e6f5e82 100644 --- a/src/config/iisnode_dev_x86_on_x86.xml +++ b/src/config/iisnode_dev_x86_on_x86.xml @@ -60,5 +60,6 @@ Details at http://learn.iis.net/page.aspx/241/configuration-extensibility/ + diff --git a/src/config/iisnode_express_schema.xml b/src/config/iisnode_express_schema.xml index 2ad9eddc..d26f65dc 100644 --- a/src/config/iisnode_express_schema.xml +++ b/src/config/iisnode_express_schema.xml @@ -60,5 +60,6 @@ Details at http://learn.iis.net/page.aspx/241/configuration-extensibility/ + diff --git a/src/config/iisnode_express_schema_x64.xml b/src/config/iisnode_express_schema_x64.xml index ddf6368a..b53f0570 100644 --- a/src/config/iisnode_express_schema_x64.xml +++ b/src/config/iisnode_express_schema_x64.xml @@ -60,5 +60,6 @@ Details at http://learn.iis.net/page.aspx/241/configuration-extensibility/ + diff --git a/src/config/iisnode_schema.xml b/src/config/iisnode_schema.xml index 4088c009..836e0388 100644 --- a/src/config/iisnode_schema.xml +++ b/src/config/iisnode_schema.xml @@ -60,5 +60,6 @@ Details at http://learn.iis.net/page.aspx/241/configuration-extensibility/ + diff --git a/src/config/iisnode_schema_x64.xml b/src/config/iisnode_schema_x64.xml index 8d454eae..d4251f30 100644 --- a/src/config/iisnode_schema_x64.xml +++ b/src/config/iisnode_schema_x64.xml @@ -60,5 +60,6 @@ Details at http://learn.iis.net/page.aspx/241/configuration-extensibility/ + " diff --git a/src/iisnode/chttpprotocol.cpp b/src/iisnode/chttpprotocol.cpp index 4e70f92c..22e67c18 100644 --- a/src/iisnode/chttpprotocol.cpp +++ b/src/iisnode/chttpprotocol.cpp @@ -364,7 +364,20 @@ HRESULT CHttpProtocol::ParseResponseStatusLine(CNodeHttpStoredContext* context) data[newOffset] = 0; // zero-terminate the reason phrase to reuse it without copying IHttpResponse* response = context->GetHttpContext()->GetResponse(); - response->SetStatus(statusCode, data + offset, subStatusCode); + + if (CModuleConfiguration::GetSkipIISCustomErrors(context->GetHttpContext())) + { + // set fTrySkipCustomErrors so that error responses sent back from the node app through iisnode + // are passed through to the client instead of being intercepted by IIS when httpErrors existingResponse="Auto" + // this allows a mixed solution where custom error pages can be provided via IIS for errors that occur outside + // of iisnode's purview, while also allowing usually-more-helpful error responses from the node application + // to be passed through to the client rather than being intercepted by IIS. + response->SetStatus(statusCode, data + offset, subStatusCode, S_OK, NULL, TRUE); + } + else + { + response->SetStatus(statusCode, data + offset, subStatusCode); + } // adjust buffers diff --git a/src/iisnode/cmoduleconfiguration.cpp b/src/iisnode/cmoduleconfiguration.cpp index 46c0f538..c1315363 100644 --- a/src/iisnode/cmoduleconfiguration.cpp +++ b/src/iisnode/cmoduleconfiguration.cpp @@ -888,6 +888,10 @@ HRESULT CModuleConfiguration::ApplyConfigOverrideKeyValue(IHttpContext* context, { CheckError(GetDWORD(valueStart, &config->idlePageOutTimePeriod)); } + else if(0 == stricmp(keyStart, "skipIISCustomErrors")) + { + CheckError(GetBOOL(valueStart, &config->skipIISCustomErrors)); + } return S_OK; Error: @@ -1247,6 +1251,7 @@ HRESULT CModuleConfiguration::GetConfig(IHttpContext* context, CModuleConfigurat CheckError(GetString(section, L"nodeProcessCommandLine", &c->nodeProcessCommandLine)); CheckError(GetString(section, L"interceptor", &c->interceptor)); CheckError(GetDWORD(section, L"idlePageOutTimePeriod", &c->idlePageOutTimePeriod)); + CheckError(GetBOOL(section, L"skipIISCustomErrors", &c->skipIISCustomErrors, FALSE)); // debuggerPathSegment @@ -1488,6 +1493,11 @@ LPWSTR CModuleConfiguration::GetConfigOverrides(IHttpContext* ctx) GETCONFIG(configOverrides) } +BOOL CModuleConfiguration::GetSkipIISCustomErrors(IHttpContext* ctx) +{ + GETCONFIG(skipIISCustomErrors) +} + HRESULT CModuleConfiguration::GenerateDebuggerConfig(IHttpContext* context, CModuleConfiguration *config) { HRESULT hr = S_OK; diff --git a/src/iisnode/cmoduleconfiguration.h b/src/iisnode/cmoduleconfiguration.h index c951fca3..bf4615c9 100644 --- a/src/iisnode/cmoduleconfiguration.h +++ b/src/iisnode/cmoduleconfiguration.h @@ -52,6 +52,7 @@ class CModuleConfiguration : public IHttpStoredContext static BOOL invalid; SRWLOCK srwlock; LPWSTR configOverrides; + BOOL skipIISCustomErrors; static IHttpServer* server; static HTTP_MODULE_ID moduleId; @@ -129,6 +130,7 @@ class CModuleConfiguration : public IHttpStoredContext static BOOL GetEnableXFF(IHttpContext* ctx); static HRESULT GetPromoteServerVars(IHttpContext* ctx, char*** vars, int* count); static LPWSTR GetConfigOverrides(IHttpContext* ctx); + static BOOL GetSkipIISCustomErrors(IHttpContext* ctx); static HRESULT CreateNodeEnvironment(IHttpContext* ctx, DWORD debugPort, PCH namedPipe, PCH signalPipeName, PCH* env); diff --git a/src/iisnode/cprotocolbridge.cpp b/src/iisnode/cprotocolbridge.cpp index 726758ff..ba3c381a 100644 --- a/src/iisnode/cprotocolbridge.cpp +++ b/src/iisnode/cprotocolbridge.cpp @@ -459,7 +459,11 @@ void CProtocolBridge::SendEmptyResponse(IHttpContext* httpCtx, USHORT status, US if (!httpCtx->GetResponseHeadersSent()) { httpCtx->GetResponse()->Clear(); - httpCtx->GetResponse()->SetStatus(status, reason, subStatus, hresult); + + // Internal iisnode errors should probably not set fTrySkipCustomErrors since these are just empty status responses. + // Let IIS capture and replace these responses with more detailed messages depending on the custom error mode. + httpCtx->GetResponse()->SetStatus(status, reason, subStatus, hresult); + if (disableCache) { httpCtx->GetResponse()->SetHeader(HttpHeaderCacheControl, "no-cache", 8, TRUE); diff --git a/src/samples/configuration/iisnode.yml b/src/samples/configuration/iisnode.yml index 415b0bf9..76e1be42 100644 --- a/src/samples/configuration/iisnode.yml +++ b/src/samples/configuration/iisnode.yml @@ -141,4 +141,7 @@ enableXFF: false # HTTP request headers; for a list of IIS server variables available see # http://msdn.microsoft.com/en-us/library/ms524602(v=vs.90).aspx; for example "AUTH_USER,AUTH_TYPE" -promoteServerVars: \ No newline at end of file +promoteServerVars: + +# skipIISCustomErrors - controls whether iisnode will try to skip IIS custom error handling when existingResponse="Auto" +skipIISCustomErrors: false \ No newline at end of file diff --git a/src/samples/configuration/readme.htm b/src/samples/configuration/readme.htm index 7dacba7b..1408ec6e 100644 --- a/src/samples/configuration/readme.htm +++ b/src/samples/configuration/readme.htm @@ -145,6 +145,8 @@

maxRequestBufferSize: 8192 # increasing from the default # maxConcurrentRequestsPerProcess: 512 - commented out setting + * skipIISCustomErrors - controls whether iisnode will try to skip IIS >httpErrors< custom error handling when existingResponse="Auto" + --> <iisnode @@ -175,6 +177,7 @@

enableXFF="false" promoteServerVars="" configOverrides="node.conf" + skipIISCustomErrors="false" /> <!-- @@ -335,6 +338,10 @@

# HTTP request headers; for a list of IIS server variables available see # http://msdn.microsoft.com/en-us/library/ms524602(v=vs.90).aspx; for example "AUTH_USER,AUTH_TYPE" -promoteServerVars: +promoteServerVars: + +# skipIISCustomErrors - controls whether iisnode will try to skip IIS >httpErrors< custom error handling when existingResponse="Auto" +skipIISCustomErrors: false + diff --git a/src/samples/configuration/web.config b/src/samples/configuration/web.config index fed9441e..51fb003a 100644 --- a/src/samples/configuration/web.config +++ b/src/samples/configuration/web.config @@ -109,6 +109,8 @@ nodeProcessCountPerApplication: 2 maxRequestBufferSize: 8192 # increasing from the default # maxConcurrentRequestsPerProcess: 512 - commented out setting + + * skipIISCustomErrors - controls whether iisnode will try to skip IIS custom error handling when existingResponse="Auto" --> @@ -140,6 +142,7 @@ enableXFF="false" promoteServerVars="" configOverrides="iisnode.yml" + skipIISCustomErrors="false" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/functional/www/web.config b/test/functional/www/web.config new file mode 100644 index 00000000..c6dc3d57 --- /dev/null +++ b/test/functional/www/web.config @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + From 7314273871ae02d2b3abd08e3236a86c7528e25d Mon Sep 17 00:00:00 2001 From: Michael Parque Date: Wed, 3 May 2017 15:51:35 -0400 Subject: [PATCH 3/3] Remove accidentally-added web.config from www/ folder --- test/functional/www/web.config | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 test/functional/www/web.config diff --git a/test/functional/www/web.config b/test/functional/www/web.config deleted file mode 100644 index c6dc3d57..00000000 --- a/test/functional/www/web.config +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - -