コード例 #1
0
        internal virtual async Task <Exception> ReadErrorResponseAsync(RestCallData callData)
        {
            try {
                var response = callData.Response;
                var hasBody  = response.Content != null && response.Content.Headers.ContentLength > 0;
                if (!hasBody)
                {
                    return(new RestException($"Web API call failed, no details returned. HTTP Status: {response.StatusCode}",
                                             response.StatusCode));
                }
                callData.ResponseBodyString = await response.Content.ReadAsStringAsync();

                switch (response.StatusCode)
                {
                case HttpStatusCode.BadRequest:
                    if (Settings.BadRequestContentType == typeof(string))
                    {
                        return(await ReadErrorResponseUntypedAsync(response));
                    }
                    var errObj = Settings.Serializer.Deserialize(Settings.BadRequestContentType, callData.ResponseBodyString);
                    return(new BadRequestException(errObj));

                default:
                    if (Settings.ServerErrorContentType == typeof(string))
                    {
                        return(await ReadErrorResponseUntypedAsync(response));
                    }
                    //deserialize custom object
                    try {
                        var serverErr = Settings.Serializer.Deserialize(Settings.ServerErrorContentType, callData.ResponseBodyString);
                        return(new RestException("Server error: " + callData.ResponseBodyString, response.StatusCode, serverErr));
                    } catch (Exception ex) {
                        var remoteErr = callData.ResponseBodyString;
                        var msg       = $"Server error: {remoteErr}. RestClient: failed to deserialize response into error object, exc: {ex}";
                        return(new RestException(msg, response.StatusCode, remoteErr));
                    }
                }//switch
            } catch (Exception exc) {
                Type errorType = callData.Response.StatusCode == HttpStatusCode.BadRequest ?
                                 Settings.BadRequestContentType : Settings.ServerErrorContentType;
                var explain = $@"Failed to read error response returned from the service.
Expected content type: {errorType}. Consider changing it to match the error response for remote service. 
Deserializer error: {exc.Message}";
                throw new Exception(explain, exc);
            }
        }
コード例 #2
0
ファイル: RestClient.cs プロジェクト: rivantsov/arrest
        }//method

        private async Task ReadResponseBodyAsync(RestCallData callData)
        {
            var content = callData.Response.Content;
            // check response body kind
            var returnValueKind = GetReturnValueKind(callData.ResponseBodyType);

            callData.ResponseBodyString = "(not set)";
            switch (returnValueKind)
            {
            case ReturnValueKind.None:
                return;

            case ReturnValueKind.HttpResponseMessage:
                callData.ResponseBodyObject = callData.Response;
                return;

            case ReturnValueKind.HttpContent:
                callData.ResponseBodyObject = content;
                return;

            case ReturnValueKind.Stream:
                callData.ResponseBodyObject = await content.ReadAsStreamAsync();

                return;

            case ReturnValueKind.HttpStatusCode:
                var status = callData.Response.StatusCode;
                callData.ResponseBodyObject = status;
                return;

            case ReturnValueKind.Object:
                // read as string and then deserialize
                callData.ResponseBodyString = await content.ReadAsStringAsync();

                if (!string.IsNullOrEmpty(callData.ResponseBodyString))
                {
                    callData.ResponseBodyObject = Settings.Serializer.Deserialize(callData.ResponseBodyType, callData.ResponseBodyString);
                }
                return;
            }// switch
        }
コード例 #3
0
ファイル: RestClient.cs プロジェクト: rivantsov/arrest
        private void BuildHttpRequestContent(RestCallData request)
        {
            var body = request.RequestBodyObject;

            if (body == null)
            {
                return;
            }
            // = ApiClientUtil.GetRequestBodyKind(request.HttpMethod, request.RequestBodyType);
            if (typeof(HttpContent).IsAssignableFrom(request.RequestBodyType))
            {
                request.Request.Content = (HttpContent)body;
            }
            else if (typeof(Stream).IsAssignableFrom(request.RequestBodyType))
            {
                var stream = (Stream)body;
                request.Request.Content = new StreamContent(stream);
            }
            else
            {
                var strContent = Settings.Serializer.Serialize(body);
                request.Request.Content = new StringContent(strContent, this.Settings.Encoding, GetRequestMediaType());
            }
        }
コード例 #4
0
ファイル: RestClient.cs プロジェクト: rivantsov/arrest
        private async Task <TResult> SendAsyncImpl <TBody, TResult>(HttpMethod method, string urlTemplate, object[] urlParameters,
                                                                    TBody body, string acceptMediaType = null)
        {
            var start    = GetTimestamp();
            var callData = new RestCallData()
            {
                StartedAtUtc      = RestClientHelper.GetUtc(),
                HttpMethod        = method,
                UrlTemplate       = urlTemplate,
                UrlParameters     = urlParameters,
                Url               = FormatUrl(urlTemplate, urlParameters),
                RequestBodyType   = typeof(TBody),
                ResponseBodyType  = typeof(TResult),
                RequestBodyObject = body,
                AcceptMediaType   = acceptMediaType ?? Settings.ExplicitAcceptList ?? Settings.Serializer.ContentTypes,
            };

            // Create RequestMessage, setup headers, serialize body
            callData.Request = new HttpRequestMessage(callData.HttpMethod, callData.Url);
            var headers = callData.Request.Headers;

            headers.Add("accept", callData.AcceptMediaType);
            foreach (var kv in this.DefaultRequestHeaders)
            {
                headers.Add(kv.Key, kv.Value);
            }
            BuildHttpRequestContent(callData);

            Settings.Events.OnSendingRequest(this, callData);

            //actually make a call
            callData.Response = await HttpClient.SendAsync(callData.Request, this.CancellationToken);

            callData.TimeElapsed = GetTimeSince(start); //measure time in case we are about to cancel and throw

            //check error
            if (callData.Response.IsSuccessStatusCode)
            {
                Settings.Events.OnReceivedResponse(this, callData);
                await ReadResponseBodyAsync(callData).ConfigureAwait(false);
            }
            else
            {
                callData.Exception = await this.ReadErrorResponseAsync(callData);

                Settings.Events.OnReceivedError(this, callData);
            }
            // get time again to include deserialization time
            callData.TimeElapsed = GetTimeSince(start);
            // Log
            // args: operationContext, clientName, urlTemplate, urlArgs, request, response, requestBody, responseBody, timeMs, exc
            var timeMs = (int)callData.TimeElapsed.TotalMilliseconds;

            Settings.LogAction?.Invoke(this.AppContext, this.ClientName, callData.UrlTemplate, callData.UrlParameters,
                                       callData.Request, callData.Response, callData.RequestBodyString, callData.ResponseBodyString,
                                       timeMs, callData.Exception);
            Settings.Events.OnCompleted(this, callData);
            if (callData.Exception != null)
            {
                throw callData.Exception;
            }
            return((TResult)callData.ResponseBodyObject);
        }//method