/* * MultipartFile test * * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * * The version of the OpenAPI document: 1.0.0 * Generated by: https://github.com/openapitools/openapi-generator.git */ using System; using System.Collections; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; using System.Net; using System.Reflection; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters; using System.Text; using System.Threading; using System.Text.RegularExpressions; using System.Threading.Tasks; using System.Web; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; using RestSharp; using RestSharp.Serializers; using RestSharpMethod = RestSharp.Method; using FileIO = System.IO.File; using Polly; using Org.OpenAPITools.Model; namespace Org.OpenAPITools.Client { /// /// Allows RestSharp to Serialize/Deserialize JSON using our custom logic, but only when ContentType is JSON. /// internal class CustomJsonCodec : IRestSerializer, ISerializer, IDeserializer { private readonly IReadableConfiguration _configuration; private readonly JsonSerializerSettings _serializerSettings = new JsonSerializerSettings { // OpenAPI generated types generally hide default constructors. ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor, ContractResolver = new DefaultContractResolver { NamingStrategy = new CamelCaseNamingStrategy { OverrideSpecifiedNames = false } } }; public CustomJsonCodec(IReadableConfiguration configuration) { _configuration = configuration; } public CustomJsonCodec(JsonSerializerSettings serializerSettings, IReadableConfiguration configuration) { _serializerSettings = serializerSettings; _configuration = configuration; } /// /// Serialize the object into a JSON string. /// /// Object to be serialized. /// A JSON string. public string Serialize(object obj) { if (obj != null && obj is AbstractOpenAPISchema) { // the object to be serialized is an oneOf/anyOf schema return ((AbstractOpenAPISchema)obj).ToJson(); } else { return JsonConvert.SerializeObject(obj, _serializerSettings); } } public string Serialize(Parameter bodyParameter) => Serialize(bodyParameter.Value); public T Deserialize(RestResponse response) { var result = (T)Deserialize(response, typeof(T)); return result; } /// /// Deserialize the JSON string into a proper object. /// /// The HTTP response. /// Object type. /// Object representation of the JSON string. internal object Deserialize(RestResponse response, Type type) { if (type == typeof(byte[])) // return byte array { return response.RawBytes; } // TODO: ? if (type.IsAssignableFrom(typeof(Stream))) if (type == typeof(Stream)) { var bytes = response.RawBytes; if (response.Headers != null) { var filePath = string.IsNullOrEmpty(_configuration.TempFolderPath) ? global::System.IO.Path.GetTempPath() : _configuration.TempFolderPath; var regex = new Regex(@"Content-Disposition=.*filename=['""]?([^'""\s]+)['""]?$"); foreach (var header in response.Headers) { var match = regex.Match(header.ToString()); if (match.Success) { string fileName = filePath + ClientUtils.SanitizeFilename(match.Groups[1].Value.Replace("\"", "").Replace("'", "")); FileIO.WriteAllBytes(fileName, bytes); return new FileStream(fileName, FileMode.Open); } } } var stream = new MemoryStream(bytes); return stream; } if (type.Name.StartsWith("System.Nullable`1[[System.DateTime")) // return a datetime object { return DateTime.Parse(response.Content, null, DateTimeStyles.RoundtripKind); } if (type == typeof(string) || type.Name.StartsWith("System.Nullable")) // return primitive type { return Convert.ChangeType(response.Content, type); } // at this point, it must be a model (json) try { return JsonConvert.DeserializeObject(response.Content, type, _serializerSettings); } catch (Exception e) { throw new ApiException(500, e.Message); } } public ISerializer Serializer => this; public IDeserializer Deserializer => this; public string[] AcceptedContentTypes => ContentType.JsonAccept; public SupportsContentType SupportsContentType => contentType => contentType.Value.EndsWith("json", StringComparison.InvariantCultureIgnoreCase) || contentType.Value.EndsWith("javascript", StringComparison.InvariantCultureIgnoreCase); public ContentType ContentType { get; set; } = ContentType.Json; public DataFormat DataFormat => DataFormat.Json; } /// /// Provides a default implementation of an Api client (both synchronous and asynchronous implementations), /// encapsulating general REST accessor use cases. /// public partial class ApiClient : ISynchronousClient, IAsynchronousClient { private readonly string _baseUrl; /// /// Specifies the settings on a object. /// These settings can be adjusted to accommodate custom serialization rules. /// public JsonSerializerSettings SerializerSettings { get; set; } = new JsonSerializerSettings { // OpenAPI generated types generally hide default constructors. ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor, ContractResolver = new DefaultContractResolver { NamingStrategy = new CamelCaseNamingStrategy { OverrideSpecifiedNames = false } } }; /// /// Allows for extending request processing for generated code. /// /// The RestSharp request object partial void InterceptRequest(RestRequest request); /// /// Allows for extending response processing for generated code. /// /// The RestSharp request object /// The RestSharp response object partial void InterceptResponse(RestRequest request, RestResponse response); /// /// Initializes a new instance of the , defaulting to the global configurations' base url. /// public ApiClient() { _baseUrl = GlobalConfiguration.Instance.BasePath; } /// /// Initializes a new instance of the /// /// The target service's base path in URL format. /// public ApiClient(string basePath) { if (string.IsNullOrEmpty(basePath)) throw new ArgumentException("basePath cannot be empty"); _baseUrl = basePath; } /// /// Constructs the RestSharp version of an http method /// /// Swagger Client Custom HttpMethod /// RestSharp's HttpMethod instance. /// private RestSharpMethod Method(HttpMethod method) { RestSharpMethod other; switch (method) { case HttpMethod.Get: other = RestSharpMethod.Get; break; case HttpMethod.Post: other = RestSharpMethod.Post; break; case HttpMethod.Put: other = RestSharpMethod.Put; break; case HttpMethod.Delete: other = RestSharpMethod.Delete; break; case HttpMethod.Head: other = RestSharpMethod.Head; break; case HttpMethod.Options: other = RestSharpMethod.Options; break; case HttpMethod.Patch: other = RestSharpMethod.Patch; break; default: throw new ArgumentOutOfRangeException("method", method, null); } return other; } /// /// Provides all logic for constructing a new RestSharp . /// At this point, all information for querying the service is known. /// Here, it is simply mapped into the RestSharp request. /// /// The http verb. /// The target path (or resource). /// The additional request options. /// A per-request configuration object. /// It is assumed that any merge with GlobalConfiguration has been done before calling this method. /// [private] A new RestRequest instance. /// private RestRequest NewRequest( HttpMethod method, string path, RequestOptions options, IReadableConfiguration configuration) { if (path == null) throw new ArgumentNullException("path"); if (options == null) throw new ArgumentNullException("options"); if (configuration == null) throw new ArgumentNullException("configuration"); RestRequest request = new RestRequest(path, Method(method)); if (options.PathParameters != null) { foreach (var pathParam in options.PathParameters) { request.AddParameter(pathParam.Key, pathParam.Value, ParameterType.UrlSegment); } } if (options.QueryParameters != null) { foreach (var queryParam in options.QueryParameters) { foreach (var value in queryParam.Value) { request.AddQueryParameter(queryParam.Key, value); } } } if (configuration.DefaultHeaders != null) { foreach (var headerParam in configuration.DefaultHeaders) { request.AddHeader(headerParam.Key, headerParam.Value); } } if (options.HeaderParameters != null) { foreach (var headerParam in options.HeaderParameters) { foreach (var value in headerParam.Value) { request.AddHeader(headerParam.Key, value); } } } if (options.FormParameters != null) { foreach (var formParam in options.FormParameters) { request.AddParameter(formParam.Key, formParam.Value); } } if (options.Data != null) { if (options.Data is Stream stream) { var contentType = "application/octet-stream"; if (options.HeaderParameters != null) { var contentTypes = options.HeaderParameters["Content-Type"]; contentType = contentTypes[0]; } var bytes = ClientUtils.ReadAsBytes(stream); request.AddParameter(contentType, bytes, ParameterType.RequestBody); } else { if (options.HeaderParameters != null) { var contentTypes = options.HeaderParameters["Content-Type"]; if (contentTypes == null || contentTypes.Any(header => header.Contains("application/json"))) { request.RequestFormat = DataFormat.Json; } else { // TODO: Generated client user should add additional handlers. RestSharp only supports XML and JSON, with XML as default. } } else { // Here, we'll assume JSON APIs are more common. XML can be forced by adding produces/consumes to openapi spec explicitly. request.RequestFormat = DataFormat.Json; } request.AddJsonBody(options.Data); } } if (options.FileParameters != null) { foreach (var fileParam in options.FileParameters) { foreach (var file in fileParam.Value) { var bytes = ClientUtils.ReadAsBytes(file); var fileStream = file as FileStream; if (fileStream != null) request.AddFile(fileParam.Key, bytes, global::System.IO.Path.GetFileName(fileStream.Name)); else request.AddFile(fileParam.Key, bytes, "no_file_name_provided"); } } } return request; } /// /// Transforms a RestResponse instance into a new ApiResponse instance. /// At this point, we have a concrete http response from the service. /// Here, it is simply mapped into the [public] ApiResponse object. /// /// The RestSharp response object /// A new ApiResponse instance. private ApiResponse ToApiResponse(RestResponse response) { T result = response.Data; string rawContent = response.Content; var transformed = new ApiResponse(response.StatusCode, new Multimap(), result, rawContent) { ErrorText = response.ErrorMessage, Cookies = new List() }; if (response.Headers != null) { foreach (var responseHeader in response.Headers) { transformed.Headers.Add(responseHeader.Name, ClientUtils.ParameterToString(responseHeader.Value)); } } if (response.ContentHeaders != null) { foreach (var responseHeader in response.ContentHeaders) { transformed.Headers.Add(responseHeader.Name, ClientUtils.ParameterToString(responseHeader.Value)); } } if (response.Cookies != null) { foreach (var responseCookies in response.Cookies.Cast()) { transformed.Cookies.Add( new Cookie( responseCookies.Name, responseCookies.Value, responseCookies.Path, responseCookies.Domain) ); } } return transformed; } /// /// Executes the HTTP request for the current service. /// Based on functions received it can be async or sync. /// /// Local function that executes http request and returns http response. /// Local function to specify options for the service. /// The RestSharp request object /// The RestSharp options object /// A per-request configuration object. /// It is assumed that any merge with GlobalConfiguration has been done before calling this method. /// A new ApiResponse instance. private async Task> ExecClientAsync(Func>> getResponse, Action setOptions, RestRequest request, RequestOptions options, IReadableConfiguration configuration) { var baseUrl = configuration.GetOperationServerUrl(options.Operation, options.OperationIndex) ?? _baseUrl; var clientOptions = new RestClientOptions(baseUrl) { ClientCertificates = configuration.ClientCertificates, MaxTimeout = configuration.Timeout, Proxy = configuration.Proxy, UserAgent = configuration.UserAgent, UseDefaultCredentials = configuration.UseDefaultCredentials, RemoteCertificateValidationCallback = configuration.RemoteCertificateValidationCallback }; setOptions(clientOptions); using (RestClient client = new RestClient(clientOptions, configureSerialization: serializerConfig => serializerConfig.UseSerializer(() => new CustomJsonCodec(SerializerSettings, configuration)))) { InterceptRequest(request); RestResponse response = await getResponse(client); // if the response type is oneOf/anyOf, call FromJSON to deserialize the data if (typeof(AbstractOpenAPISchema).IsAssignableFrom(typeof(T))) { try { response.Data = (T)typeof(T).GetMethod("FromJson").Invoke(null, new object[] { response.Content }); } catch (Exception ex) { throw ex.InnerException != null ? ex.InnerException : ex; } } else if (typeof(T).Name == "Stream") // for binary response { response.Data = (T)(object)new MemoryStream(response.RawBytes); } else if (typeof(T).Name == "Byte[]") // for byte response { response.Data = (T)(object)response.RawBytes; } else if (typeof(T).Name == "String") // for string response { response.Data = (T)(object)response.Content; } InterceptResponse(request, response); var result = ToApiResponse(response); if (response.ErrorMessage != null) { result.ErrorText = response.ErrorMessage; } if (response.Cookies != null && response.Cookies.Count > 0) { if (result.Cookies == null) result.Cookies = new List(); foreach (var restResponseCookie in response.Cookies.Cast()) { var cookie = new Cookie( restResponseCookie.Name, restResponseCookie.Value, restResponseCookie.Path, restResponseCookie.Domain ) { Comment = restResponseCookie.Comment, CommentUri = restResponseCookie.CommentUri, Discard = restResponseCookie.Discard, Expired = restResponseCookie.Expired, Expires = restResponseCookie.Expires, HttpOnly = restResponseCookie.HttpOnly, Port = restResponseCookie.Port, Secure = restResponseCookie.Secure, Version = restResponseCookie.Version }; result.Cookies.Add(cookie); } } return result; } } private async Task> DeserializeRestResponseFromPolicyAsync(RestClient client, RestRequest request, PolicyResult policyResult, CancellationToken cancellationToken = default) { if (policyResult.Outcome == OutcomeType.Successful) { return await client.Deserialize(policyResult.Result, cancellationToken); } else { return new RestResponse(request) { ErrorException = policyResult.FinalException }; } } private ApiResponse Exec(RestRequest request, RequestOptions options, IReadableConfiguration configuration) { Action setOptions = (clientOptions) => { var cookies = new CookieContainer(); if (options.Cookies != null && options.Cookies.Count > 0) { foreach (var cookie in options.Cookies) { cookies.Add(new Cookie(cookie.Name, cookie.Value)); } } clientOptions.CookieContainer = cookies; }; Func>> getResponse = (client) => { if (RetryConfiguration.RetryPolicy != null) { var policy = RetryConfiguration.RetryPolicy; var policyResult = policy.ExecuteAndCapture(() => client.Execute(request)); return DeserializeRestResponseFromPolicyAsync(client, request, policyResult); } else { return Task.FromResult(client.Execute(request)); } }; return ExecClientAsync(getResponse, setOptions, request, options, configuration).GetAwaiter().GetResult(); } private Task> ExecAsync(RestRequest request, RequestOptions options, IReadableConfiguration configuration, CancellationToken cancellationToken = default(CancellationToken)) { Action setOptions = (clientOptions) => { //no extra options }; Func>> getResponse = async (client) => { if (RetryConfiguration.AsyncRetryPolicy != null) { var policy = RetryConfiguration.AsyncRetryPolicy; var policyResult = await policy.ExecuteAndCaptureAsync((ct) => client.ExecuteAsync(request, ct), cancellationToken).ConfigureAwait(false); return await DeserializeRestResponseFromPolicyAsync(client, request, policyResult, cancellationToken); } else { return await client.ExecuteAsync(request, cancellationToken).ConfigureAwait(false); } }; return ExecClientAsync(getResponse, setOptions, request, options, configuration); } #region IAsynchronousClient /// /// Make a HTTP GET request (async). /// /// The target path (or resource). /// The additional request options. /// A per-request configuration object. It is assumed that any merge with /// GlobalConfiguration has been done before calling this method. /// Token that enables callers to cancel the request. /// A Task containing ApiResponse public Task> GetAsync(string path, RequestOptions options, IReadableConfiguration configuration = null, CancellationToken cancellationToken = default) { var config = configuration ?? GlobalConfiguration.Instance; return ExecAsync(NewRequest(HttpMethod.Get, path, options, config), options, config, cancellationToken); } /// /// Make a HTTP POST request (async). /// /// The target path (or resource). /// The additional request options. /// A per-request configuration object. It is assumed that any merge with /// GlobalConfiguration has been done before calling this method. /// Token that enables callers to cancel the request. /// A Task containing ApiResponse public Task> PostAsync(string path, RequestOptions options, IReadableConfiguration configuration = null, CancellationToken cancellationToken = default) { var config = configuration ?? GlobalConfiguration.Instance; return ExecAsync(NewRequest(HttpMethod.Post, path, options, config), options, config, cancellationToken); } /// /// Make a HTTP PUT request (async). /// /// The target path (or resource). /// The additional request options. /// A per-request configuration object. It is assumed that any merge with /// GlobalConfiguration has been done before calling this method. /// Token that enables callers to cancel the request. /// A Task containing ApiResponse public Task> PutAsync(string path, RequestOptions options, IReadableConfiguration configuration = null, CancellationToken cancellationToken = default) { var config = configuration ?? GlobalConfiguration.Instance; return ExecAsync(NewRequest(HttpMethod.Put, path, options, config), options, config, cancellationToken); } /// /// Make a HTTP DELETE request (async). /// /// The target path (or resource). /// The additional request options. /// A per-request configuration object. It is assumed that any merge with /// GlobalConfiguration has been done before calling this method. /// Token that enables callers to cancel the request. /// A Task containing ApiResponse public Task> DeleteAsync(string path, RequestOptions options, IReadableConfiguration configuration = null, CancellationToken cancellationToken = default) { var config = configuration ?? GlobalConfiguration.Instance; return ExecAsync(NewRequest(HttpMethod.Delete, path, options, config), options, config, cancellationToken); } /// /// Make a HTTP HEAD request (async). /// /// The target path (or resource). /// The additional request options. /// A per-request configuration object. It is assumed that any merge with /// GlobalConfiguration has been done before calling this method. /// Token that enables callers to cancel the request. /// A Task containing ApiResponse public Task> HeadAsync(string path, RequestOptions options, IReadableConfiguration configuration = null, CancellationToken cancellationToken = default) { var config = configuration ?? GlobalConfiguration.Instance; return ExecAsync(NewRequest(HttpMethod.Head, path, options, config), options, config, cancellationToken); } /// /// Make a HTTP OPTION request (async). /// /// The target path (or resource). /// The additional request options. /// A per-request configuration object. It is assumed that any merge with /// GlobalConfiguration has been done before calling this method. /// Token that enables callers to cancel the request. /// A Task containing ApiResponse public Task> OptionsAsync(string path, RequestOptions options, IReadableConfiguration configuration = null, CancellationToken cancellationToken = default) { var config = configuration ?? GlobalConfiguration.Instance; return ExecAsync(NewRequest(HttpMethod.Options, path, options, config), options, config, cancellationToken); } /// /// Make a HTTP PATCH request (async). /// /// The target path (or resource). /// The additional request options. /// A per-request configuration object. It is assumed that any merge with /// GlobalConfiguration has been done before calling this method. /// Token that enables callers to cancel the request. /// A Task containing ApiResponse public Task> PatchAsync(string path, RequestOptions options, IReadableConfiguration configuration = null, CancellationToken cancellationToken = default) { var config = configuration ?? GlobalConfiguration.Instance; return ExecAsync(NewRequest(HttpMethod.Patch, path, options, config), options, config, cancellationToken); } #endregion IAsynchronousClient #region ISynchronousClient /// /// Make a HTTP GET request (synchronous). /// /// The target path (or resource). /// The additional request options. /// A per-request configuration object. It is assumed that any merge with /// GlobalConfiguration has been done before calling this method. /// A Task containing ApiResponse public ApiResponse Get(string path, RequestOptions options, IReadableConfiguration configuration = null) { var config = configuration ?? GlobalConfiguration.Instance; return Exec(NewRequest(HttpMethod.Get, path, options, config), options, config); } /// /// Make a HTTP POST request (synchronous). /// /// The target path (or resource). /// The additional request options. /// A per-request configuration object. It is assumed that any merge with /// GlobalConfiguration has been done before calling this method. /// A Task containing ApiResponse public ApiResponse Post(string path, RequestOptions options, IReadableConfiguration configuration = null) { var config = configuration ?? GlobalConfiguration.Instance; return Exec(NewRequest(HttpMethod.Post, path, options, config), options, config); } /// /// Make a HTTP PUT request (synchronous). /// /// The target path (or resource). /// The additional request options. /// A per-request configuration object. It is assumed that any merge with /// GlobalConfiguration has been done before calling this method. /// A Task containing ApiResponse public ApiResponse Put(string path, RequestOptions options, IReadableConfiguration configuration = null) { var config = configuration ?? GlobalConfiguration.Instance; return Exec(NewRequest(HttpMethod.Put, path, options, config), options, config); } /// /// Make a HTTP DELETE request (synchronous). /// /// The target path (or resource). /// The additional request options. /// A per-request configuration object. It is assumed that any merge with /// GlobalConfiguration has been done before calling this method. /// A Task containing ApiResponse public ApiResponse Delete(string path, RequestOptions options, IReadableConfiguration configuration = null) { var config = configuration ?? GlobalConfiguration.Instance; return Exec(NewRequest(HttpMethod.Delete, path, options, config), options, config); } /// /// Make a HTTP HEAD request (synchronous). /// /// The target path (or resource). /// The additional request options. /// A per-request configuration object. It is assumed that any merge with /// GlobalConfiguration has been done before calling this method. /// A Task containing ApiResponse public ApiResponse Head(string path, RequestOptions options, IReadableConfiguration configuration = null) { var config = configuration ?? GlobalConfiguration.Instance; return Exec(NewRequest(HttpMethod.Head, path, options, config), options, config); } /// /// Make a HTTP OPTION request (synchronous). /// /// The target path (or resource). /// The additional request options. /// A per-request configuration object. It is assumed that any merge with /// GlobalConfiguration has been done before calling this method. /// A Task containing ApiResponse public ApiResponse Options(string path, RequestOptions options, IReadableConfiguration configuration = null) { var config = configuration ?? GlobalConfiguration.Instance; return Exec(NewRequest(HttpMethod.Options, path, options, config), options, config); } /// /// Make a HTTP PATCH request (synchronous). /// /// The target path (or resource). /// The additional request options. /// A per-request configuration object. It is assumed that any merge with /// GlobalConfiguration has been done before calling this method. /// A Task containing ApiResponse public ApiResponse Patch(string path, RequestOptions options, IReadableConfiguration configuration = null) { var config = configuration ?? GlobalConfiguration.Instance; return Exec(NewRequest(HttpMethod.Patch, path, options, config), options, config); } #endregion ISynchronousClient } }