コード例 #1
0
        /// <summary>
        /// Adds StringContent containing a json string of the supplied body object
        /// </summary>
        /// <typeparam name="T">The type of body</typeparam>
        /// <param name="request">The SolidHttpRequest</param>
        /// <param name="body">The request body object</param>
        /// <param name="settings">(Optional) JsonSerializerSettings to use to serialize the body object</param>
        /// <returns>SolidHttpRequest</returns>
        public static ISolidHttpRequest WithJsonContent <T>(this ISolidHttpRequest request, T body, JsonSerializerSettings settings = null)
        {
            var json    = JsonConvert.SerializeObject(body, settings ?? request.GetJsonSerializerSettings());
            var content = new StringContent(json, Encoding.UTF8, "application/json");

            return(request.WithContent(content));
        }
コード例 #2
0
        /// <summary>
        /// Adds form data content to the inner <see cref="HttpRequestMessage" />.
        /// </summary>
        /// <param name="request">The <see cref="ISolidHttpRequest" /> that is being extended.</param>
        /// <param name="name">The form name of the <see cref="HttpContent" />.</param>
        /// <param name="content">The <see cref="HttpContent" /> to add.</param>
        /// <returns>The <see cref="ISolidHttpRequest" /> so that additional calls can be chained.</returns>
        public static ISolidHttpRequest WithFormDataContent(this ISolidHttpRequest request, string name, HttpContent content)
        {
            var form = request.GetMultipartFormDataContent();

            form.Add(content, name);
            return(request);
        }
コード例 #3
0
        private static ISolidHttpRequest WithMultipartContent(this ISolidHttpRequest request, Func <MultipartContent> create)
        {
            var content   = request.BaseRequest.Content;
            var multipart = content as MultipartContent;
            var contents  = Enumerable.Empty <HttpContent>();

            if (multipart != null)
            {
                contents = multipart;
            }
            else if (content != null)
            {
                contents = new[] { content }
            }
            ;

            var m = create();

            // TODO: Make sure the headers aren't gonna be a problem
            foreach (var c in contents)
            {
                m.Add(c);
            }
            request.BaseRequest.Content = m;
            return(request);
        }
    }
コード例 #4
0
        /// <summary>
        /// Adds form data file to the inner <see cref="HttpRequestMessage" />.
        /// </summary>
        /// <param name="request">The <see cref="ISolidHttpRequest" /> that is being extended.</param>
        /// <param name="name">The form name of the file.</param>
        /// <param name="content">The file <see cref="ByteArrayContent" />.</param>
        /// <param name="fileName">The file name.</param>
        /// <returns>The <see cref="ISolidHttpRequest" /> so that additional calls can be chained.</returns>
        public static ISolidHttpRequest WithFormDataFile(this ISolidHttpRequest request, string name, ByteArrayContent content, string fileName)
        {
            var form = request.GetMultipartFormDataContent();

            form.Add(content, name, fileName);
            return(request);
        }
コード例 #5
0
        /// <summary>
        /// Deserializes the response content as the specified type using the specified settings
        /// </summary>
        /// <typeparam name="T">The type of response body</typeparam>
        /// <param name="request">The SolidHttpRequest</param>
        /// <param name="settings">The specified DataContractSerializerSettings</param>
        /// <returns>Task of type T</returns>
        public static async Task <T> As <T>(this ISolidHttpRequest request, DataContractSerializerSettings settings)
        {
            var factory     = new XmlResponseDeserializerFactory(settings);
            var deserialize = factory.CreateDeserializer <T>();

            return(await request.As <T>(deserialize));
        }
コード例 #6
0
        /// <summary>
        /// Returns the content as a GzipStream, caller is responsable for disposing the stream
        /// </summary>
        /// <param name="request">The extended ISolidHttpRequest</param>
        /// <param name="mode">The zip archive mode</param>
        /// <returns>An awaitable task</returns>
        public static Task <ZipArchive> AsZipArchive(this ISolidHttpRequest request, ZipArchiveMode mode = ZipArchiveMode.Read)
        {
            var factory     = new ZipArchiveResponseDeserializerFactory(mode);
            var deserialize = factory.CreateDeserializer <ZipArchive>();

            return(request.As <ZipArchive>());
        }
コード例 #7
0
        /// <summary>
        /// Performs an async assertion against the http response message
        /// </summary>
        /// <param name="request">The Solid.Http request</param>
        /// <param name="assert">The async assertion action</param>
        /// <returns>The fluent assertion</returns>
        public static Assertion Should(this ISolidHttpRequest request, Func <HttpResponseMessage, Task> assert)
        {
            var assertion = new Assertion(request);

            assertion.Request.OnHttpResponse(async(_, response) => await assert(response));
            return(assertion);
        }
        /// <summary>
        /// Deserializes <see cref="HttpContent" /> into <typeparamref name="T" />.
        /// </summary>
        /// <typeparam name="T">The type to deserialize as.</typeparam>
        /// <param name="request">The <see cref="ISolidHttpRequest" /> that is being extended.</param>
        /// <returns>A <see cref="ValueTask{T}" /> of type <typeparamref name="T" />.</returns>
        public static ValueTask <T> As <T>(this ISolidHttpRequest request)
        {
            var provider = request.Services.GetService <DeserializerProvider>();

            return(request
                   .As(content => content.ReadAsAsync <T>(provider))
                   );
        }
コード例 #9
0
 /// <summary>
 /// Deserializes an XML <see cref="HttpContent" /> as <typeparamref name="T" /> using the
 /// specified serializer settings.
 /// </summary>
 /// <typeparam name="T">The type of response body.</typeparam>
 /// <param name="request">The <see cref="ISolidHttpRequest" /> that is being extended.</param>
 /// <param name="settings">The specified <see cref="DataContractSerializerSettings" />.</param>
 /// <returns><see cref="ValueTask{T}" /> of type <typeparamref name="T" /></returns>
 public static ValueTask <T> As <T>(this ISolidHttpRequest request, DataContractSerializerSettings settings)
 {
     return(request.As <T>((services, content) =>
     {
         var deserializer = services.GetService <DataContractXmlDeserializer>();
         return deserializer.DeserializeAsync <T>(content, settings);
     }));
 }
コード例 #10
0
 /// <summary>
 /// Adds a query parameter to the url of the <see cref="ISolidHttpRequest"/>.
 /// </summary>
 /// <param name="request">The <see cref="ISolidHttpRequest"/> that is being extended.</param>
 /// <param name="parameters">The query parameters to be added.</param>
 /// <returns>The <see cref="ISolidHttpRequest"/> so that additional calls can be chained.</returns>
 public static ISolidHttpRequest WithQueryParameters(this ISolidHttpRequest request, IDictionary <string, string> parameters)
 {
     foreach (var parameter in parameters)
     {
         request.WithQueryParameter(parameter.Key, parameter.Value, o => o.ConvertToStrings());
     }
     return(request);
 }
コード例 #11
0
 /// <summary>
 /// Adds headers to the <see cref="ISolidHttpRequest"/>.
 /// </summary>
 /// <param name="request">The <see cref="ISolidHttpRequest"/> that is being extended.</param>
 /// <param name="parameters">The headers to be added.</param>
 /// <returns>The <see cref="ISolidHttpRequest"/> so that additional calls can be chained.</returns>
 public static ISolidHttpRequest WithHeaders(this ISolidHttpRequest request, IDictionary <string, string> parameters)
 {
     foreach (var parameter in parameters)
     {
         request.WithHeader(parameter.Key, parameter.Value);
     }
     return(request);
 }
コード例 #12
0
        /// <summary>
        /// Replaces a templated parameter in the url
        /// </summary>
        /// <param name="request">The SolidHttpRequest</param>
        /// <param name="name">The name of the templated parameter</param>
        /// <param name="value">The value to inject</param>
        /// <returns>SolidHttpRequest</returns>
        public static ISolidHttpRequest WithNamedParameter(this ISolidHttpRequest request, string name, string value)
        {
            var url   = request.BaseRequest.RequestUri.OriginalString;
            var regex = new Regex($@"{{\s*{name}\s*}}");

            url = regex.Replace(url, value);
            request.BaseRequest.RequestUri = new Uri(url, UriKind.RelativeOrAbsolute);
            return(request);
        }
コード例 #13
0
 /// <summary>
 /// Deserializes a JSON <see cref="HttpContent" /> as <typeparamref name="T" /> using the
 /// specified serializer settings.
 /// </summary>
 /// <typeparam name="T">The type of response body.</typeparam>
 /// <param name="request">The <see cref="ISolidHttpRequest" /> that is being extended.</param>
 /// <param name="options">The specified <see cref="JsonSerializerOptions" />.</param>
 /// <returns><see cref="ValueTask{T}" /> of type <typeparamref name="T" /></returns>
 public static async ValueTask <T> As <T>(this ISolidHttpRequest request, JsonSerializerOptions options)
 {
     return(await request.As <T>(async content =>
     {
         using (var stream = await content.ReadAsStreamAsync())
         {
             return await JsonSerializer.DeserializeAsync <T>(stream, options);
         }
     }));
 }
コード例 #14
0
 /// <summary>
 /// Map a handler that is run on a specific condition defined by <paramref name="predicate" />.
 /// </summary>
 /// <param name="request">The <see cref="ISolidHttpRequest" /> that is being extended.</param>
 /// <param name="predicate">The predicate</param>
 /// <param name="handler">The handler to run when <paramref name ="predicate" /> returns true.</param>
 /// <returns>The <see cref="ISolidHttpRequest" /> so that additional calls can be chained.</returns>
 public static ISolidHttpRequest On(this ISolidHttpRequest request, Func <HttpResponseMessage, bool> predicate, Func <IServiceProvider, HttpResponseMessage, ValueTask> handler)
 {
     request.OnHttpResponse(async(services, response) =>
     {
         if (predicate(response))
         {
             await handler(services, response);
         }
     });
     return(request);
 }
コード例 #15
0
 /// <summary>
 /// Map a handler to a specific http status code
 /// </summary>
 /// <param name="request">The ISolidHttpRequest</param>
 /// <param name="predicate">The predicate</param>
 /// <param name="handler">The handler</param>
 /// <returns>SolidHttpRequest</returns>
 public static ISolidHttpRequest On(this ISolidHttpRequest request, Func <HttpResponseMessage, bool> predicate, Action <IServiceProvider, HttpResponseMessage> handler)
 {
     request.OnResponse((services, response) =>
     {
         if (predicate(response))
         {
             handler(services, response);
         }
     });
     return(request);
 }
コード例 #16
0
        private static MultipartFormDataContent GetMultipartFormDataContent(this ISolidHttpRequest request)
        {
            var multipart = request.BaseRequest.Content as MultipartFormDataContent;

            if (multipart == null)
            {
                multipart = request.WithMultipartContent(() => new MultipartFormDataContent()).BaseRequest.Content as MultipartFormDataContent;
            }

            return(multipart);
        }
コード例 #17
0
        /// <summary>
        /// Adds <see cref="HttpContent" /> to the inner <seealso cref="HttpRequestMessage" />.
        /// <para>If there is already <see cref="HttpContent" /> on the <seealso cref="HttpRequestMessage" />, it makes the request multipart.</para>
        /// </summary>
        /// <param name="request">The <see cref="ISolidHttpRequest" /> that is being extended.</param>
        /// <param name="content">The <see cref="HttpContent" /> to add to the <seealso cref="HttpRequestMessage" />.await</param>
        /// <returns>The <see cref="ISolidHttpRequest" /> so that additional calls can be chained.</returns>
        public static ISolidHttpRequest WithContent(this ISolidHttpRequest request, HttpContent content)
        {
            if (request.BaseRequest.Content == null)
            {
                request.BaseRequest.Content = content;
                return(request);
            }
            var multipart = request.WithMultipartContent(() => new MultipartContent()).BaseRequest.Content as MultipartContent;

            multipart.Add(content);
            return(request);
        }
コード例 #18
0
        /// <summary>
        /// Adds <see cref="StringContent" /> containing a json string of type <typeparamref name="T" />.
        /// </summary>
        /// <typeparam name="T">The type of body</typeparam>
        /// <param name="request">The <see cref="ISolidHttpRequest" /> that is being extended.</param>
        /// <param name="body">The request body object of type <typeparamref name="T" />.</param>
        /// <param name="contentType">(Optional) The content type header value.</param>
        /// <param name="settings">(Optional) <see cref="JsonSerializerSettings" /> to use to serialize the <paramref name="body" />..</param>
        /// <returns>The <see cref="ISolidHttpRequest" /> so that additional calls can be chained.</returns>
        public static ISolidHttpRequest WithNewtonsoftJsonContent <T>(this ISolidHttpRequest request, T body, string contentType = "application/json", JsonSerializerSettings settings = null)
        {
            if (settings == null)
            {
                settings = request.Services.GetService <IOptions <SolidHttpNewtonsoftJsonOptions> >().Value.SerializerSettings;
            }

            var json    = JsonConvert.SerializeObject(body, settings);
            var content = new StringContent(json, Encoding.UTF8, contentType);

            return(request.WithContent(content));
        }
コード例 #19
0
        /// <summary>
        /// Deserializes an ZIP <see cref="HttpContent" /> as <seealso cref="ZipArchive" />.
        /// </summary>
        /// <param name="request">The <see cref="ISolidHttpRequest" /> that is being extended.</param>
        /// <param name="mode">(Optional) The specified <see cref="ZipArchiveMode" />.</param>
        /// <returns><see cref="ValueTask{T}" /> of type <see cref="ZipArchive" /></returns>
        public static ValueTask <ZipArchive> AsZipArchive(this ISolidHttpRequest request, ZipArchiveMode?mode = null)
        {
            if (!mode.HasValue)
            {
                return(request.As <ZipArchive>());
            }

            return(request.As <ZipArchive>((services, content) =>
            {
                var deserializer = services.GetService <ZipArchiveDeserializer>();
                return deserializer.DeserializeAsync(content, mode.Value);
            }));
        }
コード例 #20
0
 /// <summary>
 /// Expect a success status code
 /// <para>If a non-success status code is received, an InvalidOperationException is thrown</para>
 /// </summary>
 /// <param name="request">The ISolidHttpRequest</param>
 /// <returns>SolidHttpRequest</returns>
 public static ISolidHttpRequest ExpectSuccess(this ISolidHttpRequest request)
 {
     request.OnResponse(async(services, response) =>
     {
         if (!response.IsSuccessStatusCode)
         {
             var message = await GenerateNonSuccessMessage(response);
             // TODO: reevaluate this exception type. maybe a seperate type for server error and client error
             throw new InvalidOperationException(message);
         }
     });
     return(request);
 }
コード例 #21
0
        private static void OnRequestCreated(IServiceProvider services, ISolidHttpRequest request)
        {
            var baseAddress = request.Client.GetProperty <Uri>("Client::BaseAddress");

            if (baseAddress == null)
            {
                return;
            }

            var url = new Uri(baseAddress, request.BaseRequest.RequestUri);

            request.BaseRequest.RequestUri = url;
        }
コード例 #22
0
        /// <summary>
        /// Deserializes a JSON <see cref="HttpContent" /> as <typeparamref name="T" /> using the
        /// specified serializer settings.
        /// </summary>
        /// <typeparam name="T">The type of response body.</typeparam>
        /// <param name="request">The <see cref="ISolidHttpRequest" /> that is being extended.</param>
        /// <param name="settings">The specified <see cref="JsonSerializerSettings" />.</param>
        /// <returns><see cref="ValueTask{T}" /> of type <typeparamref name="T" /></returns>
        public static async ValueTask <T> As <T>(this ISolidHttpRequest request, JsonSerializerSettings settings)
        {
            if (settings == null)
            {
                settings = request.Services.GetService <IOptions <SolidHttpNewtonsoftJsonOptions> >().Value.SerializerSettings;
            }

            return(await request.As <T>(async content =>
            {
                var json = await content.ReadAsStringAsync();
                return JsonConvert.DeserializeObject <T>(json, settings);
            }));
        }
コード例 #23
0
        /// <summary>
        /// Deserializes the response content using a specified deserializer
        /// </summary>
        /// <typeparam name="T">The type to deserialize to</typeparam>
        /// <param name="request">The ISolidHttpRequest</param>
        /// <param name="deserialize">The deserialization method</param>
        /// <returns>Task of type T</returns>
        public static async Task <T> As <T>(this ISolidHttpRequest request, Func <HttpContent, Task <T> > deserialize)
        {
            var content = await request.GetContentAsync();

            if (content == null)
            {
                return(default(T));                 // should we maybe throw an exception if there is no content?
            }
            if (request.BaseRequest.Properties.ContainsKey(IgnoreSerializationErrorKey))
            {
                return(await SafeDeserializeAsync(() => deserialize(content)));
            }
            return(await deserialize(content));
        }
コード例 #24
0
        /// <summary>
        /// Adds StringContent containing a json string of the supplied body object
        /// </summary>
        /// <typeparam name="T">The type of body</typeparam>
        /// <param name="request">The SolidHttpRequest</param>
        /// <param name="body">The request body object</param>
        /// <param name="settings">(Optional) DataContractSerializerSettings to use to serialize the body object</param>
        /// <returns>SolidHttpRequest</returns>
        public static ISolidHttpRequest WithXmlContent <T>(this ISolidHttpRequest request, T body, DataContractSerializerSettings settings = null)
        {
            using (var ms = new MemoryStream())
            {
                var ser = new DataContractSerializer(typeof(T), settings ?? request.GetXmlSerializerSettings());
                ser.WriteObject(ms, body);
                ms.Position = 0;

                using (var reader = new StreamReader(ms))
                {
                    var content = new StringContent(reader.ReadToEnd(), Encoding.UTF8, "application/xml");
                    return(request.WithContent(content));
                }
            }
        }
コード例 #25
0
        /// <summary>
        /// Adds <see cref="StreamContent" /> containing UTF-8 serialized JSON of type <typeparamref name="T" />.
        /// </summary>
        /// <typeparam name="T">The type of body</typeparam>
        /// <param name="request">The <see cref="ISolidHttpRequest" /> that is being extended.</param>
        /// <param name="body">The request body object of type <typeparamref name="T" />.</param>
        /// <param name="contentType">(Optional) The content type header value.</param>
        /// <param name="options">(Optional) <see cref="JsonSerializerOptions" /> to use to serialize the <paramref name="body" />..</param>
        /// <returns>The <see cref="ISolidHttpRequest" /> so that additional calls can be chained.</returns>
        public static ISolidHttpRequest WithJsonContent <T>(this ISolidHttpRequest request, T body, string contentType = "application/json", JsonSerializerOptions options = null)
        {
            if (options == null)
            {
                options = request.Services.GetService <IOptions <SolidHttpJsonOptions> >().Value.SerializerOptions;
            }

            var bytes   = JsonSerializer.SerializeToUtf8Bytes <T>(body, options);
            var stream  = new MemoryStream(bytes);
            var content = new StreamContent(stream);

            content.Headers.ContentType = new MediaTypeHeaderValue(contentType)
            {
                CharSet = "utf-8"
            };
            return(request.WithContent(content));
        }
コード例 #26
0
        /// <summary>
        /// Adds a query parameter to the url
        /// </summary>
        /// <param name="request">The SolidHttpRequest</param>
        /// <param name="name">The name of the query parameter</param>
        /// <param name="values">The value of the query parameter</param>
        /// <returns></returns>
        public static ISolidHttpRequest WithQueryParameter(this ISolidHttpRequest request, string name, StringValues values)
        {
            var url = request.BaseRequest.RequestUri.OriginalString;

            foreach (var value in values)
            {
                if (url.Contains("?"))
                {
                    url += $"&{name}={value}";
                }
                else
                {
                    url += $"?{name}={value}";
                }
            }
            request.BaseRequest.RequestUri = new Uri(url, UriKind.RelativeOrAbsolute);
            return(request);
        }
コード例 #27
0
        /// <summary>
        /// Adds a query parameter to the url.
        /// </summary>
        /// <param name="request">The <see cref="ISolidHttpRequest"/> that is being extended.</param>
        /// <param name="name">The name of the query parameter</param>
        /// <param name="value">The value of the query parameter.</param>
        /// <param name="convert">A converter used to convert the <paramref name="value"/> to an <see cref="IEnumerable{T}"/> of <seealso cref="string"/>.</param>
        /// <returns>The <see cref="ISolidHttpRequest"/> so that additional calls can be chained.</returns>
        public static ISolidHttpRequest WithQueryParameter(this ISolidHttpRequest request, string name, object value, Func <object, IEnumerable <string> > convert)
        {
            var url    = request.BaseRequest.RequestUri.OriginalString;
            var values = convert(value);

            foreach (var v in values)
            {
                if (url.Contains("?"))
                {
                    url += $"&{name}={v}";
                }
                else
                {
                    url += $"?{name}={v}";
                }
            }
            request.BaseRequest.RequestUri = new Uri(url, UriKind.RelativeOrAbsolute);
            return(request);
        }
コード例 #28
0
 /// <summary>
 /// Expect a success status code.
 /// <para>If a status code  in the 400 range is received, a <see cref="ClientErrorException" /> is thrown.</para>
 /// <para>If a status code  in the 500 range is received, a <see cref="ServerErrorException" /> is thrown.</para>
 /// </summary>
 /// <param name="request">The <see cref="ISolidHttpRequest" /> that is being extended.</param>
 /// <returns>The <see cref="ISolidHttpRequest" /> so that additional calls can be chained.</returns>
 public static ISolidHttpRequest ExpectSuccess(this ISolidHttpRequest request)
 {
     request.OnHttpResponse(async(services, response) =>
     {
         if (!response.IsSuccessStatusCode)
         {
             var message = await GenerateNonSuccessMessage(response);
             if ((int)response.StatusCode < 500)
             {
                 throw new ClientErrorException(message);
             }
             else
             {
                 throw new ServerErrorException(message);
             }
         }
     });
     return(request);
 }
コード例 #29
0
        /// <summary>
        /// Adds <see cref="StreamContent" /> containing UTF-8 serialized XML of type <typeparamref name="T" />.
        /// </summary>
        /// <typeparam name="T">The type of body</typeparam>
        /// <param name="request">The <see cref="ISolidHttpRequest" /> that is being extended.</param>
        /// <param name="body">The request body object of type <typeparamref name="T" />.</param>
        /// <param name="contentType">(Optional) The content type header value.</param>
        /// <param name="settings">(Optional) <see cref="DataContractSerializerSettings" /> to use to serialize the <paramref name="body" />.</param>
        /// <returns>The <see cref="ISolidHttpRequest" /> so that additional calls can be chained.</returns>
        public static ISolidHttpRequest WithXmlContent <T>(this ISolidHttpRequest request, T body, string contentType = "application/xml", DataContractSerializerSettings settings = null)
        {
            if (settings == null)
            {
                settings = request.Services.GetService <IOptions <SolidHttpXmlOptions> >().Value.SerializerSettings;
            }

            var stream     = new MemoryStream();
            var serializer = new DataContractSerializer(typeof(T), settings);

            serializer.WriteObject(stream, body);
            stream.Position = 0;

            var content = new StreamContent(stream);

            content.Headers.ContentType = new MediaTypeHeaderValue(contentType)
            {
                CharSet = "utf-8"
            };
            return(request.WithContent(content));
        }
コード例 #30
0
        /// <summary>
        /// Deserializes the response content
        /// </summary>
        /// <typeparam name="T">The type to deserialize to</typeparam>
        /// <param name="request">The ISolidHttpRequest</param>
        /// <returns>Task of type T</returns>
        public static async Task <T> As <T>(this ISolidHttpRequest request)
        {
            var content = await request.GetContentAsync();

            if (content == null)
            {
                return(default(T));                 // should we maybe throw an exception if there is no content?
            }
            var mime = content?.Headers?.ContentType?.MediaType;

            var deserializer = request.Client.Deserializers.FirstOrDefault(d => d.CanDeserialize(mime));

            if (deserializer == null)
            {
                throw new InvalidOperationException($"Cannot deserialize {mime} response as {typeof(T).FullName}");
            }
            if (request.BaseRequest.Properties.ContainsKey(IgnoreSerializationErrorKey))
            {
                return(await SafeDeserializeAsync(() => deserializer.DeserializeAsync <T>(content)));
            }
            return(await deserializer.DeserializeAsync <T>(content));
        }