/// <summary> /// API post using multipart/form-data. /// </summary> /// <param name="application">The full Uri you want to call (including any get parameters)</param> /// <param name="getParameters">Get parameters (or null if none)</param> /// <param name="postParameters">Post parameters as an object or JObject /// </param> /// <returns>The result as a JObject, with MetaData filled in.</returns> public async Task <JObject> PostFormAsync(string application, object getParameters, object postParameters, params string[] fileParameterNames) { string uri = AddGetParams(MakeUri(application), getParameters); using (DisposableCollection objectsToDispose = new DisposableCollection()) { MultipartFormDataContent content = objectsToDispose.Add(new MultipartFormDataContent()); JObject data = postParameters.ToJObject(); foreach (var o in data) { if (o.Value.Type == JTokenType.Null) { continue; } if (Array.IndexOf(fileParameterNames, o.Key) >= 0) { string filename = o.Value.ToString(); FileStream fs = objectsToDispose.Add(new FileStream(filename, FileMode.Open)); HttpContent v = objectsToDispose.Add(new StreamContent(fs)); content.Add(v, o.Key, Path.GetFileName(filename)); } else { HttpContent v = objectsToDispose.Add(new StringContent(o.Value.ToString())); content.Add(v, o.Key); } } return(await SendMessageAsync(HttpMethod.Post, uri, content)); } }
/// <summary> /// Send a message and get the result. /// Deal with rate limiting return values and redirects. /// </summary> /// <param name="method">Get/Post/etc.</param> /// <param name="uri">The full Uri you want to call (including any get parameters)</param> /// <param name="postParameters">Post parameters as an object or JObject</param> public async Task <HttpResponseMessage> SendMessageAsyncAndGetResponse(HttpMethod method, string uri, object postParameters = null, object headerParameters = null) { LastRequest = ""; LastResponse = ""; for (; ;) { string content = null; using (DisposableCollection disposeMe = new DisposableCollection()) { var message = disposeMe.Add(new HttpRequestMessage(method, uri)); if (!string.IsNullOrEmpty(Settings.Username) && !string.IsNullOrEmpty(Settings.Password)) { message.Headers.Authorization = new AuthenticationHeaderValue("Basic", basicAuth()); } else if (!string.IsNullOrEmpty(Settings.AccessToken)) { message.Headers.Authorization = new AuthenticationHeaderValue("Bearer", Settings.AccessToken); } message.Headers.Add("OCS-APIRequest", "true"); message.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); message.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("text/html")); message.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("*/*")); message.Headers.Add("User-Agent", Settings.ApplicationName); if (headerParameters != null) { foreach (var h in headerParameters.ToCollection()) { message.Headers.Add(h.Key, h.Value); } } if (postParameters != null) { if (postParameters is Stream f) { message.Content = disposeMe.Add(new StreamContent(f)); message.Content.Headers.ContentLength = f.Length; f.Position = 0; if (f is FileStream) { content = Path.GetFileName((f as FileStream).Name); string contentType = MimeMapping.MimeUtility.GetMimeMapping(content); message.Content.Headers.ContentType = new MediaTypeHeaderValue(contentType); message.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = content }; content = "File: " + content; } else { content = "Stream"; } } else if (postParameters is HttpContent) { message.Content = (HttpContent)postParameters; } else if (postParameters is XElement || postParameters is XDocument) { content = postParameters.ToString(); message.Content = disposeMe.Add(new StringContent(content)); } else { content = postParameters.ToJson(); message.Content = disposeMe.Add(new StringContent(content, Encoding.UTF8, "application/json")); // message.Content = disposeMe.Add(new FormUrlEncodedContent(postParameters.ToCollection())); } } LastRequest = $"{message}:{content}"; HttpResponseMessage result; int backoff = 500; int delay; if (Settings.LogRequest > 0) { Log($"Sent -> {(Settings.LogRequest > 1 ? message.ToString() : message.RequestUri.ToString())}:{content}"); } result = await _client.SendAsync(message); LastResponse = result.ToString(); if (Settings.LogResult > 1) { Log($"Received -> {result}"); } switch (result.StatusCode) { case HttpStatusCode.Found: // Redirect uri = result.Headers.Location.AbsoluteUri; delay = 1; break; case (HttpStatusCode)429: // TooManyRequests delay = 5000; break; case HttpStatusCode.BadGateway: case HttpStatusCode.ServiceUnavailable: case HttpStatusCode.GatewayTimeout: backoff *= 2; delay = backoff; if (delay > 16000) { return(result); } break; default: return(result); } result.Dispose(); Thread.Sleep(delay); } } }