Nancyの403からエラー処理へ
6282 ワード
前回のブログでは、権限のないユーザーがリソースにアクセスすると、403エラーが返され、403はユーザーにとってわけのわからない数字であり、もちろん友好的なヒントに処理します.
エラー処理については、Nancyのソースコードを見てみましたが、このように処理されています.次のアドレスを参照してください.
https://github.com/NancyFx/Nancy/blob/master/src/Nancy/ErrorHandling/DefaultStatusCodeHandler.cs
実はNancyは私たちが同じ方法で処理することを許可して、今DefaultStatusCodeHandler.csのソースコードをコピーして、私たち自身のCustomStatusCodeに変更します.csは以下の通り、詳細についてはNancyソースDefaultStatusCodeHandlerを参照する.cs.
これにより、Nancyに内蔵されている500404エラーをカスタマイズした表示に変更することもできます.
これは面倒だと思うことがありますが、Moduleでログインユーザーがロールを持っているかどうかを判断することができます.コードは以下の通りです.
エラー処理については、Nancyのソースコードを見てみましたが、このように処理されています.次のアドレスを参照してください.
https://github.com/NancyFx/Nancy/blob/master/src/Nancy/ErrorHandling/DefaultStatusCodeHandler.cs
実はNancyは私たちが同じ方法で処理することを許可して、今DefaultStatusCodeHandler.csのソースコードをコピーして、私たち自身のCustomStatusCodeに変更します.csは以下の通り、詳細についてはNancyソースDefaultStatusCodeHandlerを参照する.cs.
using Nancy;
using Nancy.ErrorHandling;
using Nancy.ViewEngines;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Nancy.Responses.Negotiation;
using Nancy.Extensions;
using Nancy.IO;
namespace NancySelfHostWeb
{
public class CustomStatusCode: IStatusCodeHandler
{
private const string DisableErrorTracesTrueMessage = "Error details are currently disabled. Please set StaticConfiguration.DisableErrorTraces = false;
to enable.";
private readonly IDictionary errorMessages;
private readonly IDictionary errorPages;
private readonly IResponseNegotiator responseNegotiator;
private readonly HttpStatusCode[] supportedStatusCodes = { HttpStatusCode.Forbidden, HttpStatusCode.NotFound};
public CustomStatusCode(IResponseNegotiator responseNegotiator)
{
this.errorMessages = new Dictionary
{
{ HttpStatusCode.Forbidden, " !" },
{ HttpStatusCode.NotFound, " !" }
};
this.errorPages = new Dictionary
{
{ HttpStatusCode.Forbidden, LoadResource("NancySelfHostWeb.403.html") },
{ HttpStatusCode.NotFound, LoadResource("NancySelfHostWeb.404.html") }
};
this.responseNegotiator = responseNegotiator;
}
public bool HandlesStatusCode(HttpStatusCode statusCode, NancyContext context)
{
return this.supportedStatusCodes.Any(s => s == statusCode);
}
public void Handle(HttpStatusCode statusCode, NancyContext context)
{
if (context.Response != null && context.Response.Contents != null && !ReferenceEquals(context.Response.Contents, Response.NoBody))
{
return;
}
if (!this.errorMessages.ContainsKey(statusCode) || !this.errorPages.ContainsKey(statusCode))
{
return;
}
Response existingResponse = null;
if (context.Response != null)
{
existingResponse = context.Response;
}
context.NegotiationContext = new NegotiationContext();
var result = new DefaultStatusCodeHandlerResult(statusCode, this.errorMessages[statusCode], StaticConfiguration.DisableErrorTraces ? DisableErrorTracesTrueMessage : context.GetExceptionDetails());
try
{
context.Response = this.responseNegotiator.NegotiateResponse(result, context);
context.Response.StatusCode = statusCode;
if (existingResponse != null)
{
context.Response.ReasonPhrase = existingResponse.ReasonPhrase;
}
return;
}
catch (ViewNotFoundException)
{
}
this.ModifyResponse(statusCode, context, result);
}
private void ModifyResponse(HttpStatusCode statusCode, NancyContext context, DefaultStatusCodeHandlerResult result)
{
if (context.Response == null)
{
context.Response = new Response { StatusCode = statusCode };
}
var contents = this.errorPages[statusCode];
if (!string.IsNullOrEmpty(contents))
{
contents = contents.Replace("[DETAILS]", result.Details);
}
context.Response.ContentType = "text/html";
context.Response.Contents = s =>
{
using (var writer = new StreamWriter(new UnclosableStreamWrapper(s), Encoding.UTF8))
{
writer.Write(contents);
}
};
}
private static string LoadResource(string filename)
{
//
var resourceStream = typeof(CustomStatusCode).Assembly.GetManifestResourceStream(string.Format("{0}", filename));
if (resourceStream == null)
{
return string.Empty;
}
using (var reader = new StreamReader(resourceStream))
{
return reader.ReadToEnd();
}
}
internal class DefaultStatusCodeHandlerResult
{
public DefaultStatusCodeHandlerResult(HttpStatusCode statusCode, string message, string details)
{
this.StatusCode = statusCode;
this.Message = message;
this.Details = details;
}
public HttpStatusCode StatusCode { get; private set; }
public string Message { get; private set; }
public string Details { get; private set; }
}
}
}
これにより、Nancyに内蔵されている500404エラーをカスタマイズした表示に変更することもできます.
これは面倒だと思うことがありますが、Moduleでログインユーザーがロールを持っているかどうかを判断することができます.コードは以下の通りです.
using Nancy;
using Nancy.Security;
using System.Linq;
namespace TestSelfHostWeb.Modules
{
public class IndexModule : NancyModule
{
public IndexModule()
{
//
this.RequiresAuthentication();
Get["/"] = parameters =>
{
// ,
//this.RequiresClaims("admin");
//
if (!this.Context.CurrentUser.Claims.Contains("admin"))
{
return View["error"];// error.cshtml
}
return View["index"];
};
}
}
}