/// <summary>
        /// Implements the same method as the real service interface allowing the mock to be plugged in
        /// </summary>
        /// <typeparam name="Response"></typeparam>
        /// <typeparam name="Request"></typeparam>
        /// <param name="resource"></param>
        /// <param name="verb"></param>
        /// <param name="request"></param>
        /// <param name="deleteBody"></param>
        /// <param name="session"></param>
        /// <returns></returns>
        public async Task <ShippingApiResponse <Response> > HttpRequest <Response, Request>(string resource, HttpVerb verb, Request request, bool deleteBody, ISession session = null) where Request : IShippingApiRequest
        {
            string fullPath = request.RecordingFullPath(resource, session);
            string cwd      = Directory.GetCurrentDirectory();

            if (File.Exists(fullPath))
            {
                var apiResponse = new ShippingApiResponse <Response> {
                    HttpStatus = HttpStatusCode.OK, Success = true
                };
                long jsonPosition = 0;
                using (var fileStream = new FileStream(fullPath, FileMode.Open, FileAccess.Read))
                    using (var fileReader = new StreamReader(fileStream))
                    {
                        for (var line = await fileReader.ReadLineAsync(); line != string.Empty; line = await fileReader.ReadLineAsync())
                        {
                            jsonPosition += line.Length + 2; // + CRLF
                            if (line.IndexOf(':') == -1)
                            {
                                continue;
                            }
                            var headerName  = line.Substring(0, line.IndexOf(':'));
                            var headerValue = line.IndexOf(':') == line.Length? string.Empty : line.Substring(line.IndexOf(':') + 1);
                            apiResponse.ProcessResponseAttribute(headerName, headerValue.Split(','));
                        }
                    }
                using (var fileStream = new FileStream(fullPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                    using (var recordingStream = new RecordingStream(fileStream, request.RecordingFullPath(resource, session), FileMode.Create))
                    {
                        try
                        {
                            //dont open the record file
                            ShippingApiResponse <Response> .Deserialize(session, recordingStream, apiResponse, jsonPosition);
                        }
                        catch (Exception ex)
                        {
                            session.LogError(string.Format("Mock request {0} got deserialization exception {1}", fullPath, ex.Message));
                            throw ex;
                        }
                    }
                return(apiResponse);
            }

            else
            {
                var apiResponse = new ShippingApiResponse <Response> {
                    HttpStatus = HttpStatusCode.NotFound, Success = false
                };
                session.LogDebug(string.Format("Mock request failed {0}", fullPath));
                apiResponse.Errors.Add(new ErrorDetail()
                {
                    ErrorCode = "Mock 401", Message = "Could not find response file" + fullPath
                });
                return(apiResponse);
            }
        }
 /// <summary>
 /// Set a message, inner exception and a response object.
 /// </summary>
 /// <param name="response">As returned by the web service classes</param>
 /// <param name="message"></param>
 /// <param name="inner"></param>
 public ShippingAPIException(ShippingApiResponse response, string message, Exception inner) : this(message, inner)
 {
     ErrorResponse = response;
 }
 /// <summary>
 /// Constructor, set the API response object
 /// </summary>
 /// <param name="response">As returned by the web service classes</param>
 public ShippingAPIException(ShippingApiResponse response) : this()
 {
     ErrorResponse = response;
 }
Exemple #4
0
        private async static Task <ShippingApiResponse <Response> > Request <Response, Request>(string uri, HttpVerb verb, Request request, bool deleteBody, ISession session = null) where Request : IShippingApiRequest
        {
            if (session == null)
            {
                session = Globals.DefaultSession;
            }
            session.LogDebug("Calling method");
            var response  = new ShippingApiResponse <Response>();
            var stopwatch = new Stopwatch();

            stopwatch.Start();
            try
            {
                int timeout = Globals.TimeOutMilliseconds;
#pragma warning disable CS0618
                int configRetries = session.Retries;
#pragma warning restore CS0618
                for (int retries = configRetries; retries > 0; retries--)
                {
                    if (session.AuthToken == null || session.AuthToken.AccessToken == null)  //TODO: Check if token should have expired
                    {
                        var tokenResponse = await TokenMethods.token();

                        if (!tokenResponse.Success)
                        {
                            session.AuthToken = null;
                            if (retries == 1) // no more tries left
                            {
                                response.Errors     = tokenResponse.Errors;
                                response.HttpStatus = tokenResponse.HttpStatus;
                                break;
                            }
                            if (stopwatch.ElapsedMilliseconds > Globals.TimeOutMilliseconds)
                            {
                                response.HttpStatus = HttpStatusCode.RequestTimeout;
                                response.Errors.Add(new ErrorDetail()
                                {
                                    ErrorCode = "Client Timeout", Message = "Client Timeout"
                                });
                                break;
                            }
                            continue;
                        }
                        session.AuthToken = tokenResponse.APIResponse;
                    }

                    request.Authorization = new StringBuilder(session.AuthToken.AccessToken);
                    response = await session.Requester.HttpRequest <Response, Request>(uri, verb, request, deleteBody, session);

                    if (response.Success)
                    {
                        break;
                    }
                    if (!Retry(response.HttpStatus, response.Errors))
                    {
                        break;
                    }
                    if (stopwatch.ElapsedMilliseconds > Globals.TimeOutMilliseconds)
                    {
                        response.HttpStatus = HttpStatusCode.RequestTimeout;
                        response.Errors.Add(new ErrorDetail()
                        {
                            ErrorCode = "Client Timeout", Message = "Client Timeout"
                        });
                        break;
                    }
                }
            }
            catch (JsonSerializationException j)
            {
#pragma warning disable CS0618
                response.HttpStatus = HttpStatusCode.InternalServerError;
                response.Errors.Add(new ErrorDetail()
                {
                    ErrorCode = "Deserialization error", Message = j.Message
                });
                if (session.ThrowExceptions)
                {
                    throw new ShippingAPIException(response, "DeserializationError", j);
                }
            }
            stopwatch.Stop();
            response.RequestTime = stopwatch.Elapsed;
            session.UpdateCounters(uri, response.Success, response.RequestTime);
            if (session.ThrowExceptions && !response.Success)
            {
                throw new ShippingAPIException(response);
            }
#pragma warning restore CS0618
            return(response);
        }
        internal async static Task <ShippingApiResponse <Response> > HttpRequestStatic <Response, Request>(string resource, HttpVerb verb, Request request, bool deleteBody = false, ISession session = null) where Request : IShippingApiRequest
        {
            if (session == null)
            {
                session = Globals.DefaultSession;
            }
            var client = Globals.Client(session.EndPoint);

            //            client.Timeout = new TimeSpan(0, 0, 0, 0, session.TimeOutMilliseconds);

            using (var recordingStream = new RecordingStream(null, request.RecordingFullPath(resource, session), FileMode.Create, RecordingStream.RecordType.MultipartMime))
            {
#pragma warning disable CS0618
                recordingStream.OpenRecord(session.Record);
#pragma warning restore CS0618
                string uriBuilder = request.GetUri(resource);

                HttpResponseMessage httpResponseMessage;
                using (HttpRequestMessage requestMessage = new HttpRequestMessage())
                {
                    using (var stream = new MemoryStream())
                    {
                        recordingStream.SetBaseStream(stream, "text/httpRequest");
                        recordingStream.WriteRecordCRLF(string.Format("{0} {1} HTTP/1.1", verb.ToString(), uriBuilder));
                        recordingStream.WriteRecordCRLF(string.Format("{0}: {1}", "Content-Type", request.ContentType));
                        foreach (var h in request.GetHeaders())
                        {
                            AddRequestHeaders(requestMessage, h.Item1, h.Item2, h.Item3, recordingStream);
                        }
                        recordingStream.WriteRecordCRLF("");

                        if (verb == HttpVerb.PUT || verb == HttpVerb.POST || (verb == HttpVerb.DELETE && deleteBody))
                        {
                            using (var writer = new StreamWriter(recordingStream))
                                using (var reqContent = new StreamContent(stream))
                                {
                                    request.SerializeBody(writer, session);
                                    stream.Seek(0, SeekOrigin.Begin);
                                    requestMessage.Content         = reqContent;
                                    reqContent.Headers.ContentType = new MediaTypeHeaderValue(request.ContentType);
                                    recordingStream.WriteRecordCRLF(string.Format("user-agent:{0}", Globals.UserAgent));
                                    recordingStream.WriteRecordCRLF(string.Format("X-PB-UnifiedErrorStructure : true"));

                                    if (verb == HttpVerb.PUT)
                                    {
                                        requestMessage.Method = HttpMethod.Put;
                                    }
                                    else if (verb == HttpVerb.DELETE)
                                    {
                                        requestMessage.Method = HttpMethod.Delete;
                                    }
                                    else
                                    {
                                        requestMessage.Method = HttpMethod.Post;
                                    }
                                    requestMessage.RequestUri = new Uri(client.BaseAddress + uriBuilder);
                                    httpResponseMessage       = await client.SendAsync(requestMessage);
                                }
                        }

                        else if (verb == HttpVerb.DELETE)
                        {
                            requestMessage.Method     = HttpMethod.Delete;
                            requestMessage.RequestUri = new Uri(client.BaseAddress + uriBuilder);
                            httpResponseMessage       = await client.SendAsync(requestMessage);
                        }
                        else
                        {
                            requestMessage.Method     = HttpMethod.Get;
                            requestMessage.RequestUri = new Uri(client.BaseAddress + uriBuilder);
                            httpResponseMessage       = await client.SendAsync(requestMessage);
                        }
                    }
                }

                using (var respStream = await httpResponseMessage.Content.ReadAsStreamAsync())
                {
                    recordingStream.SetBaseStream(respStream, "text/httpResponse");

                    recordingStream.WriteRecordCRLF(string.Format("HTTP/1.1 {0} {1}", (int)httpResponseMessage.StatusCode, httpResponseMessage.ReasonPhrase));
                    recordingStream.WriteRecordCRLF(string.Format("Content-Length: {0}", httpResponseMessage.Content.Headers.ContentLength));
                    recordingStream.WriteRecordCRLF(string.Format("Content-Type: {0}", httpResponseMessage.Content.Headers.ContentType));
                    recordingStream.WriteRecordCRLF("");

                    if (httpResponseMessage.IsSuccessStatusCode)
                    {
                        var apiResponse = new ShippingApiResponse <Response> {
                            HttpStatus = httpResponseMessage.StatusCode, Success = httpResponseMessage.IsSuccessStatusCode
                        };
                        var sb = new StringBuilder();
                        foreach (var h in httpResponseMessage.Headers)
                        {
                            apiResponse.ProcessResponseAttribute(h.Key, h.Value);
                            bool firstValue = true;
                            foreach (var s in h.Value)
                            {
                                if (firstValue)
                                {
                                    firstValue = false;
                                }
                                else
                                {
                                    sb.Append(';');
                                }
                                sb.Append(s);
                            }
                            recordingStream.WriteRecordCRLF(string.Format("{0}:{1}", h.Key, sb.ToString()));
                            sb.Clear();
                        }
                        recordingStream.WriteRecordCRLF("");
                        ShippingApiResponse <Response> .Deserialize(session, recordingStream, apiResponse);

                        return(apiResponse);
                    }
                    else
                    {
                        var apiResponse = new ShippingApiResponse <Response> {
                            HttpStatus = httpResponseMessage.StatusCode, Success = httpResponseMessage.IsSuccessStatusCode
                        };
                        try
                        {
                            ShippingApiResponse <Response> .Deserialize(session, recordingStream, apiResponse);
                        }
                        catch (JsonException)
                        {
                            session.LogWarning(String.Format("http {0} request to {1} failed to deserialize with error {2}", verb.ToString(), uriBuilder, httpResponseMessage.StatusCode));
                            apiResponse.Errors.Add(new ErrorDetail()
                            {
                                ErrorCode = "HTTP " + httpResponseMessage.Version + " " + httpResponseMessage.StatusCode.ToString(), Message = httpResponseMessage.ReasonPhrase
                            });
                        }
                        return(apiResponse);
                    }
                }
            }
        }