Skip to content

Commit e22c354

Browse files
committed
added sample to samples-azure-functions
1 parent f27290b commit e22c354

1 file changed

Lines changed: 172 additions & 0 deletions

File tree

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
package com.functions;
4+
5+
import com.microsoft.azure.functions.ExecutionContext;
6+
import com.microsoft.azure.functions.HttpMethod;
7+
import com.microsoft.azure.functions.HttpRequestMessage;
8+
import com.microsoft.azure.functions.HttpResponseMessage;
9+
import com.microsoft.azure.functions.annotation.AuthorizationLevel;
10+
import com.microsoft.azure.functions.annotation.FunctionName;
11+
import com.microsoft.azure.functions.annotation.HttpTrigger;
12+
import com.microsoft.durabletask.DurableHttpRequest;
13+
import com.microsoft.durabletask.DurableHttpResponse;
14+
import com.microsoft.durabletask.DurableTaskClient;
15+
import com.microsoft.durabletask.HttpRetryOptions;
16+
import com.microsoft.durabletask.ManagedIdentityTokenSource;
17+
import com.microsoft.durabletask.TaskOrchestrationContext;
18+
import com.microsoft.durabletask.azurefunctions.DurableClientContext;
19+
import com.microsoft.durabletask.azurefunctions.DurableClientInput;
20+
import com.microsoft.durabletask.azurefunctions.DurableOrchestrationTrigger;
21+
22+
import java.net.URI;
23+
import java.time.Duration;
24+
import java.util.Arrays;
25+
import java.util.HashMap;
26+
import java.util.Map;
27+
import java.util.Optional;
28+
29+
/**
30+
* Sample Azure Functions demonstrating different {@code callHttp} usage patterns
31+
* with Durable Functions orchestrations.
32+
*/
33+
public class CallHttpFunctions {
34+
35+
// =====================================================================
36+
// 1. Simple GET using the convenience method
37+
// =====================================================================
38+
39+
@FunctionName("StartSimpleGetOrchestration")
40+
public HttpResponseMessage startSimpleGet(
41+
@HttpTrigger(name = "req", methods = {HttpMethod.GET, HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS)
42+
HttpRequestMessage<Optional<String>> request,
43+
@DurableClientInput(name = "durableContext") DurableClientContext durableContext,
44+
final ExecutionContext context) {
45+
DurableTaskClient client = durableContext.getClient();
46+
String instanceId = client.scheduleNewOrchestrationInstance("SimpleGetOrchestrator");
47+
context.getLogger().info("Started SimpleGetOrchestrator with instance ID = " + instanceId);
48+
return durableContext.createCheckStatusResponse(request, instanceId);
49+
}
50+
51+
@FunctionName("SimpleGetOrchestrator")
52+
public String simpleGetOrchestrator(
53+
@DurableOrchestrationTrigger(name = "ctx") TaskOrchestrationContext ctx) {
54+
// Simple GET request using the convenience overload (method + URI only)
55+
DurableHttpResponse response = ctx.callHttp("GET",
56+
URI.create("https://httpbin.org/get")).await();
57+
58+
return "Status: " + response.getStatusCode() + ", Body: " + response.getContent();
59+
}
60+
61+
// =====================================================================
62+
// 2. POST with custom headers and JSON body
63+
// =====================================================================
64+
65+
@FunctionName("StartPostWithHeadersOrchestration")
66+
public HttpResponseMessage startPostWithHeaders(
67+
@HttpTrigger(name = "req", methods = {HttpMethod.GET, HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS)
68+
HttpRequestMessage<Optional<String>> request,
69+
@DurableClientInput(name = "durableContext") DurableClientContext durableContext,
70+
final ExecutionContext context) {
71+
DurableTaskClient client = durableContext.getClient();
72+
String instanceId = client.scheduleNewOrchestrationInstance("PostWithHeadersOrchestrator");
73+
context.getLogger().info("Started PostWithHeadersOrchestrator with instance ID = " + instanceId);
74+
return durableContext.createCheckStatusResponse(request, instanceId);
75+
}
76+
77+
@FunctionName("PostWithHeadersOrchestrator")
78+
public String postWithHeadersOrchestrator(
79+
@DurableOrchestrationTrigger(name = "ctx") TaskOrchestrationContext ctx) {
80+
// POST request with custom headers and a JSON body
81+
Map<String, String> headers = new HashMap<>();
82+
headers.put("Content-Type", "application/json");
83+
headers.put("X-Custom-Header", "my-value");
84+
85+
String jsonBody = "{\"name\": \"Durable Functions\", \"language\": \"Java\"}";
86+
87+
DurableHttpResponse response = ctx.callHttp("POST",
88+
URI.create("https://httpbin.org/post"),
89+
headers,
90+
jsonBody).await();
91+
92+
return "Status: " + response.getStatusCode() + ", Body: " + response.getContent();
93+
}
94+
95+
// =====================================================================
96+
// 3. Managed Identity token source for calling Azure resources
97+
// =====================================================================
98+
99+
@FunctionName("StartManagedIdentityOrchestration")
100+
public HttpResponseMessage startManagedIdentity(
101+
@HttpTrigger(name = "req", methods = {HttpMethod.GET, HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS)
102+
HttpRequestMessage<Optional<String>> request,
103+
@DurableClientInput(name = "durableContext") DurableClientContext durableContext,
104+
final ExecutionContext context) {
105+
DurableTaskClient client = durableContext.getClient();
106+
String instanceId = client.scheduleNewOrchestrationInstance("ManagedIdentityOrchestrator");
107+
context.getLogger().info("Started ManagedIdentityOrchestrator with instance ID = " + instanceId);
108+
return durableContext.createCheckStatusResponse(request, instanceId);
109+
}
110+
111+
@FunctionName("ManagedIdentityOrchestrator")
112+
public String managedIdentityOrchestrator(
113+
@DurableOrchestrationTrigger(name = "ctx") TaskOrchestrationContext ctx) {
114+
// Use ManagedIdentityTokenSource to automatically attach a bearer token
115+
// when calling Azure Resource Manager APIs. The resource URI is auto-normalized
116+
// to include "/.default" for well-known Azure resource bases.
117+
ManagedIdentityTokenSource tokenSource =
118+
new ManagedIdentityTokenSource("https://management.core.windows.net");
119+
120+
DurableHttpRequest request = new DurableHttpRequest(
121+
"GET",
122+
URI.create("https://management.azure.com/subscriptions?api-version=2020-01-01"),
123+
null, // headers
124+
null, // content
125+
tokenSource);
126+
127+
DurableHttpResponse response = ctx.callHttp(request).await();
128+
129+
return "Status: " + response.getStatusCode() + ", Body: " + response.getContent();
130+
}
131+
132+
// =====================================================================
133+
// 4. HTTP retry options with backoff and status code filtering
134+
// =====================================================================
135+
136+
@FunctionName("StartRetryableHttpOrchestration")
137+
public HttpResponseMessage startRetryableHttp(
138+
@HttpTrigger(name = "req", methods = {HttpMethod.GET, HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS)
139+
HttpRequestMessage<Optional<String>> request,
140+
@DurableClientInput(name = "durableContext") DurableClientContext durableContext,
141+
final ExecutionContext context) {
142+
DurableTaskClient client = durableContext.getClient();
143+
String instanceId = client.scheduleNewOrchestrationInstance("RetryableHttpOrchestrator");
144+
context.getLogger().info("Started RetryableHttpOrchestrator with instance ID = " + instanceId);
145+
return durableContext.createCheckStatusResponse(request, instanceId);
146+
}
147+
148+
@FunctionName("RetryableHttpOrchestrator")
149+
public String retryableHttpOrchestrator(
150+
@DurableOrchestrationTrigger(name = "ctx") TaskOrchestrationContext ctx) {
151+
// Configure HTTP-level retry with exponential backoff and specific status codes
152+
HttpRetryOptions retryOptions = new HttpRetryOptions(Duration.ofSeconds(5), 3);
153+
retryOptions.setBackoffCoefficient(2.0);
154+
retryOptions.setMaxRetryInterval(Duration.ofMinutes(1));
155+
retryOptions.setRetryTimeout(Duration.ofMinutes(5));
156+
retryOptions.setStatusCodesToRetry(Arrays.asList(500, 502, 503, 504));
157+
158+
DurableHttpRequest request = new DurableHttpRequest(
159+
"GET",
160+
URI.create("https://httpbin.org/status/200"),
161+
null, // headers
162+
null, // content
163+
null, // tokenSource
164+
true, // asynchronousPatternEnabled
165+
Duration.ofMinutes(10), // timeout
166+
retryOptions);
167+
168+
DurableHttpResponse response = ctx.callHttp(request).await();
169+
170+
return "Status: " + response.getStatusCode() + ", Body: " + response.getContent();
171+
}
172+
}

0 commit comments

Comments
 (0)