Example #1
0
 /// <summary>
 /// Manages the actual write to the HttpListenerContext Response.
 /// </summary>
 /// <param name="ctx">HttpListenerContext object.</param>
 /// <param name="response">Response to write to the output.</param>
 private static void WriteToOutput(HttpListenerContext ctx, RestfulResponse response)
 {
     if (response != null) {
         ctx.Response.StatusCode = (int)response.StatusCode;
         // Propagate the headers back in the response.
         if (response.Headers != null) {
             foreach (var header in response.Headers) {
                 ctx.Response.Headers.Add(header.Key, header.Value);
             }
         }
         var responseString = response.Body;
         if (!string.IsNullOrEmpty(responseString)) {
             var buf = Encoding.UTF8.GetBytes(responseString);
             ctx.Response.ContentLength64 = buf.Length;
             ctx.Response.OutputStream.Write(buf, 0, buf.Length);
         }
     }
 }
        /// <summary>
        /// This is where the good stuff happens.   Incoming requests are Resolved using the
        /// EndPointGroup.   This is where there is room for potential optimizations; there are
        /// two reflection calls happening at runtime for each request.  
        /// 1)  An instantiation of the BaseModule - this is because each BaseModule has a 
        /// responseHeaders dictionary that cannot be shared.  Obviously, some scheme that 
        /// avoids reflection can be devised.
        /// 2) The actual invocation of the MethodInfo.   
        /// </summary>
        /// <param name="request">An IRequest object encapsulating the request.</param>
        /// <returns>A RestfulResponse object that can be serialized and written to the
        /// response.</returns>
        public RestfulResponse ResolveRequest(IRequest request)
        {
            SidModule moduleInstance = null;
            try {
                // Resolve the endpoint the request is for.
                Regex pathRegex;
                var endPoint = ResolveEndPoint(request, out pathRegex);

                // Instantiate the module.
                moduleInstance = Activator.CreateInstance(endPoint.ModuleType) as SidModule;
                moduleInstance.RestfulRequest = request;
                request.Match = GetPathRegexMatch(request, endPoint, pathRegex);

                // Determine if it's an OPTIONS request or not.
                var optionsRequest = request.HttpMethod == HttpMethod.Options;

                // Create CORS-specific headers if appropriate, or throw Forbidden exception.
                DoCORSHandling(request, moduleInstance.ResponseHeaders, endPoint,
                    optionsRequest);

                // Get the arguments and execute the method.
                var args = GetArguments(request, endPoint, moduleInstance);
                var ret = endPoint.MethodInfo.Invoke(moduleInstance, args);

                // Create the Access-Control-Expose-Headers header, if the endpoint added any
                // response headers.
                CopyResponseHeadersToAccessControlExposeHeadersKey(optionsRequest,
                        moduleInstance.ResponseHeaders);

                // Serialize the return value.
                var json = ret != null ? JsonConvert.SerializeObject(ret) : null;

                // Construct a RestfulResponse object from the return value.
                var successResponse = new RestfulResponse {
                    StatusCode = HttpStatusCode.OK,
                    Body = json,
                    Headers = moduleInstance.ResponseHeaders,
                };

                return successResponse;
            } catch (Exception ex) {
                return HandleDispatchException(ex, moduleInstance);
            }
        }
Example #3
0
        /// <summary>
        /// This shouldn't get hit; RestfulMethodDispatcher.ResolveResponse is supposed to 
        /// catch errors, but if something slips through, this is a stopgap.
        /// This is equivalent to the Nancy 'Oh Noes!....page'.
        /// </summary>
        /// <param name="ex"></param>
        /// <param name="ctx"></param>
        private static void HandleDispatchException(Exception ex, HttpListenerContext ctx)
        {
            var errMsg = string.Format("RestfulMethodDispatcher incorrectly threw an untrapped"
                + " error = {0}, request = {1} stack = {2}",
                ex.Message, ctx.Request.RawUrl, ex.StackTrace);

            log.Error(errMsg);

            var error = new RestfulResponse{
                StatusCode = HttpStatusCode.InternalServerError,
                Body = errMsg,
            };
            WriteToOutput(ctx, error);
        }