2020import io .serverlessworkflow .api .types .CallHTTP ;
2121import io .serverlessworkflow .api .types .Endpoint ;
2222import io .serverlessworkflow .api .types .HTTPArguments ;
23+ import io .serverlessworkflow .api .types .ReferenceableAuthenticationPolicy ;
2324import io .serverlessworkflow .api .types .TaskBase ;
2425import io .serverlessworkflow .impl .TaskContext ;
2526import io .serverlessworkflow .impl .WorkflowApplication ;
3031import io .serverlessworkflow .impl .WorkflowModel ;
3132import io .serverlessworkflow .impl .WorkflowValueResolver ;
3233import io .serverlessworkflow .impl .executors .CallableTask ;
34+ import io .serverlessworkflow .impl .expressions .ExpressionDescriptor ;
3335import jakarta .ws .rs .HttpMethod ;
3436import jakarta .ws .rs .WebApplicationException ;
3537import jakarta .ws .rs .client .Client ;
3638import jakarta .ws .rs .client .ClientBuilder ;
3739import jakarta .ws .rs .client .Invocation .Builder ;
3840import jakarta .ws .rs .client .WebTarget ;
41+ import java .net .URI ;
3942import java .util .Map ;
4043import java .util .Optional ;
4144import java .util .concurrent .CompletableFuture ;
4447public class HttpExecutor implements CallableTask <CallHTTP > {
4548
4649 private static final Client client = ClientBuilder .newClient ();
50+ // TODO allow changing default converter
51+ private static final HttpModelConverter defaultConverter = new HttpModelConverter () {};
4752
4853 private TargetSupplier targetSupplier ;
4954 private Optional <WorkflowValueResolver <Map <String , Object >>> headersMap ;
5055 private Optional <WorkflowValueResolver <Map <String , Object >>> queryMap ;
5156 private Optional <AuthProvider > authProvider ;
5257 private RequestSupplier requestFunction ;
53- private HttpModelConverter converter = new HttpModelConverter () {};
58+
59+ public static class HttpExecutorBuilder {
60+
61+ private final WorkflowDefinition definition ;
62+
63+ private ReferenceableAuthenticationPolicy authPolicy ;
64+ private WorkflowValueResolver <Map <String , Object >> headersMap ;
65+ private WorkflowValueResolver <Map <String , Object >> queryMap ;
66+ private WorkflowValueResolver <URI > pathSupplier ;
67+ private Object body ;
68+ private boolean redirect ;
69+ private String method = HttpMethod .GET ;
70+
71+ private HttpExecutorBuilder (WorkflowDefinition definition ) {
72+ this .definition = definition ;
73+ }
74+
75+ public HttpExecutorBuilder withAuth (ReferenceableAuthenticationPolicy policy ) {
76+ this .authPolicy = policy ;
77+ return this ;
78+ }
79+
80+ public HttpExecutorBuilder withBody (Object body ) {
81+ this .body = body ;
82+ return this ;
83+ }
84+
85+ public HttpExecutorBuilder withPath (WorkflowValueResolver <URI > pathSupplier ) {
86+ this .pathSupplier = pathSupplier ;
87+ return this ;
88+ }
89+
90+ public HttpExecutorBuilder withHeaders (WorkflowValueResolver <Map <String , Object >> headersMap ) {
91+ this .headersMap = headersMap ;
92+ return this ;
93+ }
94+
95+ public HttpExecutorBuilder withQueryMap (WorkflowValueResolver <Map <String , Object >> queryMap ) {
96+ this .queryMap = queryMap ;
97+ return this ;
98+ }
99+
100+ public HttpExecutorBuilder withHeaders (Map <String , Object > headersMap ) {
101+ return withHeaders (
102+ definition
103+ .application ()
104+ .expressionFactory ()
105+ .resolveMap (ExpressionDescriptor .object (headersMap )));
106+ }
107+
108+ public HttpExecutorBuilder withQueryMap (Map <String , Object > headersMap ) {
109+ return withQueryMap (
110+ definition
111+ .application ()
112+ .expressionFactory ()
113+ .resolveMap (ExpressionDescriptor .object (headersMap )));
114+ }
115+
116+ public HttpExecutorBuilder withMethod (String method ) {
117+ this .method = method ;
118+ return this ;
119+ }
120+
121+ public HttpExecutorBuilder redirect (boolean redirect ) {
122+ this .redirect = redirect ;
123+ return this ;
124+ }
125+
126+ public HttpExecutor build (String uri ) {
127+ return build ((w , f , n ) -> URI .create (uri ));
128+ }
129+
130+ public HttpExecutor build (WorkflowValueResolver <URI > uriSupplier ) {
131+ HttpExecutor executor = new HttpExecutor ();
132+ executor .targetSupplier =
133+ pathSupplier == null
134+ ? getTargetSupplier (uriSupplier )
135+ : getTargetSupplier (uriSupplier , pathSupplier );
136+ executor .authProvider = AuthProviderFactory .getAuth (definition , authPolicy );
137+ executor .requestFunction =
138+ buildRequestSupplier (method , body , definition .application (), defaultConverter );
139+ executor .headersMap = Optional .ofNullable (headersMap );
140+ executor .queryMap = Optional .ofNullable (queryMap );
141+ return executor ;
142+ }
143+ }
144+
145+ public static HttpExecutorBuilder builder (WorkflowDefinition definition ) {
146+ return new HttpExecutorBuilder (definition );
147+ }
54148
55149 @ FunctionalInterface
56150 private interface RequestSupplier {
@@ -60,22 +154,21 @@ WorkflowModel apply(
60154
61155 @ Override
62156 public void init (CallHTTP task , WorkflowDefinition definition ) {
63- HTTPArguments httpArgs = task .getWith ();
64-
65- WorkflowApplication application = definition .application ();
157+ final HTTPArguments httpArgs = task .getWith ();
158+ final Endpoint endpoint = httpArgs .getEndpoint ();
66159
67160 this .authProvider =
68- AuthProviderFactory . getAuth (
69- application ,
70- definition . workflow (),
71- task . getWith ().getEndpoint (). getEndpointConfiguration ());
161+ endpoint . getEndpointConfiguration () == null
162+ ? Optional . empty ()
163+ : AuthProviderFactory . getAuth (
164+ definition , endpoint . getEndpointConfiguration ().getAuthentication ());
72165
73- this .targetSupplier = getTargetSupplier (definition , httpArgs . getEndpoint ( ));
166+ this .targetSupplier = getTargetSupplier (definition . resourceLoader (). uriSupplier ( endpoint ));
74167 this .headersMap =
75168 httpArgs .getHeaders () != null
76169 ? Optional .of (
77170 buildMapResolver (
78- application ,
171+ definition . application () ,
79172 httpArgs .getHeaders ().getRuntimeExpression (),
80173 httpArgs .getHeaders ().getHTTPHeaders () != null
81174 ? httpArgs .getHeaders ().getHTTPHeaders ().getAdditionalProperties ()
@@ -85,30 +178,36 @@ public void init(CallHTTP task, WorkflowDefinition definition) {
85178 httpArgs .getQuery () != null
86179 ? Optional .of (
87180 buildMapResolver (
88- application ,
181+ definition . application () ,
89182 httpArgs .getQuery ().getRuntimeExpression (),
90183 httpArgs .getQuery ().getHTTPQuery () != null
91184 ? httpArgs .getQuery ().getHTTPQuery ().getAdditionalProperties ()
92185 : null ))
93186 : Optional .empty ();
94- switch (httpArgs .getMethod ().toUpperCase ()) {
187+ this .requestFunction =
188+ buildRequestSupplier (
189+ httpArgs .getMethod ().toUpperCase (),
190+ httpArgs .getBody (),
191+ definition .application (),
192+ defaultConverter );
193+ }
194+
195+ private static RequestSupplier buildRequestSupplier (
196+ String method , Object body , WorkflowApplication application , HttpModelConverter converter ) {
197+ switch (method .toUpperCase ()) {
95198 case HttpMethod .POST :
96199 WorkflowValueResolver <Map <String , Object >> bodyFilter =
97- buildMapResolver (application , null , httpArgs .getBody ());
98- this .requestFunction =
99- (request , w , context , node ) ->
100- converter .toModel (
101- application .modelFactory (),
102- node ,
103- request .post (
104- converter .toEntity (bodyFilter .apply (w , context , node )),
105- node .objectClass ()));
106- break ;
200+ buildMapResolver (application , null , body );
201+ return (request , w , context , node ) ->
202+ converter .toModel (
203+ application .modelFactory (),
204+ node ,
205+ request .post (
206+ converter .toEntity (bodyFilter .apply (w , context , node )), node .objectClass ()));
107207 case HttpMethod .GET :
108208 default :
109- this .requestFunction =
110- (request , w , t , n ) ->
111- converter .toModel (application .modelFactory (), n , request .get (n .objectClass ()));
209+ return (request , w , t , n ) ->
210+ converter .toModel (application .modelFactory (), n , request .get (n .objectClass ()));
112211 }
113212 }
114213
@@ -162,26 +261,17 @@ public boolean accept(Class<? extends TaskBase> clazz) {
162261 return clazz .equals (CallHTTP .class );
163262 }
164263
264+ private static TargetSupplier getTargetSupplier (WorkflowValueResolver <URI > uriSupplier ) {
265+ return (w , t , n ) -> client .target (uriSupplier .apply (w , t , n ));
266+ }
267+
165268 private static TargetSupplier getTargetSupplier (
166- WorkflowDefinition definition , Endpoint endpoint ) {
269+ WorkflowValueResolver < URI > uriSupplier , WorkflowValueResolver < URI > pathSupplier ) {
167270 return (w , t , n ) ->
168- client .target (definition . resourceLoader (). uriSupplier ( endpoint ) .apply (w , t , n ));
271+ client .target (uriSupplier . apply ( w , t , n ). resolve ( pathSupplier .apply (w , t , n ) ));
169272 }
170273
171274 private static interface TargetSupplier {
172275 WebTarget apply (WorkflowContext workflow , TaskContext task , WorkflowModel node );
173276 }
174-
175- private static class ExpressionURISupplier implements TargetSupplier {
176- private WorkflowValueResolver <String > expr ;
177-
178- public ExpressionURISupplier (WorkflowValueResolver <String > expr ) {
179- this .expr = expr ;
180- }
181-
182- @ Override
183- public WebTarget apply (WorkflowContext workflow , TaskContext task , WorkflowModel node ) {
184- return client .target (expr .apply (workflow , task , node ));
185- }
186- }
187277}
0 commit comments