1 module hunt.http.routing.handler.ErrorResponseHandler;
2 
3 import hunt.http.routing.handler.DefaultErrorResponseHandler;
4 import hunt.http.routing.RoutingContext;
5 
6 import hunt.http.Version;
7 import hunt.http.HttpHeader;
8 import hunt.http.HttpStatus;
9 
10 import hunt.logging;
11 import hunt.Exceptions;
12 
13 import std.conv;
14 import std.concurrency : initOnce;
15 import std.range;
16 
17 
18 /**
19  * 
20  */
21 abstract class ErrorResponseHandler : RouteHandler {
22 
23     private __gshared ErrorResponseHandler inst;
24 
25     static ErrorResponseHandler Default() {
26         if(inst is null) {
27             inst = new DefaultErrorResponseHandler();
28         }
29         return inst;
30     }
31 
32     static void Default(ErrorResponseHandler handler) {
33         inst = handler;
34     }
35 
36     private int _status;
37 
38     this(int status = HttpStatus.NOT_FOUND_404) {
39         _status = status;
40     }
41 
42 
43     void handle(RoutingContext context) {
44         if (context.hasNext()) {
45             try {
46                 context.next();
47             } catch (Exception t) {
48                 version(HUNT_DEBUG) errorf("http handler exception", t.msg);
49                 if (!context.isCommitted()) {
50                     render(context, HttpStatus.INTERNAL_SERVER_ERROR_500, t);
51                     context.fail(t);
52                 }
53             }
54         } else {
55             render(context, _status, null);
56             context.succeed(true);
57         }
58     }
59 
60     abstract void render(RoutingContext context, int status, Exception ex);
61 }
62 
63 
64 void renderErrorPage(RoutingContext context, int status, Exception t) {
65     HttpStatusCode code = HttpStatus.getCode(status); 
66     if(code == HttpStatusCode.Null)
67         code = HttpStatusCode.INTERNAL_SERVER_ERROR;
68     
69     string title = status.to!string() ~ " " ~ code.getMessage();
70     string content;
71     if(status == HttpStatus.NOT_FOUND_404) {
72         // content = title;
73     } else if(status == HttpStatus.INTERNAL_SERVER_ERROR_500) {
74         content = "The server internal error. <br/>" ~ (t !is null ? t.msg : "");
75     } else {
76         content = (t !is null ? t.msg : "");
77     }
78 
79     context.setStatus(status);
80     context.getResponseHeaders().put(HttpHeader.CONTENT_TYPE, "text/html");
81     context.write("<!DOCTYPE html>")
82         .write("<html>")
83         .write("<head>")
84         .write("<title>")
85         .write(title)
86         .write("</title>")
87         .write("</head>")
88         .write("<body>")
89         .write("<center><h1> " ~ title ~ " </h1></center>");
90 
91     if(!content.empty()) {
92         context.write("<center><p>" ~ content ~ "</p></center>");
93     }
94 
95     context.write("<hr/>")
96         .write("<center><footer><em>powered by Hunt HTTP " ~ Version ~"</em></footer></center>")
97         .write("</body>")
98         .end("</html>");
99 }
100 
101