From 7a09638afee198b5a87761ff33999aa72060340b Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Tue, 9 Oct 2018 16:12:01 -0700 Subject: [PATCH] Modernize startup error pages (#1476) --- .../AspNetCore/InProcessShimStaticHtml.htm | 121 ++++++++++++------ .../AspNetCore/OutOfProcessShimStaticHtml.htm | 119 +++++++++++------ .../AspNetCore/ServerErrorApplication.h | 3 +- .../CommonLib/ServerErrorHandler.h | 73 ++++++++++- .../CommonLib/file_utility.cpp | 20 --- .../CommonLib/requesthandler.h | 26 ---- .../InProcessRhStaticHtml.htm | 115 +++++++++++------ .../StartupExceptionApplication.h | 5 +- .../HtmlResponses.rc | 68 ++++++++++ .../OutOfProcessRequestHandler.vcxproj | 5 + .../OutOfProcessRhStaticHtml.htm | 85 ++++++++++++ .../OutOfProcessRequestHandler/dllmain.cpp | 2 + .../forwardinghandler.cpp | 44 +------ .../forwardinghandler.h | 1 + .../OutOfProcessRequestHandler/resource.h | 16 +++ .../InProcess/ErrorPagesTests.cs | 106 +++++++++++++++ .../InProcess/StartupTests.cs | 4 +- .../OutOfProcess/GlobalVersionTests.cs | 2 +- 18 files changed, 598 insertions(+), 217 deletions(-) create mode 100644 src/AspNetCoreModuleV2/OutOfProcessRequestHandler/HtmlResponses.rc create mode 100644 src/AspNetCoreModuleV2/OutOfProcessRequestHandler/OutOfProcessRhStaticHtml.htm create mode 100644 src/AspNetCoreModuleV2/OutOfProcessRequestHandler/resource.h create mode 100644 test/IISExpress.FunctionalTests/InProcess/ErrorPagesTests.cs diff --git a/src/AspNetCoreModuleV2/AspNetCore/InProcessShimStaticHtml.htm b/src/AspNetCoreModuleV2/AspNetCore/InProcessShimStaticHtml.htm index b7e575552a..a8c9d7fe1f 100644 --- a/src/AspNetCoreModuleV2/AspNetCore/InProcessShimStaticHtml.htm +++ b/src/AspNetCoreModuleV2/AspNetCore/InProcessShimStaticHtml.htm @@ -1,45 +1,84 @@ - - + + + + + HTTP Error 500.0 - ANCM In-Process Handler Load Failure + - + h1, h2, h3, h4, h5 { + /*font-family: 'Segoe UI',Tahoma,Arial,Helvetica,sans-serif;*/ + font-weight: 100; + } - -
-
-

HTTP Error 500.0 - ANCM InProcess Startup Failure

-
-
-
-

Common causes of this issue:

-
    -
  • The specified version of Microsoft.NetCore.App or Microsoft.AspNetCore.App was not found.
  • -
  • The in process request handler, Microsoft.AspNetCore.Server.IIS, was not referenced in the application.
  • -
  • ANCM could not find dotnet.
  • -
-
-
-
-
-

Troubleshooting steps:

-
    -
  • Check the system event log for error messages
  • -
  • Enable logging the application process' stdout messages
  • -
  • Attach a debugger to the application process and inspect
  • -
-
-
-

For more information visit: - - https://go.microsoft.com/fwlink/?LinkID=808681 - -

-
-
-
- + h1 { + color: #44525e; + margin: 15px 0 15px 0; + } + h2 { + margin: 10px 5px 0 0; + } + + h3 { + color: #363636; + margin: 5px 5px 0 0; + } + + code { + font-family: Consolas, "Courier New", courier, monospace; + } + + body .titleerror { + padding: 3px 3px 6px 3px; + display: block; + font-size: 1.5em; + font-weight: 100; + } + + a { + color: #1ba1e2; + text-decoration: none; + } + + a:hover { + color: #13709e; + text-decoration: underline; + } + + li { + margin: 5px; + } + + + + +

HTTP Error 500.0 - ANCM In-Process Handler Load Failure

+ +

Common causes of this issue:

+ + + +

Troubleshooting steps:

+ + + +

+ For more information visit: + %s https://go.microsoft.com/fwlink/?LinkID=2028526 +

+ diff --git a/src/AspNetCoreModuleV2/AspNetCore/OutOfProcessShimStaticHtml.htm b/src/AspNetCoreModuleV2/AspNetCore/OutOfProcessShimStaticHtml.htm index 475ce26956..1194cf4025 100644 --- a/src/AspNetCoreModuleV2/AspNetCore/OutOfProcessShimStaticHtml.htm +++ b/src/AspNetCoreModuleV2/AspNetCore/OutOfProcessShimStaticHtml.htm @@ -1,44 +1,81 @@ - - + + + + + HTTP Error 500.0 - ANCM Out-Of-Process Handler Load Failure + - + h1, h2, h3, h4, h5 { + /*font-family: 'Segoe UI',Tahoma,Arial,Helvetica,sans-serif;*/ + font-weight: 100; + } - -
-
-

HTTP Error 500.0 - ANCM OutOfProcess Startup Failure

-
-
-
-

Common causes of this issue:

-
    -
  • The out of process request handler, aspnetcorev2_outofprocess.dll, could not be found next to the aspnetcorev2.dll.
  • -
  • Could not read configuration correctly. Check the application's associated web.config.
  • -
-
-
-
-
-

Troubleshooting steps:

-
    -
  • Check the system event log for error messages
  • -
  • Enable logging the application process' stdout messages
  • -
  • Attach a debugger to the application process and inspect
  • -
-
-
-

For more information visit: - - https://go.microsoft.com/fwlink/?LinkID=808681 - -

-
-
-
- + h1 { + color: #44525e; + margin: 15px 0 15px 0; + } - \ No newline at end of file + h2 { + margin: 10px 5px 0 0; + } + + h3 { + color: #363636; + margin: 5px 5px 0 0; + } + + code { + font-family: Consolas, "Courier New", courier, monospace; + } + + body .titleerror { + padding: 3px 3px 6px 3px; + display: block; + font-size: 1.5em; + font-weight: 100; + } + + a { + color: #1ba1e2; + text-decoration: none; + } + + a:hover { + color: #13709e; + text-decoration: underline; + } + + li { + margin: 5px; + } + + + + +

HTTP Error 500.0 - ANCM Out-Of-Process Handler Load Failure

+ +

Common causes of this issue:

+ + +

Troubleshooting steps:

+ + +

+ For more information visit: + %s https://go.microsoft.com/fwlink/?LinkID=2028526 +

+ + diff --git a/src/AspNetCoreModuleV2/AspNetCore/ServerErrorApplication.h b/src/AspNetCoreModuleV2/AspNetCore/ServerErrorApplication.h index ac5bd85aaf..b5b86aa20c 100644 --- a/src/AspNetCoreModuleV2/AspNetCore/ServerErrorApplication.h +++ b/src/AspNetCoreModuleV2/AspNetCore/ServerErrorApplication.h @@ -27,7 +27,7 @@ public: HRESULT CreateHandler(IHttpContext *pHttpContext, IREQUEST_HANDLER ** pRequestHandler) override { - auto handler = std::make_unique(*pHttpContext, m_HR, m_moduleInstance, m_disableStartupPage, m_page); + auto handler = std::make_unique(*pHttpContext, 500ui16, 0ui16, "Internal Server Error", m_HR, m_moduleInstance, m_disableStartupPage, m_page); *pRequestHandler = handler.release(); return S_OK; } @@ -39,4 +39,3 @@ private: int m_page; HINSTANCE m_moduleInstance; }; - diff --git a/src/AspNetCoreModuleV2/CommonLib/ServerErrorHandler.h b/src/AspNetCoreModuleV2/CommonLib/ServerErrorHandler.h index 721c0d12eb..f6745768a7 100644 --- a/src/AspNetCoreModuleV2/CommonLib/ServerErrorHandler.h +++ b/src/AspNetCoreModuleV2/CommonLib/ServerErrorHandler.h @@ -4,19 +4,27 @@ #pragma once #include "requesthandler.h" #include "file_utility.h" +#include "Environment.h" class ServerErrorHandler : public REQUEST_HANDLER { public: - ServerErrorHandler(IHttpContext &pContext, HRESULT hr, HINSTANCE moduleInstance, bool disableStartupPage, int page) - : m_pContext(pContext), m_HR(hr), m_disableStartupPage(disableStartupPage), m_page(page), m_moduleInstance(moduleInstance) + ServerErrorHandler(IHttpContext &pContext, USHORT statusCode, USHORT subStatusCode, std::string statusText, HRESULT hr, HINSTANCE moduleInstance, bool disableStartupPage, int page) + : m_pContext(pContext), + m_HR(hr), + m_disableStartupPage(disableStartupPage), + m_page(page), + m_moduleInstance(moduleInstance), + m_statusCode(statusCode), + m_subStatusCode(subStatusCode), + m_statusText(std::move(statusText)) { } REQUEST_NOTIFICATION_STATUS OnExecuteRequestHandler() override { - static std::string s_html500Page = FILE_UTILITY::GetHtml(m_moduleInstance, m_page); + static std::string s_html500Page = GetHtml(m_moduleInstance, m_page); WriteStaticResponse(m_pContext, s_html500Page, m_HR, m_disableStartupPage); @@ -24,9 +32,68 @@ public: } private: + void WriteStaticResponse(IHttpContext& pContext, std::string &page, HRESULT hr, bool disableStartupErrorPage) const + { + if (disableStartupErrorPage) + { + pContext.GetResponse()->SetStatus(m_statusCode, m_statusText.c_str(), m_subStatusCode, E_FAIL); + return; + } + + HTTP_DATA_CHUNK dataChunk = {}; + IHttpResponse* pResponse = pContext.GetResponse(); + pResponse->SetStatus(m_statusCode, m_statusText.c_str(), m_subStatusCode, hr, nullptr, true); + pResponse->SetHeader("Content-Type", + "text/html", + (USHORT)strlen("text/html"), + FALSE + ); + dataChunk.DataChunkType = HttpDataChunkFromMemory; + + dataChunk.FromMemory.pBuffer = page.data(); + dataChunk.FromMemory.BufferLength = static_cast(page.size()); + pResponse->WriteEntityChunkByReference(&dataChunk); + } + + static + std::string + GetHtml(HMODULE module, int page) + { + try + { + HRSRC rc = nullptr; + HGLOBAL rcData = nullptr; + const char* data = nullptr; + + THROW_LAST_ERROR_IF_NULL(rc = FindResource(module, MAKEINTRESOURCE(page), RT_HTML)); + THROW_LAST_ERROR_IF_NULL(rcData = LoadResource(module, rc)); + auto const size = SizeofResource(module, rc); + THROW_LAST_ERROR_IF(size == 0); + THROW_LAST_ERROR_IF_NULL(data = static_cast(LockResource(rcData))); + + auto additionalErrorLink = Environment::GetEnvironmentVariableValue(L"ANCM_ADDITIONAL_ERROR_PAGE_LINK"); + std::string additionalHtml; + + if (additionalErrorLink.has_value()) + { + additionalHtml = format(" %S and ", additionalErrorLink->c_str(), additionalErrorLink->c_str()); + } + + return format(data, additionalHtml.c_str()); + } + catch (...) + { + OBSERVE_CAUGHT_EXCEPTION(); + return ""; + } + } + IHttpContext &m_pContext; HRESULT m_HR; bool m_disableStartupPage; int m_page; HINSTANCE m_moduleInstance; + USHORT m_statusCode; + USHORT m_subStatusCode; + std::string m_statusText; }; diff --git a/src/AspNetCoreModuleV2/CommonLib/file_utility.cpp b/src/AspNetCoreModuleV2/CommonLib/file_utility.cpp index 228c1c0d66..2831eac64d 100644 --- a/src/AspNetCoreModuleV2/CommonLib/file_utility.cpp +++ b/src/AspNetCoreModuleV2/CommonLib/file_utility.cpp @@ -167,23 +167,3 @@ Finished: return hr; } -std::string -FILE_UTILITY::GetHtml(HMODULE module, int page) -{ - HRESULT hr = S_OK; - HRSRC rc = nullptr; - HGLOBAL rcData = nullptr; - const char* data = nullptr; - DWORD size = 0; - - FINISHED_LAST_ERROR_IF_NULL(rc = FindResource(module, MAKEINTRESOURCE(page), RT_HTML)); - FINISHED_LAST_ERROR_IF_NULL(rcData = LoadResource(module, rc)); - size = SizeofResource(module, rc); - FINISHED_LAST_ERROR_IF(size == 0); - FINISHED_LAST_ERROR_IF_NULL(data = static_cast(LockResource(rcData))); - - return data; -Finished: - - return ""; -} diff --git a/src/AspNetCoreModuleV2/CommonLib/requesthandler.h b/src/AspNetCoreModuleV2/CommonLib/requesthandler.h index b4cd3a0e35..a5e16bf022 100644 --- a/src/AspNetCoreModuleV2/CommonLib/requesthandler.h +++ b/src/AspNetCoreModuleV2/CommonLib/requesthandler.h @@ -46,32 +46,6 @@ public: { } -protected: - - static - void WriteStaticResponse(IHttpContext& pContext, std::string &s_html500Page, HRESULT hr, bool disableStartupErrorPage) - { - if (disableStartupErrorPage) - { - pContext.GetResponse()->SetStatus(500, "Internal Server Error", 30, E_FAIL); - return; - } - - HTTP_DATA_CHUNK dataChunk = {}; - IHttpResponse* pResponse = pContext.GetResponse(); - pResponse->SetStatus(500, "Internal Server Error", 0, hr, nullptr, true); - pResponse->SetHeader("Content-Type", - "text/html", - (USHORT)strlen("text/html"), - FALSE - ); - dataChunk.DataChunkType = HttpDataChunkFromMemory; - - dataChunk.FromMemory.pBuffer = s_html500Page.data(); - dataChunk.FromMemory.BufferLength = static_cast(s_html500Page.size()); - pResponse->WriteEntityChunkByReference(&dataChunk); - } - private: mutable LONG m_cRefs = 1; }; diff --git a/src/AspNetCoreModuleV2/InProcessRequestHandler/InProcessRhStaticHtml.htm b/src/AspNetCoreModuleV2/InProcessRequestHandler/InProcessRhStaticHtml.htm index b558d83d5e..59d6b0dacb 100644 --- a/src/AspNetCoreModuleV2/InProcessRequestHandler/InProcessRhStaticHtml.htm +++ b/src/AspNetCoreModuleV2/InProcessRequestHandler/InProcessRhStaticHtml.htm @@ -1,44 +1,83 @@ - - + + + + + HTTP Error 500.30 - ANCM In-Process Start Failure + - - -
+ h1 { + color: #44525e; + margin: 15px 0 15px 0; + } -

HTTP Error 500.30 - ANCM In-Process Start Failure

-
+ h2 { + margin: 10px 5px 0 0; + } -
-

Common causes of this issue:

-
    -
  • The application failed to start
  • -
  • The application started but then stopped
  • -
  • The application started but threw an exception during startup
  • -
-
-
-
+ h3 { + color: #363636; + margin: 5px 5px 0 0; + } -
-

Troubleshooting steps:

-
    -
  • Check the system event log for error messages
  • -
  • Enable logging the application process' stdout messages
  • -
  • Attach a debugger to the application process and inspect
  • -
-
-
-

- For more information visit: - https://go.microsoft.com/fwlink/?LinkID=808681 -

-
-
-
- + code { + font-family: Consolas, "Courier New", courier, monospace; + } + + body .titleerror { + padding: 3px 3px 6px 3px; + display: block; + font-size: 1.5em; + font-weight: 100; + } + + a { + color: #1ba1e2; + text-decoration: none; + } + + a:hover { + color: #13709e; + text-decoration: underline; + } + + li { + margin: 5px; + } + + + + +

HTTP Error 500.30 - ANCM In-Process Start Failure

+ +

Common causes of this issue:

+
    +
  • The application failed to start
  • +
  • The application started but then stopped
  • +
  • The application started but threw an exception during startup
  • +
+ +

Troubleshooting steps:

+
    +
  • Check the system event log for error messages
  • +
  • Enable logging the application process' stdout messages
  • +
  • Attach a debugger to the application process and inspect
  • +
+ +

+ For more information visit: + %s https://go.microsoft.com/fwlink/?LinkID=2028265 +

+ + diff --git a/src/AspNetCoreModuleV2/InProcessRequestHandler/StartupExceptionApplication.h b/src/AspNetCoreModuleV2/InProcessRequestHandler/StartupExceptionApplication.h index 7d8acc4e7e..72b26d857c 100644 --- a/src/AspNetCoreModuleV2/InProcessRequestHandler/StartupExceptionApplication.h +++ b/src/AspNetCoreModuleV2/InProcessRequestHandler/StartupExceptionApplication.h @@ -25,10 +25,9 @@ public: ~StartupExceptionApplication() = default; - HRESULT - CreateHandler(IHttpContext *pHttpContext, IREQUEST_HANDLER ** pRequestHandler) + HRESULT CreateHandler(IHttpContext *pHttpContext, IREQUEST_HANDLER ** pRequestHandler) { - *pRequestHandler = new ServerErrorHandler(*pHttpContext, m_HR,m_moduleInstance, m_disableLogs, IN_PROCESS_RH_STATIC_HTML); + *pRequestHandler = new ServerErrorHandler(*pHttpContext, 500, 30, "Internal Server Error", m_HR, m_moduleInstance, m_disableLogs, IN_PROCESS_RH_STATIC_HTML); return S_OK; } diff --git a/src/AspNetCoreModuleV2/OutOfProcessRequestHandler/HtmlResponses.rc b/src/AspNetCoreModuleV2/OutOfProcessRequestHandler/HtmlResponses.rc new file mode 100644 index 0000000000..231f122fef --- /dev/null +++ b/src/AspNetCoreModuleV2/OutOfProcessRequestHandler/HtmlResponses.rc @@ -0,0 +1,68 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// HTML +// + +OUT_OF_PROCESS_RH_STATIC_HTML HTML "OutOfProcessRhStaticHtml.htm" + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/AspNetCoreModuleV2/OutOfProcessRequestHandler/OutOfProcessRequestHandler.vcxproj b/src/AspNetCoreModuleV2/OutOfProcessRequestHandler/OutOfProcessRequestHandler.vcxproj index 3c4ee3b264..7d29672fa0 100644 --- a/src/AspNetCoreModuleV2/OutOfProcessRequestHandler/OutOfProcessRequestHandler.vcxproj +++ b/src/AspNetCoreModuleV2/OutOfProcessRequestHandler/OutOfProcessRequestHandler.vcxproj @@ -228,6 +228,7 @@ + @@ -268,9 +269,13 @@ + + + true + diff --git a/src/AspNetCoreModuleV2/OutOfProcessRequestHandler/OutOfProcessRhStaticHtml.htm b/src/AspNetCoreModuleV2/OutOfProcessRequestHandler/OutOfProcessRhStaticHtml.htm new file mode 100644 index 0000000000..e7d2f04e7c --- /dev/null +++ b/src/AspNetCoreModuleV2/OutOfProcessRequestHandler/OutOfProcessRhStaticHtml.htm @@ -0,0 +1,85 @@ + + + + + HTTP Error 502.5 - ANCM Out-Of-Process Startup Failure + + + +

HTTP Error 502.5 - ANCM Out-Of-Process Startup Failure

+ +

Common causes of this issue:

+ +
    +
  • The application process failed to start
  • +
  • The application process started but then stopped
  • +
  • The application process started but failed to listen on the configured port
  • +
+ +

Troubleshooting steps:

+ +
    +
  • Check the system event log for error messages
  • +
  • Enable logging the application process' stdout messages
  • +
  • Attach a debugger to the application process and inspect
  • +
+ +

+ For more information visit: + %s https://go.microsoft.com/fwlink/?LinkID=808681 +

+ + + diff --git a/src/AspNetCoreModuleV2/OutOfProcessRequestHandler/dllmain.cpp b/src/AspNetCoreModuleV2/OutOfProcessRequestHandler/dllmain.cpp index b5f2014bf2..24c166a056 100644 --- a/src/AspNetCoreModuleV2/OutOfProcessRequestHandler/dllmain.cpp +++ b/src/AspNetCoreModuleV2/OutOfProcessRequestHandler/dllmain.cpp @@ -20,6 +20,7 @@ SRWLOCK g_srwLockRH; HINTERNET g_hWinhttpSession = NULL; IHttpServer * g_pHttpServer = NULL; HINSTANCE g_hWinHttpModule; +HINSTANCE g_hOutOfProcessRHModule; HINSTANCE g_hAspNetCoreModule; HANDLE g_hEventLog = NULL; @@ -223,6 +224,7 @@ BOOL APIENTRY DllMain(HMODULE hModule, switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: + g_hOutOfProcessRHModule = hModule; DisableThreadLibraryCalls(hModule); InitializeSRWLock(&g_srwLockRH); DebugInitialize(hModule); diff --git a/src/AspNetCoreModuleV2/OutOfProcessRequestHandler/forwardinghandler.cpp b/src/AspNetCoreModuleV2/OutOfProcessRequestHandler/forwardinghandler.cpp index c43241495d..d97a55a17e 100644 --- a/src/AspNetCoreModuleV2/OutOfProcessRequestHandler/forwardinghandler.cpp +++ b/src/AspNetCoreModuleV2/OutOfProcessRequestHandler/forwardinghandler.cpp @@ -4,6 +4,8 @@ #include "forwardinghandler.h" #include "url_utility.h" #include "exceptions.h" +#include "ServerErrorHandler.h" +#include "resource.h" // Just to be aware of the FORWARDING_HANDLER object size. C_ASSERT(sizeof(FORWARDING_HANDLER) <= 632); @@ -16,7 +18,6 @@ C_ASSERT(sizeof(FORWARDING_HANDLER) <= 632); #define FORWARDING_HANDLER_SIGNATURE ((DWORD)'FHLR') #define FORWARDING_HANDLER_SIGNATURE_FREE ((DWORD)'fhlr') -STRA FORWARDING_HANDLER::sm_pStra502ErrorMsg; ALLOC_CACHE_HANDLER * FORWARDING_HANDLER::sm_pAlloc = NULL; TRACE_LOG * FORWARDING_HANDLER::sm_pTraceLog = NULL; PROTOCOL_CONFIG FORWARDING_HANDLER::sm_ProtocolConfig; @@ -318,18 +319,8 @@ Failure: } else if (fFailedToStartKestrel && !m_pApplication->QueryConfig()->QueryDisableStartUpErrorPage()) { - HTTP_DATA_CHUNK DataChunk; - pResponse->SetStatus(502, "Bad Gateway", 5, hr, NULL, TRUE); - pResponse->SetHeader("Content-Type", - "text/html", - (USHORT)strlen("text/html"), - FALSE - ); - - DataChunk.DataChunkType = HttpDataChunkFromMemory; - DataChunk.FromMemory.pBuffer = (PVOID)sm_pStra502ErrorMsg.QueryStr(); - DataChunk.FromMemory.BufferLength = sm_pStra502ErrorMsg.QueryCB(); - pResponse->WriteEntityChunkByReference(&DataChunk); + ServerErrorHandler handler(*m_pW3Context, 502, 5, "Bad Gateway", hr, g_hOutOfProcessRHModule, m_pApplication->QueryConfig()->QueryDisableStartUpErrorPage(), OUT_OF_PROCESS_RH_STATIC_HTML); + handler.OnExecuteRequestHandler(); } else { @@ -728,31 +719,6 @@ HRESULT sm_pTraceLog = CreateRefTraceLog(10000, 0); } - sm_pStra502ErrorMsg.Copy( - " \ - \ - \ - \ - IIS 502.5 Error \ -
\ -

HTTP Error 502.5 - Process Failure

\ -
\ -

Common causes of this issue:

\ -
  • The application process failed to start
  • \ -
  • The application process started but then stopped
  • \ -
  • The application process started but failed to listen on the configured port
\ -
\ -
\ -

Troubleshooting steps:

\ -
  • Check the system event log for error messages
  • \ -
  • Enable logging the application process' stdout messages
  • \ -
  • Attach a debugger to the application process and inspect
\ -

For more information visit: \ - https://go.microsoft.com/fwlink/?LinkID=808681

\ -
\ -
\ -
"); - Finished: if (FAILED_LOG(hr)) { @@ -765,8 +731,6 @@ Finished: VOID FORWARDING_HANDLER::StaticTerminate() { - sm_pStra502ErrorMsg.Reset(); - if (sm_pResponseHeaderHash != NULL) { sm_pResponseHeaderHash->Clear(); diff --git a/src/AspNetCoreModuleV2/OutOfProcessRequestHandler/forwardinghandler.h b/src/AspNetCoreModuleV2/OutOfProcessRequestHandler/forwardinghandler.h index cb9255e16d..e30d69b6c0 100644 --- a/src/AspNetCoreModuleV2/OutOfProcessRequestHandler/forwardinghandler.h +++ b/src/AspNetCoreModuleV2/OutOfProcessRequestHandler/forwardinghandler.h @@ -1,6 +1,7 @@ #pragma once extern DWORD g_OptionalWinHttpFlags; +extern HINSTANCE g_hOutOfProcessRHModule; extern HINSTANCE g_hWinHttpModule; extern HINSTANCE g_hAspNetCoreModule; diff --git a/src/AspNetCoreModuleV2/OutOfProcessRequestHandler/resource.h b/src/AspNetCoreModuleV2/OutOfProcessRequestHandler/resource.h new file mode 100644 index 0000000000..4d54425300 --- /dev/null +++ b/src/AspNetCoreModuleV2/OutOfProcessRequestHandler/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by HtmlResponses.rc +// +#define OUT_OF_PROCESS_RH_STATIC_HTML 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/test/IISExpress.FunctionalTests/InProcess/ErrorPagesTests.cs b/test/IISExpress.FunctionalTests/InProcess/ErrorPagesTests.cs new file mode 100644 index 0000000000..7669e7034a --- /dev/null +++ b/test/IISExpress.FunctionalTests/InProcess/ErrorPagesTests.cs @@ -0,0 +1,106 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Net; +using System.Net.Http; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Server.IIS.FunctionalTests.Utilities; +using Microsoft.AspNetCore.Server.IntegrationTesting; +using Microsoft.AspNetCore.Server.IntegrationTesting.IIS; +using Microsoft.AspNetCore.Testing.xunit; +using Xunit; + +namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests +{ + [Collection(PublishedSitesCollection.Name)] + public class ErrorPagesTests : IISFunctionalTestBase + { + private readonly PublishedSitesFixture _fixture; + + public ErrorPagesTests(PublishedSitesFixture fixture) + { + _fixture = fixture; + } + + [ConditionalFact] + public async Task IncludesAdditionalErrorPageTextInProcessHandlerLoadFailure() + { + var deploymentParameters = _fixture.GetBaseDeploymentParameters(publish: true); + var response = await DeployAppWithStartupFailure(deploymentParameters); + + Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); + + StopServer(); + + Assert.Contains("HTTP Error 500.0 - ANCM In-Process Handler Load Failure", await response.Content.ReadAsStringAsync()); + await AssertLink(response); + } + + [ConditionalFact] + public async Task IncludesAdditionalErrorPageTextOutOfProcessStartupFailure() + { + var deploymentParameters = _fixture.GetBaseDeploymentParameters(HostingModel.OutOfProcess, publish: true); + var response = await DeployAppWithStartupFailure(deploymentParameters); + + Assert.Equal(HttpStatusCode.BadGateway, response.StatusCode); + + StopServer(); + + Assert.Contains("HTTP Error 502.5 - ANCM Out-Of-Process Startup Failure", await response.Content.ReadAsStringAsync()); + await AssertLink(response); + } + + [ConditionalFact] + public async Task IncludesAdditionalErrorPageTextOutOfProcessHandlerLoadFailure() + { + var deploymentParameters = _fixture.GetBaseDeploymentParameters(HostingModel.OutOfProcess, publish: true); + deploymentParameters.HandlerSettings["handlerVersion"] = "88.93"; + deploymentParameters.EnvironmentVariables["ANCM_ADDITIONAL_ERROR_PAGE_LINK"] = "http://example"; + + var deploymentResult = await DeployAsync(deploymentParameters); + var response = await deploymentResult.HttpClient.GetAsync("HelloWorld"); + + Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); + + StopServer(); + + Assert.Contains("HTTP Error 500.0 - ANCM Out-Of-Process Handler Load Failure", await response.Content.ReadAsStringAsync()); + await AssertLink(response); + } + + [ConditionalFact] + public async Task IncludesAdditionalErrorPageTextInProcessStartupFailure() + { + var deploymentParameters = _fixture.GetBaseDeploymentParameters(publish: true); + deploymentParameters.TransformArguments((a, _) => $"{a} EarlyReturn"); + deploymentParameters.EnvironmentVariables["ANCM_ADDITIONAL_ERROR_PAGE_LINK"] = "http://example"; + + var deploymentResult = await DeployAsync(deploymentParameters); + var response = await deploymentResult.HttpClient.GetAsync("HelloWorld"); + + Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); + + StopServer(); + + Assert.Contains("HTTP Error 500.30 - ANCM In-Process Start Failure", await response.Content.ReadAsStringAsync()); + await AssertLink(response); + } + + private static async Task AssertLink(HttpResponseMessage response) + { + Assert.Contains(" http://example and ", await response.Content.ReadAsStringAsync()); + } + + private async Task DeployAppWithStartupFailure(IISDeploymentParameters deploymentParameters) + { + deploymentParameters.WebConfigActionList.Add(WebConfigHelpers.AddOrModifyAspNetCoreSection("processPath", "doesnot")); + deploymentParameters.WebConfigActionList.Add(WebConfigHelpers.AddOrModifyAspNetCoreSection("arguments", "start")); + + deploymentParameters.EnvironmentVariables["ANCM_ADDITIONAL_ERROR_PAGE_LINK"] = "http://example"; + + var deploymentResult = await DeployAsync(deploymentParameters); + + return await deploymentResult.HttpClient.GetAsync("HelloWorld"); + } + } +} diff --git a/test/IISExpress.FunctionalTests/InProcess/StartupTests.cs b/test/IISExpress.FunctionalTests/InProcess/StartupTests.cs index 662aba0727..037ab8eb2e 100644 --- a/test/IISExpress.FunctionalTests/InProcess/StartupTests.cs +++ b/test/IISExpress.FunctionalTests/InProcess/StartupTests.cs @@ -62,7 +62,7 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests EventLogHelpers.VerifyEventLogEvent(deploymentResult, $@"Application '{Regex.Escape(deploymentResult.ContentRoot)}\\' wasn't able to start. {subError}"); - Assert.Contains("HTTP Error 500.0 - ANCM InProcess Startup Failure", await response.Content.ReadAsStringAsync()); + Assert.Contains("HTTP Error 500.0 - ANCM In-Process Handler Load Failure", await response.Content.ReadAsStringAsync()); } [ConditionalFact] @@ -456,7 +456,7 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests { var response = await deploymentResult.HttpClient.GetAsync("/HelloWorld"); Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); - Assert.Contains("HTTP Error 500.0 - ANCM InProcess Startup Failure", await response.Content.ReadAsStringAsync()); + Assert.Contains("HTTP Error 500.0 - ANCM In-Process Handler Load Failure", await response.Content.ReadAsStringAsync()); StopServer(); } } diff --git a/test/IISExpress.FunctionalTests/OutOfProcess/GlobalVersionTests.cs b/test/IISExpress.FunctionalTests/OutOfProcess/GlobalVersionTests.cs index 855096e026..c92349ae3a 100644 --- a/test/IISExpress.FunctionalTests/OutOfProcess/GlobalVersionTests.cs +++ b/test/IISExpress.FunctionalTests/OutOfProcess/GlobalVersionTests.cs @@ -65,7 +65,7 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests var response = await deploymentResult.HttpClient.GetAsync(_helloWorldRequest); Assert.False(response.IsSuccessStatusCode); var responseString = await response.Content.ReadAsStringAsync(); - Assert.Contains("HTTP Error 500.0 - ANCM OutOfProcess Startup Failure", responseString); + Assert.Contains("HTTP Error 500.0 - ANCM Out-Of-Process Handler Load Failure", responseString); } [ConditionalTheory]