async Task <DurableHttpResponse> IDurableOrchestrationContext.CallHttpAsync(DurableHttpRequest req) { DurableHttpResponse durableHttpResponse = await this.ScheduleDurableHttpActivityAsync(req); HttpStatusCode currStatusCode = durableHttpResponse.StatusCode; while (currStatusCode == HttpStatusCode.Accepted && req.AsynchronousPatternEnabled) { Dictionary <string, StringValues> headersDictionary = new Dictionary <string, StringValues>(durableHttpResponse.Headers); DateTime fireAt = default(DateTime); if (headersDictionary.ContainsKey("Retry-After")) { fireAt = this.InnerContext.CurrentUtcDateTime.AddSeconds(int.Parse(headersDictionary["Retry-After"])); } else { fireAt = this.InnerContext.CurrentUtcDateTime.AddMilliseconds(this.Config.Options.HttpSettings.DefaultAsyncRequestSleepTimeMilliseconds); } this.IncrementActionsOrThrowException(); await this.InnerContext.CreateTimer(fireAt, CancellationToken.None); DurableHttpRequest durableAsyncHttpRequest = this.CreateHttpRequestMessageCopy(req, durableHttpResponse.Headers["Location"]); durableHttpResponse = await this.ScheduleDurableHttpActivityAsync(durableAsyncHttpRequest); currStatusCode = durableHttpResponse.StatusCode; } return(durableHttpResponse); }
public async override Task <string> RunAsync(TaskContext context, string rawInput) { DurableHttpRequest durableHttpRequest = ReconstructDurableHttpRequest(rawInput); HttpRequestMessage requestMessage = await this.ConvertToHttpRequestMessage(durableHttpRequest); HttpResponseMessage response; if (durableHttpRequest.Timeout == null) { response = await this.httpClient.SendAsync(requestMessage); } else { try { using (CancellationTokenSource cts = new CancellationTokenSource()) { cts.CancelAfter(durableHttpRequest.Timeout.Value); response = await this.httpClient.SendAsync(requestMessage, cts.Token); } } catch (OperationCanceledException ex) { TimeoutException e = new TimeoutException(ex.Message + $" Reached user specified timeout: {durableHttpRequest.Timeout.Value}."); string details = Utils.SerializeCause(e, this.config.ErrorDataConverter); throw new TaskFailureException(e.Message, e, details); } } DurableHttpResponse durableHttpResponse = await DurableHttpResponse.CreateDurableHttpResponseWithHttpResponseMessage(response); return(JsonConvert.SerializeObject(durableHttpResponse)); }
Task <DurableHttpResponse> IDurableOrchestrationContext.CallHttpAsync(HttpMethod method, Uri uri, string content) { DurableHttpRequest req = new DurableHttpRequest( method: method, uri: uri, content: content); return(((IDurableOrchestrationContext)this).CallHttpAsync(req)); }
private async Task <HttpRequestMessage> ConvertToHttpRequestMessage(DurableHttpRequest durableHttpRequest) { string contentType = ""; HttpRequestMessage requestMessage = new HttpRequestMessage(durableHttpRequest.Method, durableHttpRequest.Uri); if (durableHttpRequest.Headers != null) { foreach (KeyValuePair <string, StringValues> entry in durableHttpRequest.Headers) { if (entry.Key.Equals("Content-Type", StringComparison.OrdinalIgnoreCase)) { foreach (string value in entry.Value) { if (value.Contains("multipart")) { throw new FunctionFailedException("Multipart content is not supported with CallHttpAsync."); } else { contentType = value; } } } else { requestMessage.Headers.Add(entry.Key, (IEnumerable <string>)entry.Value); } } } if (durableHttpRequest.Content != null) { if (contentType == "") { contentType = "text/plain"; } if (string.Equals(contentType, "application/x-www-form-urlencoded", StringComparison.OrdinalIgnoreCase)) { requestMessage.Content = new StringContent(durableHttpRequest.Content, Encoding.UTF8, contentType); } else { requestMessage.Content = new StringContent(durableHttpRequest.Content); requestMessage.Content.Headers.ContentType = new MediaTypeHeaderValue(contentType); } } if (durableHttpRequest.TokenSource != null) { string accessToken = await durableHttpRequest.TokenSource.GetTokenAsync(); requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); } return(requestMessage); }
private static DurableHttpRequest ReconstructDurableHttpRequest(string serializedRequest) { // DeserializeObject deserializes into a List and then the first element // of that list is the DurableHttpRequest IList <DurableHttpRequest> input = JsonConvert.DeserializeObject <IList <DurableHttpRequest> >(serializedRequest); DurableHttpRequest durableHttpRequest = input.First(); return(durableHttpRequest); }
private DurableHttpRequest CreateHttpRequestMessageCopy(DurableHttpRequest durableHttpRequest, string locationUri) { DurableHttpRequest newDurableHttpRequest = new DurableHttpRequest( method: HttpMethod.Get, uri: new Uri(locationUri), headers: durableHttpRequest.Headers, content: durableHttpRequest.Content, tokenSource: durableHttpRequest.TokenSource); return(newDurableHttpRequest); }
private async Task <DurableHttpResponse> ScheduleDurableHttpActivityAsync(DurableHttpRequest req) { DurableHttpResponse durableHttpResponse = await this.CallDurableTaskFunctionAsync <DurableHttpResponse>( functionName : HttpOptions.HttpTaskActivityReservedName, functionType : FunctionType.Activity, oneWay : false, instanceId : null, operation : null, retryOptions : null, input : req); return(durableHttpResponse); }
private DurableHttpRequest CreateLocationPollRequest(DurableHttpRequest durableHttpRequest, string locationUri) { DurableHttpRequest newDurableHttpRequest = new DurableHttpRequest( method: HttpMethod.Get, uri: new Uri(locationUri), headers: durableHttpRequest.Headers, content: durableHttpRequest.Content, tokenSource: durableHttpRequest.TokenSource); // Do not copy over the x-functions-key header, as in many cases, the // functions key used for the initial request will be a Function-level key // and the status endpoint requires a master key. newDurableHttpRequest.Headers.Remove("x-functions-key"); return(newDurableHttpRequest); }