/// <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; }
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); } } } }