package ddth.dasp.hetty.message.protobuf; import java.io.ByteArrayOutputStream; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Map; import java.util.Map.Entry; import java.util.TimeZone; import org.apache.commons.lang3.ArrayUtils; import ddth.dasp.hetty.HettyConstants; import ddth.dasp.hetty.message.ICookie; import ddth.dasp.hetty.message.IRequest; import ddth.dasp.hetty.message.IResponse; import ddth.dasp.hetty.utils.HettyUtils; /** * Response generator utility class. * * @author Thanh Ba Nguyen <btnguyen2k@gmail.com> */ public class ResponseUtils { public final static String HEADER_CONTENT_TYPE = "Content-Type";; public final static DateFormat DF_HEADER = new SimpleDateFormat("E, d MMM yyyy HH:mm:ss z"); static { DF_HEADER.setTimeZone(TimeZone.getTimeZone("GMT")); } private final static byte[] EMPTY_CONTENT = ArrayUtils.EMPTY_BYTE_ARRAY; /** * Helper method to create a "text/html; charset=utf-8"-200 response, * without cookies or any specific headers. * * @param request * @param contentString * @return */ public static IResponse response200(IRequest request, String contentString) { return response200(request, contentString, "text/html; charset=utf-8"); } /** * Helper method to create a "text/html; charset=utf-8"-200 response, * without cookies or any specific headers. * * @param request * @param contentBin * @return */ public static IResponse response200(IRequest request, byte[] contentBin) { return response200(request, contentBin, "text/html; charset=utf-8"); } /** * Helper method to create a 200 response with specified content type, * without cookies or any specific headers. * * @param request * @param contentString * @param contentType * @return */ public static IResponse response200(IRequest request, String contentString, String contentType) { return response200(request, contentString, contentType, null, null); } /** * Helper method to create a 200 response with specified content type, * cookies and headers. * * @param request * @param contentString * @param contentType * @param headers * @param cookies * @return */ public static IResponse response200(IRequest request, String contentString, String contentType, Map<String, String> headers, ICookie[] cookies) { IResponse response = newResponse(request).setStatus(200); response.addHeader(HEADER_CONTENT_TYPE, contentType); response.setContent(contentString); // headers if (headers != null) { for (Entry<String, String> header : headers.entrySet()) { response.addHeader(header.getKey(), header.getValue()); } } // cookies if (cookies != null) { for (ICookie cookie : cookies) { response.addCookie(cookie); } } return response; } /** * Helper method to create a 200 response with specified content type, * without cookies or any specific headers. * * @param request * @param contentBin * @param contentType * @return */ public static IResponse response200(IRequest request, byte[] contentBin, String contentType) { return response200(request, contentBin, contentType, null, null); } /** * Helper method to create a 200 response with specified content type, * cookies and headers. * * @param request * @param contentBin * @param contentType * @param headers * @param cookies * @return */ public static IResponse response200(IRequest request, byte[] contentBin, String contentType, Map<String, String> headers, ICookie[] cookies) { IResponse response = newResponse(request).setStatus(200); response.addHeader(HEADER_CONTENT_TYPE, contentType); response.setContent(contentBin); // headers if (headers != null) { for (Entry<String, String> header : headers.entrySet()) { response.addHeader(header.getKey(), header.getValue()); } } // cookies if (cookies != null) { for (ICookie cookie : cookies) { response.addCookie(cookie); } } return response; } /** * Helper method to create a 301 response. * * @param request * @param url * @return */ public static IResponse response301(IRequest request, String url) { IResponse response = newResponse(request).setStatus(301).addHeader("Location", url); return response; } /** * Helper method to create a 304 response. * * @param request * @return */ public static IResponse response304(IRequest request) { IResponse response = newResponse(request).setStatus(304); return response; } /** * Helper method to create a 404 response. * * @param request * @return */ public static IResponse response404(IRequest request) { return response404(request, "Not found"); } /** * Helper method to create a 404 response. * * @param request * @param message * @return */ public static IResponse response404(IRequest request, String message) { String content = HettyUtils.loadContentInClasspath("/ddth/dasp/hetty/404.tpl"); String referer = request.getHeader("Referer"); String htmlContent = content.replace("${referer}", referer != null ? referer : "").replace( "${message}", message != null ? message : ""); IResponse response = newResponse(request).setStatus(404) .addHeader(HEADER_CONTENT_TYPE, "text/html; charset=UTF-8").setContent(htmlContent); return response; } /** * Helper method to create a 403 response. * * @param request * @return */ public static IResponse response403(IRequest request) { return response403(request, "Access denied"); } /** * Helper method to create a 403 response. * * @param request * @param message * @return */ public static IResponse response403(IRequest request, String message) { String content = HettyUtils.loadContentInClasspath("/ddth/dasp/hetty/403.tpl"); String referer = request.getHeader("Referer"); String htmlContent = content.replace("${referer}", referer != null ? referer : "").replace( "${message}", message != null ? message : ""); IResponse response = newResponse(request).setStatus(403) .addHeader(HEADER_CONTENT_TYPE, "text/html; charset=UTF-8").setContent(htmlContent); return response; } /** * Helper method to create a 500 response. * * @param request * @return */ public static IResponse response500(IRequest request) { return response500(request, null, null); } /** * Helper method to create a 500 response. * * @param request * @param message * @return */ public static IResponse response500(IRequest request, String message) { return response500(request, message, null); } /** * Helper method to create a 500 response. * * @param request * @param message * @param t * @return */ public static IResponse response500(IRequest request, String message, Throwable t) { String content = HettyUtils.loadContentInClasspath("/ddth/dasp/hetty/500.tpl"); String referer = request.getHeader("Referer"); if (message == null && t != null) { message = t.getMessage(); } StringBuilder exception = null; if (t != null) { exception = new StringBuilder("<h5 class=\"alert-heading\">Stacktrace:</h5>"); ByteArrayOutputStream baos = new ByteArrayOutputStream(); PrintWriter writer = new PrintWriter(baos); writer.print("<pre>"); t.printStackTrace(writer); writer.print("</pre>"); writer.println("<p> </p>"); Throwable cause = t.getCause(); while (cause != null) { writer.println("<h6 class=\"alert-heading\">Cause:</h6>"); writer.println("<pre>"); cause.printStackTrace(writer); writer.println("</pre>"); cause = cause.getCause(); } writer.flush(); try { exception.append(baos.toString("utf-8")); } catch (UnsupportedEncodingException e) { } } String htmlContent = content.replace("${referer}", referer != null ? referer : "") .replace("${message}", message != null ? message : "") .replace("${exception}", exception != null ? exception.toString() : ""); IResponse response = newResponse(request).setStatus(500) .addHeader(HEADER_CONTENT_TYPE, "text/html; charset=UTF-8").setContent(htmlContent); return response; } /** * Helper method to create a 503 response. * * @param request * @return */ public static IResponse response503(IRequest request) { return response503(request, null); } /** * Helper method to create a 503 response. * * @param request * @param message * @return */ public static IResponse response503(IRequest request, String message) { String content = HettyUtils.loadContentInClasspath("/ddth/dasp/hetty/503.tpl"); String referer = request.getHeader("Referer"); String htmlContent = content.replace("${referer}", referer != null ? referer : "").replace( "${message}", message != null ? message : ""); IResponse response = newResponse(request).setStatus(500) .addHeader(HEADER_CONTENT_TYPE, "text/html; charset=UTF-8").setContent(htmlContent); return response; } /** * Helper method to create a 504 response. * * @param request * @return */ public static IResponse response504(IRequest request) { return response504(request, null); } /** * Helper method to create a 504 response. * * @param request * @param message * @return */ public static IResponse response504(IRequest request, String message) { String content = HettyUtils.loadContentInClasspath("/ddth/dasp/hetty/504.tpl"); String referer = request.getHeader("Referer"); String htmlContent = content.replace("${referer}", referer != null ? referer : "").replace( "${message}", message != null ? message : ""); IResponse response = newResponse(request).setStatus(500) .addHeader(HEADER_CONTENT_TYPE, "text/html; charset=UTF-8").setContent(htmlContent); return response; } /** * Helper method to create a new empty response. * * The newly created response will have status of 200, and 2 headers * "Server" and "Date" added. * * @param request * @return */ public static IResponse newResponse(IRequest request) { HettyProtoBuf.Response.Builder responseBuilder = HettyProtoBuf.Response.newBuilder() .setRequestId(request.getId()).setRequestTimestampNano(request.getTimestampNano()) .setChannelId(request.getChannelId()).setStatus(200); // .addHeaders(newHeader("Server", SERVER)).setContent(EMPTY_CONTENT) // .addHeaders(newHeader("Date", new Date())); IResponse response = new ProtoBufResponse(responseBuilder) .addHeader("Server", HettyConstants.SERVER_SIGNATURE).addHeader("Date", new Date()) .setContent(EMPTY_CONTENT); return response; } }