/// <summary> /// Writes the given API response to the given HTTP context's response. /// </summary> /// <param name="context">The HTTP context whose response should be written to.</param> /// <param name="request">The de-serialized API request that generated the current response. May be null.</param> /// <param name="response">The API response to write.</param> /// <param name="knownTypes">A collection of known types that may exist in the response object graph.</param> public virtual void WriteResponse(HttpContextBase context, ApiRequest request, ApiResponse response, IEnumerable<Type> knownTypes) { string json = response.ToJson(knownTypes); json = Regex.Replace(json, "({)?(,)?\"__type\":\".*?\"(})?(,)?", new MatchEvaluator(TypeIdentifiersEvaluator)); if (context.AcceptsGZip() && request != null && request.GetType().GetCustomAttributes(typeof(GZipAttribute), true).Length > 0) { context.Response.Filter = new GZipStream(context.Response.Filter, CompressionMode.Compress); context.Response.AddHeader("content-encoding", "gzip"); } context.Response.ContentType = "application/json"; context.Response.Write(json); }
/// <summary> /// Reads a request from the given HTTP context into the given concrete type. /// </summary> /// <param name="context">The HTTP context to read the request from.</param> /// <param name="requestType">The concrete request type to de-serialize.</param> /// <param name="response">The API response to modify of something goes wrong.</param> /// <returns>An <see cref="ApiRequest"/>.</returns> public virtual ApiRequest ReadRequest(HttpContextBase context, Type requestType, ApiResponse response) { ApiRequest request = null; if (context.Request.InputStream != null && context.Request.InputStream.Length > 0) { request = (ApiRequest)new DataContractBinaryPlistSerializer(requestType).ReadObject(context.Request.InputStream); } else { request = (ApiRequest)Activator.CreateInstance(requestType); } return request; }
public virtual void ProcessRequest(HttpContextBase context) { ApiRequest request = null; MatchedRoute route = null; ApiResponse response = new ApiResponse(); Type[] knownTypes = new Type[0]; if (RequestPassesSslCheck(context)) { try { route = this.GetRequestRoute(context); request = this.GetRequestReader(context, route, readers).ReadRequest(context, route.RouteType, response); // Permitted? IPermission failedOn; if (context.EnsurePermitted(route.RouteType, out failedOn)) { knownTypes = route.RouteType.GetCustomAttributes(typeof(KnownTypeAttribute), true) .Cast<KnownTypeAttribute>() .Select(a => a.Type) .ToArray(); ApiResult valid = request.Validate(); if (valid.Success) { // Do it. ApiActionResult result = request.Do(); response.Success = result.Success; response.Reason = result.Reason; response.Value = result.Value; } else { response.Success = false; response.Reason = valid.Reason; } } else { response.Success = false; response.Reason = "Access denied."; response.Allowed = false; response.StatusCode = 401; } } catch (InvalidRequestTypeException ex) { response.Success = false; response.Reason = ex.Message; response.StatusCode = 400; } catch (Exception ex) { response.Success = false; response.StatusCode = 500; if (context.Request.IsLocal) { response.Reason = String.Concat(ex.Message, "\n", ex.StackTrace); } else { response.Reason = "An internal server error occurred while processing your request."; } } } else { response.Success = false; response.Reason = "A secure connection is required when making this request."; response.StatusCode = 403; } string id = context.Request.Headers["X-Request-Id"]; id = !String.IsNullOrEmpty(id) ? id : "0"; context.Response.AppendHeader("X-Response-Id", id); context.Response.StatusCode = response.StatusCode; this.GetResponseWriter(context, route, writers).WriteResponse(context, request, response, knownTypes); }
/// <summary> /// Writes the given API response to the given HTTP context's response. /// </summary> /// <param name="context">The HTTP context whose response should be written to.</param> /// <param name="request">The de-serialized API request that generated the current response. May be null.</param> /// <param name="response">The API response to write.</param> /// <param name="knownTypes">A collection of known types that may exist in the response object graph.</param> public virtual void WriteResponse(HttpContextBase context, ApiRequest request, ApiResponse response, IEnumerable<Type> knownTypes) { context.Response.ContentType = "application/x-bplist"; new DataContractBinaryPlistSerializer(response.GetType()).WriteObject(context.Response.OutputStream, response); }