/// <summary>
 /// Used when creating generic requests
 /// </summary>
 internal RequestParameters(Context context, Method method, IResource resource, string protocolIdentifier = null, string viewName = null)
 {
     TraceId            = context.InitialTraceId;
     Context            = context;
     Method             = method;
     Headers            = new Headers();
     iresource          = resource;
     IsWebSocketUpgrade = Context.WebSocket?.Status == WebSocketStatus.Waiting;
     Uri = new URI
     {
         ResourceSpecifier = resource.Name,
         ViewName          = viewName
     };
     CachedProtocolProvider = ProtocolController.ResolveProtocolProvider(protocolIdentifier);
 }
        /// <summary>
        /// Used when performing CheckOrigin
        /// </summary>
        internal RequestParameters(Context context, string uri, Headers headers)
        {
            TraceId = context.InitialTraceId;
            Context = context;
            Headers = headers ?? new Headers();
            Uri     = URI.ParseInternal(uri, PercentCharsEscaped(headers), context, out var cachedProtocolProvider);
            var hasMacro = Uri?.Macro != null;

            if (hasMacro)
            {
                if (Uri.Macro.OverwriteHeaders)
                {
                    Uri.Macro.Headers?.ForEach(pair => Headers[pair.Key] = pair.Value);
                }
                else
                {
                    Uri.Macro.Headers?.ForEach(pair =>
                    {
                        var currentValue = Headers.SafeGet(pair.Key);
                        if (string.IsNullOrWhiteSpace(currentValue) || currentValue == "*/*")
                        {
                            Headers[pair.Key] = pair.Value;
                        }
                    });
                }
            }
            CachedProtocolProvider = cachedProtocolProvider;
            UnparsedUri            = uri;
            try
            {
                var _ = IResource;
            }
            catch (Exception e)
            {
                Error = e.AsError();
            }
            if (Error == null && Uri?.HasError == true)
            {
                Error = Uri.Error;
            }
        }
Ejemplo n.º 3
0
        private async Task <IResult> _GetResult()
        {
            try
            {
                var sw      = Stopwatch.StartNew();
                var method  = new HttpMethod(Method.ToString());
                var message = new HttpRequestMessage(method, URI);
                switch (Method)
                {
                case Method.POST:
                case Method.PATCH:
                case Method.PUT:
                    if (GetBody().HasContent)
                    {
                        message.Content = new StreamContent(GetBody().Stream);
                        message.Content.Headers.ContentType = MediaTypeHeaderValue.Parse(Headers.ContentType.ToString());
                    }
                    break;
                }
                Headers.Metadata    = "full";
                Headers.ContentType = null;
                Headers.ForEach(header => message.Headers.Add(header.Key, header.Value));
                var response = await HttpClient.SendAsync(message);

                switch (response?.StatusCode)
                {
                case null:
                case HttpStatusCode.GatewayTimeout:
                case HttpStatusCode.RequestTimeout: return(new Timeout(URI.ToString()).AsResultOf(this));

                case HttpStatusCode.BadGateway: return(new BadGateway(URI.ToString()).AsResultOf(this));
                }
                var responseHeaders = new Headers();
                response.Headers.ForEach(header => responseHeaders[header.Key]         = header.Value.FirstOrDefault());
                response.Content.Headers.ForEach(header => responseHeaders[header.Key] = header.Value.FirstOrDefault());
                var metadata = responseHeaders.Metadata?.Split(';');
                if (metadata?.Length != 3)
                {
                    return(new ExternalServiceNotRESTar(URI).AsResultOf(this));
                }
                var(resultType, resourceName, data) = (metadata[0], metadata[1], metadata[2]);
                if (string.IsNullOrWhiteSpace(resultType))
                {
                    return(new ExternalServiceNotRESTar(URI).AsResultOf(this));
                }
                RemoteResource = new RemoteResource(resourceName);
                var stream = default(RESTarStream);
                if (response.Content != null)
                {
                    if (!(responseHeaders.ContentType is ContentType contentType))
                    {
                        return(new ExternalServiceNotRESTar(URI).AsResultOf(this));
                    }
                    var _stream = new RESTarStream(contentType);
                    await response.Content.CopyToAsync(_stream);

                    stream = _stream.Rewind();
                }

                IResult getResult()
                {
                    int        nr;
                    ErrorCodes ec;

                    switch (resultType)
                    {
                    case nameof(Entities <object>) when ulong.TryParse(responseHeaders.EntityCount, out var count):
                        return(new RemoteEntities(this, stream, count));

                    case nameof(Head) when int.TryParse(data, out nr): return(new Head(this, nr));

                    case nameof(Report) when int.TryParse(data, out nr): return(new Report(this, nr));

                    case nameof(Binary): return(new Binary(this, stream, responseHeaders.ContentType ?? ContentType.DefaultOutput));

                    case nameof(NoContent): return(new NoContent(this));

                    case nameof(InsertedEntities) when int.TryParse(data, out nr): return(new InsertedEntities(this, nr));

                    case nameof(UpdatedEntities) when int.TryParse(data, out nr): return(new UpdatedEntities(this, nr));

                    case nameof(DeletedEntities) when int.TryParse(data, out nr): return(new DeletedEntities(this, nr));

                    case nameof(SafePostedEntities)
                        when data.TSplit(',') is var vt && int.TryParse(vt.Item1, out var upd) && int.TryParse(vt.Item2, out var ins):
                        return(new SafePostedEntities(this, upd, ins));

                    case nameof(BadRequest) when Enum.TryParse(data, out ec): return(new RemoteBadRequest(ec));

                    case nameof(NotFound) when Enum.TryParse(data, out ec): return(new RemoteNotFound(ec));

                    case nameof(Forbidden) when Enum.TryParse(data, out ec): return(new RemoteForbidden(ec));

                    case nameof(Results.Internal) when Enum.TryParse(data, out ec): return(new RemoteInternal(ec));

                    case nameof(FeatureNotImplemented): return(new FeatureNotImplemented(null));

                    case nameof(InfiniteLoop): return(new InfiniteLoop());

                    case nameof(MethodNotAllowed): return(new MethodNotAllowed(Method, Resource, false));

                    case nameof(NotAcceptable): return(new NotAcceptable(Headers.Accept.ToString()));

                    case nameof(UnsupportedContent): return(new UnsupportedContent(Headers.ContentType.ToString()));

                    case nameof(UpgradeRequired): return(new UpgradeRequired(Resource.Name));

                    default: return(new RemoteOther(this, response.StatusCode, response.ReasonPhrase));
                    }
                }

                var result = getResult();
                if (result is Error error)
                {
                    result = error.AsResultOf(this);
                }
                responseHeaders.ForEach(result.Headers.Put);
                TimeElapsed = sw.Elapsed;
                return(result);
            }
            catch (Exception e)
            {
                return(new ExternalServiceNotRESTar(URI, e).AsResultOf(this));
            }
        }
        /// <summary>
        /// Used when creating parsed requests
        /// </summary>
        internal RequestParameters(Context context, Method method, string uri, byte[] body, Headers headers)
        {
            TraceId            = context.InitialTraceId;
            Context            = context;
            Method             = method;
            Headers            = headers ?? new Headers();
            IsWebSocketUpgrade = Context.WebSocket?.Status == WebSocketStatus.Waiting;
            Uri = URI.ParseInternal(uri, PercentCharsEscaped(headers), context, out var cachedProtocolProvider);
            var hasMacro = Uri?.Macro != null;

            if (hasMacro)
            {
                if (Uri.Macro.OverwriteHeaders)
                {
                    Uri.Macro.Headers?.ForEach(pair => Headers[pair.Key] = pair.Value);
                }
                else
                {
                    Uri.Macro.Headers?.ForEach(pair =>
                    {
                        var currentValue = Headers.SafeGet(pair.Key);
                        if (string.IsNullOrWhiteSpace(currentValue) || currentValue == "*/*")
                        {
                            Headers[pair.Key] = pair.Value;
                        }
                    });
                }
            }
            CachedProtocolProvider = cachedProtocolProvider;
            UnparsedUri            = uri;
            if (Uri?.HasError == true)
            {
                Error = Uri.Error;
                return;
            }
            try
            {
                var _ = IResource;
            }
            catch (Exception e)
            {
                Error = e.AsError();
            }

            if (hasMacro)
            {
                if (Uri.Macro.OverwriteBody)
                {
                    if (Uri.Macro.HasBody)
                    {
                        BodyBytes           = Uri.Macro.Body;
                        Headers.ContentType = Providers.Json.ContentType;
                    }
                }
                else
                {
                    if (!(body?.Length > 0) && Uri.Macro.HasBody)
                    {
                        BodyBytes           = Uri.Macro.Body;
                        Headers.ContentType = Providers.Json.ContentType;
                    }
                    else
                    {
                        BodyBytes = body;
                    }
                }
            }
            else
            {
                BodyBytes = body;
            }
            HasBody = BodyBytes?.Length > 0;
        }