diff --git a/BTCPayServer.Tests/SeleniumTester.cs b/BTCPayServer.Tests/SeleniumTester.cs index c7f163312..e97b958d5 100644 --- a/BTCPayServer.Tests/SeleniumTester.cs +++ b/BTCPayServer.Tests/SeleniumTester.cs @@ -202,7 +202,7 @@ namespace BTCPayServer.Tests internal void AssertNotFound() { - Assert.Contains("Status Code: 404; Not Found", Driver.PageSource); + Assert.Contains("404 - Page not found", Driver.PageSource); } public void GoToHome() diff --git a/BTCPayServer.Tests/UnitTest1.cs b/BTCPayServer.Tests/UnitTest1.cs index 3b6b0fcb3..ef2b8327c 100644 --- a/BTCPayServer.Tests/UnitTest1.cs +++ b/BTCPayServer.Tests/UnitTest1.cs @@ -521,6 +521,39 @@ namespace BTCPayServer.Tests } } + [Fact] + [Trait("Integration", "Integration")] + public async Task CanThrowBitpay404Error() + { + using (var tester = ServerTester.Create()) + { + await tester.StartAsync(); + var user = tester.NewAccount(); + user.GrantAccess(); + user.RegisterDerivationScheme("BTC"); + + var invoice = user.BitPay.CreateInvoice(new Invoice() + { + Buyer = new Buyer() { email = "test@fwf.com" }, + Price = 5000.0m, + Currency = "USD", + PosData = "posData", + OrderId = "orderId", + ItemDesc = "Some description", + FullNotifications = true + }, Facade.Merchant); + + try + { + var throwsBitpay404Error = user.BitPay.GetInvoice(invoice.Id + "123"); + } + catch (BitPayException ex) + { + Assert.Equal("Object not found", ex.Errors.First()); + } + } + } + [Fact] [Trait("Fast", "Fast")] public void RoundupCurrenciesCorrectly() diff --git a/BTCPayServer/Controllers/ErrorController.cs b/BTCPayServer/Controllers/ErrorController.cs new file mode 100644 index 000000000..0cafdb4e5 --- /dev/null +++ b/BTCPayServer/Controllers/ErrorController.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; + +namespace BTCPayServer.Controllers +{ + [Route("[controller]/[action]")] + public class ErrorController : Controller + { + public IActionResult Handle(int? statusCode = null) + { + if (statusCode.HasValue) + { + var specialPages = new[] { 404, 429, 500 }; + if (specialPages.Any(a => a == statusCode.Value)) + { + var viewName = statusCode.ToString(); + return View(viewName); + } + } + return View(statusCode); + } + } +} diff --git a/BTCPayServer/Hosting/BTCpayMiddleware.cs b/BTCPayServer/Hosting/BTCpayMiddleware.cs index d58c2953d..7175fd0d4 100644 --- a/BTCPayServer/Hosting/BTCpayMiddleware.cs +++ b/BTCPayServer/Hosting/BTCpayMiddleware.cs @@ -62,10 +62,12 @@ namespace BTCPayServer.Hosting catch (UnauthorizedAccessException ex) { await HandleBitpayHttpException(httpContext, new BitpayHttpException(401, ex.Message)); + return; } catch (BitpayHttpException ex) { await HandleBitpayHttpException(httpContext, ex); + return; } catch (Exception ex) { @@ -133,13 +135,9 @@ namespace BTCPayServer.Hosting private static async Task HandleBitpayHttpException(HttpContext httpContext, BitpayHttpException ex) { httpContext.Response.StatusCode = ex.StatusCode; - using (var writer = new StreamWriter(httpContext.Response.Body, new UTF8Encoding(false), 1024, true)) - { - httpContext.Response.ContentType = "application/json"; - var result = JsonConvert.SerializeObject(new BitpayErrorsModel(ex)); - writer.Write(result); - await writer.FlushAsync(); - } + httpContext.Response.ContentType = "application/json"; + var result = JsonConvert.SerializeObject(new BitpayErrorsModel(ex)); + await httpContext.Response.WriteAsync(result); } } } diff --git a/BTCPayServer/Hosting/Startup.cs b/BTCPayServer/Hosting/Startup.cs index 541f5cb3f..a88e7f037 100644 --- a/BTCPayServer/Hosting/Startup.cs +++ b/BTCPayServer/Hosting/Startup.cs @@ -241,6 +241,10 @@ namespace BTCPayServer.Hosting forwardingOptions.KnownProxies.Clear(); forwardingOptions.ForwardedHeaders = ForwardedHeaders.All; app.UseForwardedHeaders(forwardingOptions); + + + app.UseStatusCodePagesWithReExecute("/Error/Handle", "?statusCode={0}"); + app.UsePayServer(); app.UseRouting(); app.UseCors(); @@ -252,7 +256,6 @@ namespace BTCPayServer.Hosting app.UseSession(); app.UseWebSockets(); - app.UseStatusCodePages(); app.UseEndpoints(endpoints => { diff --git a/BTCPayServer/Views/Account/Login.cshtml b/BTCPayServer/Views/Account/Login.cshtml index 2fc0c4d41..b7eaadeca 100644 --- a/BTCPayServer/Views/Account/Login.cshtml +++ b/BTCPayServer/Views/Account/Login.cshtml @@ -2,7 +2,7 @@ @inject BTCPayServer.HostedServices.CssThemeManager themeManager @{ ViewData["Title"] = "Log in"; - Layout = "_WelcomeLayout.cshtml"; + Layout = "_LayoutWelcome"; } @if (TempData.HasStatusMessage()) { diff --git a/BTCPayServer/Views/Account/Register.cshtml b/BTCPayServer/Views/Account/Register.cshtml index a7b7e298c..b87603b1b 100644 --- a/BTCPayServer/Views/Account/Register.cshtml +++ b/BTCPayServer/Views/Account/Register.cshtml @@ -2,7 +2,7 @@ @{ ViewData["Title"] = "Register"; var useBasicLayout = ViewData["UseBasicLayout"] is true; - Layout = useBasicLayout ? "../Shared/_Layout.cshtml" : "_WelcomeLayout.cshtml"; + Layout = useBasicLayout ? "_Layout" : "_LayoutWelcome"; } @if (TempData.HasStatusMessage()) { diff --git a/BTCPayServer/Views/Error/404.cshtml b/BTCPayServer/Views/Error/404.cshtml new file mode 100644 index 000000000..10daba9ff --- /dev/null +++ b/BTCPayServer/Views/Error/404.cshtml @@ -0,0 +1,15 @@ +@{ + ViewData["ErrorTitle"] = "404 - Page not found"; +} + +
+ This is like searching for a person more beautiful than Nicolas Dorier.
+
+
+
+
+
+ It doesn't exist.
+
+ You can always try navigating back to home.
+
+ Please send requests slower. Or face the wrath of Vin Diesel.
+
+
+
+
+
+ You sure you want to risk that?
+
+ Slowly navigate back to home.
+
+ Whoops, something really went wrong! Mr Kukks is so sorry.
+
+
+
+
+
+ Consult server log and consider submitting issue on BTCPayServer GitHub.
+
+ Navigate back to home.
+
+ Generic error occurred, HTTP Code: @Model
+
+ Consult server log for more details.
+
+ Navigate back to home.
+
+
BTCPay Server is a self-hosted, open-source cryptocurrency payment processor. It is secure, private, censorship-resistant and free.
-