Ejemplo n.º 1
0
        public async Task PostMultiGet()
        {
            using (ContextPool.AllocateOperationContext(out JsonOperationContext context))
            {
                var input = await context.ReadForMemoryAsync(RequestBodyStream(), "multi_get");

                if (input.TryGet("Requests", out BlittableJsonReaderArray requests) == false)
                {
                    ThrowRequiredPropertyNameInRequest("Requests");
                }

                await using (var writer = new AsyncBlittableJsonTextWriter(context, ResponseBodyStream()))
                {
                    writer.WriteStartObject();
                    writer.WritePropertyName("Results");
                    writer.WriteStartArray();
                    var resultProperty  = context.GetLazyStringForFieldWithCaching(nameof(GetResponse.Result));
                    var statusProperty  = context.GetLazyStringForFieldWithCaching(nameof(GetResponse.StatusCode));
                    var headersProperty = context.GetLazyStringForFieldWithCaching(nameof(GetResponse.Headers));

                    var features       = new FeatureCollection(HttpContext.Features);
                    var responseStream = new MultiGetHttpResponseStream(ResponseBodyStream());
                    features.Set <IHttpResponseFeature>(new MultiGetHttpResponseFeature());
                    features.Set <IHttpResponseBodyFeature>(new StreamResponseBodyFeature(responseStream));
                    var           httpContext = new DefaultHttpContext(features);
                    var           host        = HttpContext.Request.Host;
                    var           scheme      = HttpContext.Request.Scheme;
                    StringBuilder trafficWatchStringBuilder = null;
                    if (TrafficWatchManager.HasRegisteredClients)
                    {
                        trafficWatchStringBuilder = new StringBuilder();
                    }
                    for (var i = 0; i < requests.Length; i++)
                    {
                        if (i != 0)
                        {
                            writer.WriteComma();
                        }

                        var request = (BlittableJsonReaderObject)requests[i];
                        await HandleRequestAsync(request, context, responseStream, writer, httpContext, host, scheme, resultProperty, statusProperty, headersProperty, trafficWatchStringBuilder);
                    }
                    if (trafficWatchStringBuilder != null)
                    {
                        AddStringToHttpContext(trafficWatchStringBuilder.ToString(), TrafficWatchChangeType.MultiGet);
                    }
                    writer.WriteEndArray();
                    writer.WriteEndObject();
                }
            }
        }
Ejemplo n.º 2
0
        public async Task PostMultiGet()
        {
            using (ContextPool.AllocateOperationContext(out JsonOperationContext context))
            {
                var input = await context.ReadForMemoryAsync(RequestBodyStream(), "multi_get");

                if (input.TryGet("Requests", out BlittableJsonReaderArray requests) == false)
                {
                    ThrowRequiredPropertyNameInRequest("Requests");
                }

                using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                {
                    writer.WriteStartObject();
                    writer.WritePropertyName("Results");
                    writer.WriteStartArray();
                    var resultProperty  = context.GetLazyStringForFieldWithCaching(nameof(GetResponse.Result));
                    var statusProperty  = context.GetLazyStringForFieldWithCaching(nameof(GetResponse.StatusCode));
                    var headersProperty = context.GetLazyStringForFieldWithCaching(nameof(GetResponse.Headers));

                    var features       = new FeatureCollection(HttpContext.Features);
                    var responseStream = new MultiGetHttpResponseStream(ResponseBodyStream());
                    features.Set <IHttpResponseFeature>(new MultiGetHttpResponseFeature(responseStream));
                    var httpContext = new DefaultHttpContext(features);
                    var host        = HttpContext.Request.Host;
                    var scheme      = HttpContext.Request.Scheme;

                    for (int i = 0; i < requests.Length; i++)
                    {
                        var request = (BlittableJsonReaderObject)requests[i];

                        if (i != 0)
                        {
                            writer.WriteComma();
                        }
                        writer.WriteStartObject();

                        if (request.TryGet("Url", out string url) == false || request.TryGet("Query", out string query) == false)
                        {
                            writer.WriteEndObject();
                            continue;
                        }

                        if (request.TryGet("Method", out string method) == false || string.IsNullOrEmpty(method))
                        {
                            method = HttpMethod.Get.Method;
                        }

                        httpContext.Request.Method = method;

                        var routeInformation = Server.Router.GetRoute(method, url, out RouteMatch localMatch);
                        if (routeInformation == null)
                        {
                            writer.WritePropertyName(statusProperty);
                            writer.WriteInteger((int)HttpStatusCode.BadRequest);
                            writer.WritePropertyName(resultProperty);
                            context.Write(writer, new DynamicJsonValue
                            {
                                ["Error"] = $"There is no handler for path: {method} {url}{query}"
                            });
                            writer.WriteEndObject();
                            continue;
                        }

                        var requestHandler = routeInformation.GetRequestHandler();
                        writer.WritePropertyName(resultProperty);
                        writer.Flush();

                        httpContext.Response.StatusCode = 0;
                        httpContext.Request.Headers.Clear();
                        httpContext.Response.Headers.Clear();
                        httpContext.Request.Host        = host;
                        httpContext.Request.Scheme      = scheme;
                        httpContext.Request.QueryString = new QueryString(query);
                        if (request.TryGet("Headers", out BlittableJsonReaderObject headers))
                        {
                            foreach (var header in headers.GetPropertyNames())
                            {
                                if (headers.TryGet(header, out string value) == false)
                                {
                                    continue;
                                }

                                if (string.IsNullOrWhiteSpace(value))
                                {
                                    continue;
                                }

                                httpContext.Request.Headers.Add(header, value);
                            }
                        }

                        if (method == HttpMethod.Post.Method && request.TryGet("Content", out object content))
                        {
                            if (content is LazyStringValue)
                            {
                                var requestBody = GetRequestBody(content.ToString());
                                HttpContext.Response.RegisterForDispose(requestBody);
                                httpContext.Request.Body = requestBody;
                            }
                            else
                            {
                                var requestBody   = new MemoryStream();
                                var contentWriter = new BlittableJsonTextWriter(context, requestBody);
                                context.Write(contentWriter, (BlittableJsonReaderObject)content);
                                contentWriter.Flush();
                                HttpContext.Response.RegisterForDispose(requestBody);
                                httpContext.Request.Body          = requestBody;
                                httpContext.Request.Body.Position = 0;
                            }
                        }

                        var bytesWrittenBeforeRequest = responseStream.BytesWritten;
                        int statusCode;
                        try
                        {
                            await requestHandler(new RequestHandlerContext
                            {
                                Database    = Database,
                                RavenServer = Server,
                                RouteMatch  = localMatch,
                                HttpContext = httpContext
                            });

                            if (bytesWrittenBeforeRequest == responseStream.BytesWritten)
                            {
                                writer.WriteNull();
                            }

                            statusCode = httpContext.Response.StatusCode == 0
                                ? (int)HttpStatusCode.OK
                                : httpContext.Response.StatusCode;
                        }
                        catch (Exception e)
                        {
                            if (bytesWrittenBeforeRequest != responseStream.BytesWritten)
                            {
                                throw;
                            }

                            statusCode = (int)HttpStatusCode.InternalServerError;

                            var djv = new DynamicJsonValue
                            {
                                [nameof(ExceptionDispatcher.ExceptionSchema.Url)]     = $"{url}{query}",
                                [nameof(ExceptionDispatcher.ExceptionSchema.Type)]    = e.GetType().FullName,
                                [nameof(ExceptionDispatcher.ExceptionSchema.Message)] = e.Message,
                                [nameof(ExceptionDispatcher.ExceptionSchema.Error)]   = e.ToString()
                            };

                            using (var json = context.ReadObject(djv, "exception"))
                                writer.WriteObject(json);
                        }

                        writer.WriteComma();
                        writer.WritePropertyName(statusProperty);
                        writer.WriteInteger(statusCode);
                        writer.WriteComma();

                        writer.WritePropertyName(headersProperty);
                        writer.WriteStartObject();
                        bool headerStart = true;
                        foreach (var header in httpContext.Response.Headers)
                        {
                            foreach (var value in header.Value)
                            {
                                if (headerStart == false)
                                {
                                    writer.WriteComma();
                                }
                                headerStart = false;
                                writer.WritePropertyName(header.Key);
                                writer.WriteString(value);
                            }
                        }
                        writer.WriteEndObject();

                        writer.WriteEndObject();
                    }
                    writer.WriteEndArray();
                    writer.WriteEndObject();
                }
            }
        }
Ejemplo n.º 3
0
        private async ValueTask HandleRequestAsync(
            BlittableJsonReaderObject request,
            JsonOperationContext context,
            MultiGetHttpResponseStream responseStream,
            AsyncBlittableJsonTextWriter writer,
            HttpContext httpContext,
            HostString host,
            string scheme,
            LazyStringValue resultProperty,
            LazyStringValue statusProperty,
            LazyStringValue headersProperty,
            StringBuilder trafficWatchStringBuilder)
        {
            writer.WriteStartObject();

            if (request.TryGet(nameof(GetRequest.Url), out string url) == false || request.TryGet(nameof(GetRequest.Query), out string query) == false)
            {
                writer.WriteEndObject();
                return;
            }

            if (request.TryGet(nameof(GetRequest.Method), out string method) == false || string.IsNullOrEmpty(method))
            {
                method = HttpMethod.Get.Method;
            }

            httpContext.Request.Method = method;

            var routeInformation = Server.Router.GetRoute(method, url, out RouteMatch localMatch);

            if (routeInformation == null)
            {
                HandleNoRoute(context, writer, method, url, query, statusProperty, resultProperty);
                return;
            }

            var requestHandler = routeInformation.GetRequestHandler();

            writer.WritePropertyName(resultProperty);
            await writer.FlushAsync();

            var content = await PrepareHttpContextAsync(request, context, httpContext, method, query, host, scheme, trafficWatchStringBuilder);

            var bytesWrittenBeforeRequest = responseStream.BytesWritten;
            int statusCode;

            try
            {
                if (Server.Configuration.Security.AuthenticationEnabled == false ||
                    (await Server.Router.TryAuthorizeAsync(routeInformation, httpContext, Database)).Authorized)
                {
                    await requestHandler(new RequestHandlerContext
                    {
                        Database    = Database,
                        RavenServer = Server,
                        RouteMatch  = localMatch,
                        HttpContext = httpContext
                    });
                }

                if (bytesWrittenBeforeRequest == responseStream.BytesWritten)
                {
                    writer.WriteNull();
                }

                statusCode = httpContext.Response.StatusCode == 0
                    ? (int)HttpStatusCode.OK
                    : httpContext.Response.StatusCode;
            }
            catch (Exception e)
            {
                if (bytesWrittenBeforeRequest != responseStream.BytesWritten)
                {
                    throw;
                }

                statusCode = (int)HttpStatusCode.InternalServerError;

                HandleException(context, writer, e, url, query);
            }

            writer.WriteComma();

            writer.WritePropertyName(statusProperty);
            writer.WriteInteger(statusCode);

            writer.WriteComma();

            WriteHeaders(writer, httpContext, headersProperty);

            writer.WriteEndObject();

            trafficWatchStringBuilder?.Append(content).AppendLine();
        }