PageRenderTime 51ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/app/com/baasbox/controllers/actions/filters/WrapResponse.java

https://gitlab.com/mkgobaco/baasbox
Java | 208 lines | 152 code | 35 blank | 21 comment | 25 complexity | 346b597ae590f4c27eaff4d02744d41b MD5 | raw file
  1. /*
  2. Copyright 2012-2013
  3. Claudio Tesoriero - c.tesoriero-at-baasbox.com
  4. Licensed under the Apache License, Version 2.0 (the "License");
  5. you may not use this file except in compliance with the License.
  6. You may obtain a copy of the License at
  7. http://www.apache.org/licenses/LICENSE-2.0
  8. Unless required by applicable law or agreed to in writing, software
  9. distributed under the License is distributed on an "AS IS" BASIS,
  10. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. See the License for the specific language governing permissions and
  12. limitations under the License.
  13. */
  14. package com.baasbox.controllers.actions.filters;
  15. import java.io.IOException;
  16. import org.apache.commons.lang.StringUtils;
  17. import com.fasterxml.jackson.core.JsonProcessingException;
  18. import com.fasterxml.jackson.databind.JsonNode;
  19. import com.fasterxml.jackson.databind.ObjectMapper;
  20. import com.fasterxml.jackson.databind.node.ObjectNode;
  21. import play.Logger;
  22. import play.api.mvc.ChunkedResult;
  23. import play.core.j.JavaResultExtractor;
  24. import play.libs.Json;
  25. import play.mvc.Http.Context;
  26. import play.mvc.Http.RequestHeader;
  27. import play.mvc.Result;
  28. import play.mvc.Results;
  29. import com.baasbox.BBConfiguration;
  30. import com.baasbox.controllers.CustomHttpCode;
  31. import play.mvc.SimpleResult;
  32. import play.libs.F;
  33. public class WrapResponse {
  34. private ObjectNode prepareError(RequestHeader request, String error) {
  35. com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper();
  36. ObjectNode result = Json.newObject();
  37. result.put("result", "error");
  38. result.put("message", error);
  39. result.put("resource", request.path());
  40. result.put("method", request.method());
  41. result.put("request_header", (JsonNode)mapper.valueToTree(request.headers()));
  42. result.put("API_version", BBConfiguration.configuration.getString(BBConfiguration.API_VERSION));
  43. setCallIdOnResult(request, result);
  44. return result;
  45. }
  46. private SimpleResult onCustomCode(int statusCode, RequestHeader request, String data) throws IOException {
  47. CustomHttpCode customCode = CustomHttpCode.getFromBbCode(statusCode);
  48. ObjectNode result=null;
  49. if (customCode.getType().equals("error")){
  50. result = prepareError(request, data);
  51. }else{
  52. result= prepareOK(statusCode, request, data);
  53. }
  54. result.put("http_code", customCode.getHttpCode());
  55. result.put("bb_code", String.valueOf(customCode.getBbCode()));
  56. return Results.status(customCode.getHttpCode(), result);
  57. }
  58. private SimpleResult onUnauthorized(RequestHeader request, String error) {
  59. ObjectNode result = prepareError(request, error);
  60. result.put("http_code", 401);
  61. return Results.unauthorized(result);
  62. }
  63. private SimpleResult onForbidden(RequestHeader request, String error) {
  64. ObjectNode result = prepareError(request, error);
  65. result.put("http_code", 403);
  66. return Results.forbidden(result);
  67. }
  68. private SimpleResult onBadRequest(RequestHeader request, String error) {
  69. ObjectNode result = prepareError(request, error);
  70. return Results.badRequest(result);
  71. }
  72. private SimpleResult onResourceNotFound(RequestHeader request,String error) {
  73. ObjectNode result = prepareError(request, error);
  74. result.put("http_code", 404);
  75. return Results.notFound(result);
  76. }
  77. private SimpleResult onDefaultError(int statusCode,RequestHeader request,String error) {
  78. ObjectNode result = prepareError(request, error);
  79. result.put("http_code", statusCode);
  80. return Results.status(statusCode,result);
  81. }
  82. private ObjectNode prepareOK(int statusCode,RequestHeader request, String stringBody) throws IOException{
  83. ObjectMapper mapper = new ObjectMapper();
  84. ObjectNode result = Json.newObject();
  85. setCallIdOnResult(request, result);
  86. result.put("result", "ok");
  87. try {
  88. result.put("data", mapper.readTree(stringBody));
  89. } catch (JsonProcessingException e) {
  90. result.put("data", stringBody);
  91. } catch (IOException e) {
  92. if (stringBody.isEmpty()) result.put("data", "");
  93. else throw new IOException("Error parsing stringBody: " + stringBody,e);
  94. }
  95. return result;
  96. }
  97. /**
  98. * @param request
  99. * @param result
  100. */
  101. private void setCallIdOnResult(RequestHeader request, ObjectNode result) {
  102. String callId = request.getQueryString("call_id");
  103. if (!StringUtils.isEmpty(callId)) result.put("call_id",callId);
  104. }
  105. private SimpleResult onOk(int statusCode,RequestHeader request, String stringBody) throws IOException {
  106. ObjectNode result = prepareOK(statusCode, request, stringBody);
  107. result.put("http_code", statusCode);
  108. return Results.status(statusCode,result);
  109. }
  110. public SimpleResult wrap(Context ctx, F.Promise<SimpleResult> simpleResult) throws Throwable {
  111. if (Logger.isTraceEnabled()) Logger.trace("Method Start");
  112. SimpleResult result=simpleResult.get(10000);
  113. ctx.response().setHeader("Access-Control-Allow-Origin", "*");
  114. ctx.response().setHeader("Access-Control-Allow-Headers", "X-Requested-With");
  115. //this is an hack because scala can't access to the http context, and we need this information for the access log
  116. String username=(String) ctx.args.get("username");
  117. if (username!=null) ctx.response().setHeader("BB-USERNAME", username);
  118. byte[] resultContent=null;
  119. if (BBConfiguration.getWrapResponse()){
  120. if (Logger.isDebugEnabled()) Logger.debug("Wrapping the response");
  121. final int statusCode = result.getWrappedSimpleResult().header().status();
  122. if (Logger.isDebugEnabled()) Logger.debug("Executed API: " + ctx.request() + " , return code " + statusCode);
  123. if (Logger.isDebugEnabled()) Logger.debug("Result type:"+result.getWrappedResult().getClass().getName() + " Response Content-Type:" +ctx.response().getHeaders().get("Content-Type"));
  124. if (ctx.response().getHeaders().get("Content-Type")!=null
  125. &&
  126. !ctx.response().getHeaders().get("Content-Type").contains("json")){
  127. if (Logger.isDebugEnabled()) Logger.debug("The response is a file, no wrap will be applied");
  128. return result;
  129. }
  130. if(result.getWrappedResult() instanceof ChunkedResult<?>){
  131. return result;
  132. }
  133. final byte[] body = JavaResultExtractor.getBody(result);
  134. String stringBody = new String(body, "UTF-8");
  135. if (Logger.isTraceEnabled()) if (Logger.isTraceEnabled()) Logger.trace ("stringBody: " +stringBody);
  136. if (statusCode>399){ //an error has occured
  137. switch (statusCode) {
  138. case 400: result =onBadRequest(ctx.request(),stringBody);
  139. break;
  140. case 401: result =onUnauthorized(ctx.request(),stringBody);
  141. break;
  142. case 403: result =onForbidden(ctx.request(),stringBody);
  143. break;
  144. case 404: result =onResourceNotFound(ctx.request(),stringBody);
  145. break;
  146. default:
  147. if (CustomHttpCode.getFromBbCode(statusCode)!=null){
  148. result = onCustomCode(statusCode,ctx.request(),stringBody);
  149. }else result =onDefaultError(statusCode,ctx.request(),stringBody);
  150. break;
  151. }
  152. }else{ //status is not an error
  153. result=onOk(statusCode,ctx.request(),stringBody);
  154. } //if (statusCode>399)
  155. if (statusCode==204) result = Results.noContent();
  156. try {
  157. if (Logger.isDebugEnabled()) Logger.debug("WrapperResponse:\n + result: \n" + result.toString() + "\n --> Body:\n" + new String(JavaResultExtractor.getBody(result),"UTF-8"));
  158. }catch (Throwable e){}
  159. }else{ //if (BBConfiguration.getWrapResponse())
  160. if (Logger.isDebugEnabled()) Logger.debug("The response will not be wrapped due configuration parameter");
  161. try {
  162. if (Logger.isDebugEnabled()) Logger.debug("WrapperResponse:\n + result: \n" + result.toString() + "\n --> Body:\n" + new String(JavaResultExtractor.getBody(result),"UTF-8"));
  163. }catch (Throwable e){}
  164. if (Logger.isDebugEnabled()) Logger.debug("WrapperResponse:\n + result: \n" + result.toString() + "\n --> Body:\n" + new String(JavaResultExtractor.getBody(result),"UTF-8"));
  165. }
  166. ctx.response().setHeader("Content-Length", Long.toString(JavaResultExtractor.getBody(result).length));
  167. if (Logger.isTraceEnabled()) Logger.trace("Method End");
  168. return result;
  169. }//wrap
  170. }