Exemplo n.º 1
0
        public void UnsupportedHttpMethodReturnsMethodNotAllowed()
        {
            A.CallTo(() => this.request.HttpMethod).Returns(HttpMethod.Get);

            ISydneyResponse response =
                this.handler.HandleRequestAsync(
                    this.request,
                    this.logger,
                    false).Result;

            Assert.Equal(HttpStatusCode.MethodNotAllowed, response.StatusCode);
        }
Exemplo n.º 2
0
        public void UnexpectedExceptionFromHandlerMethodReturnsInternalServerError()
        {
            A.CallTo(this.handler)
            .Where(call => call.Method.Name == "GetAsync")
            .Throws(new InvalidOperationException());
            A.CallTo(() => this.request.HttpMethod).Returns(HttpMethod.Get);

            ISydneyResponse response =
                this.handler.HandleRequestAsync(
                    this.request,
                    this.logger,
                    false).Result;

            Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
        }
Exemplo n.º 3
0
        public void HttpResponseExceptionFromHandlerMethodReturnsSpecifiedStatusCode()
        {
            A.CallTo(this.handler)
            .Where(call => call.Method.Name == "GetAsync")
            .Throws(new HttpResponseException(HttpStatusCode.EarlyHints));
            A.CallTo(() => this.request.HttpMethod).Returns(HttpMethod.Get);

            ISydneyResponse response =
                this.handler.HandleRequestAsync(
                    this.request,
                    this.logger,
                    false).Result;

            Assert.Equal(HttpStatusCode.EarlyHints, response.StatusCode);
        }
Exemplo n.º 4
0
        public void ExceptionMessageIsReturnedInPayloadWhenReturnExceptionMessagesInResponseIsTrue()
        {
            string expectedExceptionMessage = "Here's an exception!";

            A.CallTo(this.handler)
            .Where(call => call.Method.Name == "GetAsync")
            .Throws(new InvalidOperationException(expectedExceptionMessage));
            A.CallTo(() => this.request.HttpMethod).Returns(HttpMethod.Get);

            ISydneyResponse response =
                this.handler.HandleRequestAsync(
                    this.request,
                    this.logger,
                    true).Result;

            Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
            Assert.Equal(expectedExceptionMessage, response.Payload);
        }
Exemplo n.º 5
0
        public void HttpMethodMapsToCorrectHandlerMethodAsync(HttpMethod httpMethod, string handlerMethodName)
        {
            A.CallTo(this.handler)
            .Where(call => call.Method.Name == handlerMethodName)
            .WithReturnType <Task <ISydneyResponse> >()
            .Returns(Task.FromResult <ISydneyResponse>(new SydneyResponse(HttpStatusCode.Ambiguous)));
            A.CallTo(() => this.request.HttpMethod).Returns(httpMethod);

            ISydneyResponse response =
                this.handler.HandleRequestAsync(
                    this.request,
                    this.logger,
                    false).Result;

            Assert.Equal(HttpStatusCode.Ambiguous, response.StatusCode);
            A.CallTo(this.handler)
            .Where(call => call.Method.Name == handlerMethodName)
            .MustHaveHappenedOnceExactly();
        }
Exemplo n.º 6
0
        internal async Task <ISydneyResponse> HandleRequestAsync(ISydneyRequest request, ILogger logger, bool returnExceptionMessagesInResponse)
        {
            Stopwatch stopwatch = Stopwatch.StartNew();

            try
            {
                ISydneyResponse response = null;
                switch (request.HttpMethod)
                {
                case HttpMethod.Get:
                    response = await this.GetAsync(request);

                    break;

                case HttpMethod.Post:
                    response = await this.PostAsync(request);

                    break;

                case HttpMethod.Delete:
                    response = await this.DeleteAsync(request);

                    break;

                case HttpMethod.Put:
                    response = await this.PutAsync(request);

                    break;

                case HttpMethod.Head:
                    response = await this.HeadAsync(request);

                    break;

                case HttpMethod.Patch:
                    response = await this.PatchAsync(request);

                    break;

                case HttpMethod.Options:
                    response = await this.OptionsAsync(request);

                    break;

                default:
                    throw new NotImplementedException();
                }

                logger.LogInformation($"Request completed after {stopwatch.Elapsed}, status code: {response.StatusCode}.");

                return(response);
            }
            catch (Exception exception)
            {
                HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
                switch (exception)
                {
                case HttpResponseException hre:
                    logger.LogWarning(
                        hre,
                        $"Request failed after {stopwatch.Elapsed}, status code: {hre.StatusCode}, exception: {hre}");
                    statusCode = hre.StatusCode;
                    break;

                case NotImplementedException nie:
                    logger.LogWarning(
                        nie,
                        $"Request made for unsupported HTTP method {request.HttpMethod}.");
                    statusCode = HttpStatusCode.MethodNotAllowed;
                    break;

                default:
                    logger.LogError(
                        exception,
                        $"Unexpected exception processing request after {stopwatch.Elapsed}, exception: {exception}");
                    break;
                }

                return
                    (new SydneyResponse(
                         statusCode,
                         returnExceptionMessagesInResponse ? exception.Message : null));
            }
        }
Exemplo n.º 7
0
        internal async Task HandleContextAsync(HttpListenerContext context)
        {
            try
            {
                // Try to match the incoming URL to a handler.
                if (!this.router.TryMatchPath(context.Request.Url.AbsolutePath, out RouteMatch match))
                {
                    this.logger.LogWarning($"No matching handler found for incoming request url: {context.Request.Url}.");

                    // If we couldn't, return a 404.
                    context.Response.StatusCode = (int)HttpStatusCode.NotFound;
                    context.Response.Close();

                    return;
                }

                // Create and handle the request.
                ISydneyRequest  request  = new SydneyRequest(context.Request, match.PathParameters);
                ISydneyResponse response =
                    await match.Handler.HandleRequestAsync(
                        request,
                        this.logger,
                        this.config.ReturnExceptionMessagesInResponse);

                // Write the response to context.Response.
                context.Response.StatusCode = (int)response.StatusCode;
                context.Response.KeepAlive  = response.KeepAlive;
                foreach (KeyValuePair <string, string> header in response.Headers)
                {
                    context.Response.AddHeader(header.Key, header.Value);
                }

                if (response.Payload != null)
                {
                    context.Response.ContentType = MediaTypeNames.Application.Json;

                    // We have to serialize to a memory stream first in order to get the content length
                    // because the output stream does not support the property. It seems good to initialize the
                    // stream with a buffer size. 512 bytes was randomly chosen as a decent medium size for now.
                    using (var memoryStream = new MemoryStream(DefaultBufferSize))
                    {
                        await JsonSerializer.SerializeAsync(memoryStream, response.Payload);

                        context.Response.ContentLength64 = memoryStream.Length;

                        // Stream.CopyToAsync starts from the current position so seek to the beginning.
                        memoryStream.Seek(0, SeekOrigin.Begin);
                        await memoryStream.CopyToAsync(context.Response.OutputStream);
                    }
                }
                else
                {
                    context.Response.ContentLength64 = 0;
                }

                // Close the response to send it back to the client.
                context.Response.Close();
            }
            catch (Exception exception)
            {
                this.logger.LogError(
                    exception,
                    $"Unexpected exception handling context, exception: {exception}");

                // Forcefully end the connection.
                context.Response.Abort();
            }
        }