Skip to content

Commit 9546b02

Browse files
committed
Add callHttp task
Signed-off-by: Ricardo Zanini <[email protected]>
1 parent 9f82c4c commit 9546b02

File tree

3 files changed

+293
-0
lines changed

3 files changed

+293
-0
lines changed
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
/*
2+
* Copyright 2020-Present The Serverless Workflow Specification Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.serverlessworkflow.fluent.standard;
17+
18+
import io.serverlessworkflow.api.types.CallHTTP;
19+
import io.serverlessworkflow.api.types.Endpoint;
20+
import io.serverlessworkflow.api.types.HTTPArguments;
21+
import io.serverlessworkflow.api.types.HTTPHeaders;
22+
import io.serverlessworkflow.api.types.HTTPQuery;
23+
import io.serverlessworkflow.api.types.Headers;
24+
import io.serverlessworkflow.api.types.Query;
25+
import io.serverlessworkflow.api.types.UriTemplate;
26+
import java.net.URI;
27+
import java.util.Map;
28+
import java.util.function.Consumer;
29+
30+
public class CallHTTPTaskBuilder extends TaskBaseBuilder<CallHTTPTaskBuilder> {
31+
32+
private final CallHTTP callHTTP;
33+
34+
CallHTTPTaskBuilder() {
35+
callHTTP = new CallHTTP();
36+
callHTTP.setWith(new HTTPArguments());
37+
callHTTP.getWith().setOutput(HTTPArguments.HTTPOutput.CONTENT);
38+
super.setTask(this.callHTTP);
39+
}
40+
41+
@Override
42+
protected CallHTTPTaskBuilder self() {
43+
return this;
44+
}
45+
46+
public CallHTTPTaskBuilder method(String method) {
47+
this.callHTTP.getWith().setMethod(method);
48+
return this;
49+
}
50+
51+
public CallHTTPTaskBuilder endpoint(URI endpoint) {
52+
this.callHTTP
53+
.getWith()
54+
.setEndpoint(new Endpoint().withUriTemplate(new UriTemplate().withLiteralUri(endpoint)));
55+
return this;
56+
}
57+
58+
public CallHTTPTaskBuilder endpoint(String expr) {
59+
this.callHTTP.getWith().setEndpoint(new Endpoint().withRuntimeExpression(expr));
60+
return this;
61+
}
62+
63+
// TODO: add endpoint configuration to support authentication
64+
65+
public CallHTTPTaskBuilder headers(String expr) {
66+
this.callHTTP.getWith().setHeaders(new Headers().withRuntimeExpression(expr));
67+
return this;
68+
}
69+
70+
public CallHTTPTaskBuilder headers(Consumer<HTTPHeadersBuilder> consumer) {
71+
HTTPHeadersBuilder hb = new HTTPHeadersBuilder();
72+
consumer.accept(hb);
73+
callHTTP.getWith().setHeaders(hb.build());
74+
return this;
75+
}
76+
77+
public CallHTTPTaskBuilder headers(Map<String, String> headers) {
78+
HTTPHeadersBuilder hb = new HTTPHeadersBuilder();
79+
hb.headers(headers);
80+
callHTTP.getWith().setHeaders(hb.build());
81+
return this;
82+
}
83+
84+
public CallHTTPTaskBuilder body(Object body) {
85+
this.callHTTP.getWith().setBody(body);
86+
return this;
87+
}
88+
89+
public CallHTTPTaskBuilder query(String expr) {
90+
this.callHTTP.getWith().setQuery(new Query().withRuntimeExpression(expr));
91+
return this;
92+
}
93+
94+
public CallHTTPTaskBuilder query(Consumer<HTTPQueryBuilder> consumer) {
95+
HTTPQueryBuilder queryBuilder = new HTTPQueryBuilder();
96+
consumer.accept(queryBuilder);
97+
callHTTP.getWith().setQuery(queryBuilder.build());
98+
return this;
99+
}
100+
101+
public CallHTTPTaskBuilder query(Map<String, String> query) {
102+
HTTPQueryBuilder httpQueryBuilder = new HTTPQueryBuilder();
103+
httpQueryBuilder.queries(query);
104+
callHTTP.getWith().setQuery(httpQueryBuilder.build());
105+
return this;
106+
}
107+
108+
public CallHTTPTaskBuilder redirect(boolean redirect) {
109+
callHTTP.getWith().setRedirect(redirect);
110+
return this;
111+
}
112+
113+
public CallHTTPTaskBuilder output(HTTPArguments.HTTPOutput output) {
114+
callHTTP.getWith().setOutput(output);
115+
return this;
116+
}
117+
118+
public CallHTTP build() {
119+
return callHTTP;
120+
}
121+
122+
public static class HTTPQueryBuilder {
123+
private final HTTPQuery httpQuery = new HTTPQuery();
124+
125+
public HTTPQueryBuilder query(String name, String value) {
126+
httpQuery.setAdditionalProperty(name, value);
127+
return this;
128+
}
129+
130+
public HTTPQueryBuilder queries(Map<String, String> headers) {
131+
headers.forEach(httpQuery::setAdditionalProperty);
132+
return this;
133+
}
134+
135+
public Query build() {
136+
return new Query().withHTTPQuery(httpQuery);
137+
}
138+
}
139+
140+
public static class HTTPHeadersBuilder {
141+
private final HTTPHeaders httpHeaders = new HTTPHeaders();
142+
143+
public HTTPHeadersBuilder header(String name, String value) {
144+
httpHeaders.setAdditionalProperty(name, value);
145+
return this;
146+
}
147+
148+
public HTTPHeadersBuilder headers(Map<String, String> headers) {
149+
headers.forEach(httpHeaders::setAdditionalProperty);
150+
return this;
151+
}
152+
153+
public Headers build() {
154+
return new Headers().withHTTPHeaders(httpHeaders);
155+
}
156+
}
157+
}

fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/DoTaskBuilder.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package io.serverlessworkflow.fluent.standard;
1717

18+
import io.serverlessworkflow.api.types.CallTask;
1819
import io.serverlessworkflow.api.types.DoTask;
1920
import io.serverlessworkflow.api.types.Task;
2021
import io.serverlessworkflow.api.types.TaskItem;
@@ -135,6 +136,19 @@ public DoTaskBuilder tryTask(Consumer<TryTaskBuilder> itemsConfigurer) {
135136
return this.tryTask(UUID.randomUUID().toString(), itemsConfigurer);
136137
}
137138

139+
public DoTaskBuilder callHTTP(String name, Consumer<CallHTTPTaskBuilder> itemsConfigurer) {
140+
final CallHTTPTaskBuilder callHTTPBuilder = new CallHTTPTaskBuilder();
141+
itemsConfigurer.accept(callHTTPBuilder);
142+
this.list.add(
143+
new TaskItem(
144+
name, new Task().withCallTask(new CallTask().withCallHTTP(callHTTPBuilder.build()))));
145+
return this;
146+
}
147+
148+
public DoTaskBuilder callHTTP(Consumer<CallHTTPTaskBuilder> itemsConfigurer) {
149+
return this.callHTTP(UUID.randomUUID().toString(), itemsConfigurer);
150+
}
151+
138152
public DoTask build() {
139153
this.doTask.setDo(this.list);
140154
return this.doTask;

fluent/standard/src/test/java/io/serverlessworkflow/fluent/standard/WorkflowBuilderTest.java

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,14 @@
2222
import static org.junit.jupiter.api.Assertions.assertTrue;
2323

2424
import io.serverlessworkflow.api.types.AuthenticationPolicyUnion;
25+
import io.serverlessworkflow.api.types.CallHTTP;
2526
import io.serverlessworkflow.api.types.CatchErrors;
2627
import io.serverlessworkflow.api.types.Document;
2728
import io.serverlessworkflow.api.types.ErrorFilter;
2829
import io.serverlessworkflow.api.types.EventFilter;
30+
import io.serverlessworkflow.api.types.HTTPArguments;
31+
import io.serverlessworkflow.api.types.HTTPHeaders;
32+
import io.serverlessworkflow.api.types.HTTPQuery;
2933
import io.serverlessworkflow.api.types.ListenTask;
3034
import io.serverlessworkflow.api.types.OneEventConsumptionStrategy;
3135
import io.serverlessworkflow.api.types.RetryLimitAttempt;
@@ -393,4 +397,122 @@ void testWorkflowInputInlineSchemaAndFromObject() {
393397
assertInstanceOf(Map.class, wf.getInput().getFrom().getObject(), "From object must be a Map");
394398
assertNotNull(wf.getInput().getSchema().getSchemaInline(), "Inline schema must be set");
395399
}
400+
401+
@Test
402+
void testDoTaskCallHTTPBasic() {
403+
Workflow wf =
404+
WorkflowBuilder.workflow("flowCallBasic")
405+
.doTasks(
406+
d ->
407+
d.callHTTP(
408+
"basicCall",
409+
c ->
410+
c.method("POST")
411+
.endpoint(URI.create("http://example.com/api"))
412+
.body(Map.of("foo", "bar"))))
413+
.build();
414+
List<TaskItem> items = wf.getDo();
415+
assertEquals(1, items.size(), "Should have one HTTP call task");
416+
TaskItem ti = items.get(0);
417+
assertEquals("basicCall", ti.getName());
418+
CallHTTP call = ti.getTask().getCallTask().getCallHTTP();
419+
assertNotNull(call, "CallHTTP should be present");
420+
assertEquals("POST", call.getWith().getMethod());
421+
assertEquals(
422+
URI.create("http://example.com/api"),
423+
call.getWith().getEndpoint().getUriTemplate().getLiteralUri());
424+
assertInstanceOf(Map.class, call.getWith().getBody(), "Body should be the Map provided");
425+
}
426+
427+
@Test
428+
void testDoTaskCallHTTPHeadersConsumerAndMap() {
429+
Workflow wf =
430+
WorkflowBuilder.workflow("flowCallHeaders")
431+
.doTasks(
432+
d ->
433+
d.callHTTP(
434+
"hdrCall",
435+
c ->
436+
c.method("GET")
437+
.endpoint("${uriExpr}")
438+
.headers(h -> h.header("A", "1").header("B", "2"))))
439+
.build();
440+
CallHTTP call = wf.getDo().get(0).getTask().getCallTask().getCallHTTP();
441+
HTTPHeaders hh = call.getWith().getHeaders().getHTTPHeaders();
442+
assertEquals("1", hh.getAdditionalProperties().get("A"));
443+
assertEquals("2", hh.getAdditionalProperties().get("B"));
444+
445+
Workflow wf2 =
446+
WorkflowBuilder.workflow()
447+
.doTasks(
448+
d ->
449+
d.callHTTP(
450+
c ->
451+
c.method("GET").endpoint("expr").headers(Map.of("X", "10", "Y", "20"))))
452+
.build();
453+
CallHTTP call2 = wf2.getDo().get(0).getTask().getCallTask().getCallHTTP();
454+
HTTPHeaders hh2 = call2.getWith().getHeaders().getHTTPHeaders();
455+
assertEquals("10", hh2.getAdditionalProperties().get("X"));
456+
assertEquals("20", hh2.getAdditionalProperties().get("Y"));
457+
}
458+
459+
@Test
460+
void testDoTaskCallHTTPQueryConsumerAndMap() {
461+
Workflow wf =
462+
WorkflowBuilder.workflow("flowCallQuery")
463+
.doTasks(
464+
d ->
465+
d.callHTTP(
466+
"qryCall",
467+
c ->
468+
c.method("GET")
469+
.endpoint("exprUri")
470+
.query(q -> q.query("k1", "v1").query("k2", "v2"))))
471+
.build();
472+
HTTPQuery hq =
473+
wf.getDo().get(0).getTask().getCallTask().getCallHTTP().getWith().getQuery().getHTTPQuery();
474+
assertEquals("v1", hq.getAdditionalProperties().get("k1"));
475+
assertEquals("v2", hq.getAdditionalProperties().get("k2"));
476+
477+
Workflow wf2 =
478+
WorkflowBuilder.workflow()
479+
.doTasks(
480+
d ->
481+
d.callHTTP(
482+
c -> c.method("GET").endpoint("uri").query(Map.of("q1", "x", "q2", "y"))))
483+
.build();
484+
HTTPQuery hq2 =
485+
wf2.getDo()
486+
.get(0)
487+
.getTask()
488+
.getCallTask()
489+
.getCallHTTP()
490+
.getWith()
491+
.getQuery()
492+
.getHTTPQuery();
493+
assertEquals("x", hq2.getAdditionalProperties().get("q1"));
494+
assertEquals("y", hq2.getAdditionalProperties().get("q2"));
495+
}
496+
497+
@Test
498+
void testDoTaskCallHTTPRedirectAndOutput() {
499+
Workflow wf =
500+
WorkflowBuilder.workflow("flowCallOpts")
501+
.doTasks(
502+
d ->
503+
d.callHTTP(
504+
"optCall",
505+
c ->
506+
c.method("DELETE")
507+
.endpoint("expr")
508+
.redirect(true)
509+
.output(HTTPArguments.HTTPOutput.RESPONSE)))
510+
.build();
511+
CallHTTP call = wf.getDo().get(0).getTask().getCallTask().getCallHTTP();
512+
assertTrue(call.getWith().isRedirect(), "Redirect should be true");
513+
assertEquals(
514+
HTTPArguments.HTTPOutput.RESPONSE,
515+
call.getWith().getOutput(),
516+
"Output should be overridden");
517+
}
396518
}

0 commit comments

Comments
 (0)