001/** 002 * Copyright (c) 2015-2022, Michael Yang 杨福海 (fuhai999@gmail.com). 003 * <p> 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * <p> 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * <p> 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package io.jboot.web.render; 017 018import com.jfinal.kit.JsonKit; 019import com.jfinal.kit.Ret; 020import com.jfinal.render.Render; 021import com.jfinal.render.RenderException; 022import com.jfinal.render.RenderManager; 023import io.jboot.exception.JbootExceptionHolder; 024import io.jboot.utils.RequestUtil; 025import io.jboot.utils.StrUtil; 026import io.jboot.components.valid.ValidException; 027 028import java.io.PrintWriter; 029import java.util.List; 030 031/** 032 * JbootErrorRender. 033 */ 034public class JbootErrorRender extends Render { 035 036 protected static final String htmlContentType = "text/html;charset=" + getEncoding(); 037 protected static final String jsonContentType = "application/json;charset=" + getEncoding(); 038 039 protected static final String poweredBy = "<center><a href='http://jboot.io' target='_blank'><b>Powered by Jboot</b></a></center>"; 040 041 protected static final String html404 = "<html><head><title>404 Not Found</title></head><body bgcolor='white'><center><h1>404 Not Found</h1></center><hr>" + poweredBy + "</body></html>"; 042 protected static final String html401 = "<html><head><title>401 Unauthorized</title></head><body bgcolor='white'><center><h1>401 Unauthorized</h1></center><hr>" + poweredBy + "</body></html>"; 043 protected static final String html403 = "<html><head><title>403 Forbidden</title></head><body bgcolor='white'><center><h1>403 Forbidden</h1></center><hr>" + poweredBy + "</body></html>"; 044 045 protected static final String html500_header = "<html><head><title>500 Internal Server Error</title></head>" + 046 "<body bgcolor='white'><center><h1>500 Internal Server Error</h1></center>" + 047 "<hr>"; 048 protected static final String html400_header = "<html><head><title>400 Internal Server Error</title></head>" + 049 "<body bgcolor='white'><center><h1>400 Internal Server Error</h1></center>" + 050 "<hr>"; 051 052 protected static final String html500_footer = "<hr>" + poweredBy + "</body></html>"; 053 054 055 protected static final String json401 = JsonKit.toJson(Ret.fail().set("errorCode", 401).set("message", "401 Unauthorized")); 056 protected static final String json403 = JsonKit.toJson(Ret.fail().set("errorCode", 403).set("message", "403 Forbidden")); 057 protected static final String json404 = JsonKit.toJson(Ret.fail().set("errorCode", 404).set("message", "404 Not Found")); 058 059 060 protected int errorCode; 061 protected String message; 062 protected Throwable throwable; 063 064 public int getErrorCode() { 065 return errorCode; 066 } 067 068 public void setErrorCode(int errorCode) { 069 this.errorCode = errorCode; 070 } 071 072 public String getMessage() { 073 return message; 074 } 075 076 public void setMessage(String message) { 077 this.message = message; 078 } 079 080 public Throwable getThrowable() { 081 return throwable; 082 } 083 084 public void setThrowable(Throwable throwable) { 085 this.throwable = throwable; 086 } 087 088 public JbootErrorRender(int errorCode, String view) { 089 this.errorCode = errorCode; 090 this.view = view; 091 } 092 093 @Override 094 public void render() { 095 response.setStatus(getErrorCode()); 096 097 //render with view 098 String view = getView(); 099 if (view != null) { 100 RenderManager.me().getRenderFactory() 101 .getRender(view) 102 .setContext(request, response) 103 .render(); 104 return; 105 } 106 107 try { 108 boolean needRenderJson = RequestUtil.isJsonContentType(request) || RequestUtil.isAjaxRequest(request); 109 response.setContentType(needRenderJson ? jsonContentType : htmlContentType); 110 PrintWriter writer = response.getWriter(); 111 writer.write(needRenderJson ? getErrorJson() : getErrorHtml()); 112 } catch (Exception ex) { 113 throw new RenderException(ex); 114 } 115 116 } 117 118 119 public String getErrorHtml() { 120 int errorCode = getErrorCode(); 121 if (throwable instanceof ValidException) { 122 return buildErrorInfo(html400_header); 123 } else if (errorCode == 404) { 124 return html404; 125 } else if (errorCode == 401) { 126 return html401; 127 } else if (errorCode == 403) { 128 return html403; 129 } else if (errorCode == 400) { 130 return buildErrorInfo(html400_header); 131 } else if (errorCode == 500) { 132 return buildErrorInfo(html500_header); 133 } 134 return "<html><head><title>" + errorCode + " Error</title></head><body bgcolor='white'><center><h1>" + errorCode + " Error</h1></center><hr>" + poweredBy + "</body></html>"; 135 } 136 137 138 public String buildErrorInfo(String headerHtml) { 139 StringBuilder stringBuilder = new StringBuilder(headerHtml); 140 141 List<String> messages = JbootExceptionHolder.getMessages(); 142 for (String message : messages) { 143 stringBuilder.append(message).append("<br />"); 144 } 145 146 List<Throwable> throwables = JbootExceptionHolder.getThrowables(); 147 for (Throwable throwable : throwables) { 148 stringBuilder.append(throwable.getClass().getName() + " : " + throwable.getMessage()).append("<br />"); 149 StackTraceElement[] elems = throwable.getStackTrace(); 150 for (StackTraceElement element : elems) { 151 stringBuilder.append(" at ") 152 .append(element) 153 .append("<br />"); 154 } 155 } 156 157 return stringBuilder.append(html500_footer).toString(); 158 } 159 160 161 public String getErrorJson() { 162 int errorCode = getErrorCode(); 163 if (throwable instanceof ValidException || errorCode == 500 || errorCode == 400) { 164 return buildErrorJson(); 165 } else if (errorCode == 404) { 166 return json404; 167 } else if (errorCode == 401) { 168 return json401; 169 } else if (errorCode == 403) { 170 return json403; 171 } 172 return JsonKit.toJson(Ret.fail().set("errorCode", errorCode).set("message", errorCode + " Error")); 173 } 174 175 176 public String buildErrorJson() { 177 178 Ret ret = Ret.fail().set("errorCode", getErrorCode()).set("message", getErrorCode() + " Internal Server Error"); 179 180 StringBuilder errorMsgBuilder = new StringBuilder(); 181 List<String> messages = JbootExceptionHolder.getMessages(); 182 for (String message : messages) { 183 errorMsgBuilder.append(message); 184 } 185 186 ret.set("errorMessage", errorMsgBuilder.toString()); 187 188 List<Throwable> throwables = JbootExceptionHolder.getThrowables(); 189 if (throwables.size() > 0) { 190 Throwable throwable = throwables.get(0); 191 ret.set("throwable", throwable.getClass().getName() + ": " + throwable.getMessage()); 192 ret.set("message", throwable.getMessage()); 193 } 194 195 if (this.throwable != null) { 196 ret.set("throwable", this.throwable.getClass().getName() + ": " + this.throwable.getMessage()); 197 ret.set("message", throwable.getMessage()); 198 199 if (throwable instanceof ValidException) { 200 ret.set("errorMessage", ((ValidException) throwable).getReason()); 201 } 202 } 203 204 if (StrUtil.isNotBlank(this.message)) { 205 ret.set("message", this.message); 206 } 207 208 return JsonKit.toJson(ret); 209 } 210} 211 212 213 214 215