Skip to content

Commit 08c3315

Browse files
ricardozaninicdavernas
authored andcommitted
Fix serverlessworkflow#818 - Merge REST and OPENAPI operations, introduce HTTP functions
Signed-off-by: Ricardo Zanini <[email protected]> Signed-off-by: Charles d'Avernas <[email protected]>
1 parent f0d1601 commit 08c3315

File tree

3 files changed

+192
-24
lines changed

3 files changed

+192
-24
lines changed

examples/curl.json

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"id": "curl",
3+
"version": "1.0.0",
4+
"specVersion": "0.9",
5+
"name": "curl-workflow",
6+
"description": "Curl Google",
7+
"start": "curl",
8+
"functions": [
9+
{
10+
"name": "curl-google",
11+
"type": "http",
12+
"operation": {
13+
"method": "GET",
14+
"uri": "https://www.google.com/search?q={query}"
15+
}
16+
}
17+
],
18+
"states": [
19+
{
20+
"name": "curl",
21+
"type": "operation",
22+
"actions": [
23+
{
24+
"name": "do-curl",
25+
"functionRef": {
26+
"refName": "curl-google",
27+
"arguments": {
28+
"query": "${ .query }"
29+
}
30+
}
31+
}
32+
],
33+
"end": true
34+
}
35+
]
36+
}

schema/functions.json

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,7 @@
2222
}
2323
]
2424
},
25-
"required": [
26-
"functions"
27-
],
25+
"required": ["functions"],
2826
"definitions": {
2927
"function": {
3028
"type": "object",
@@ -40,9 +38,9 @@
4038
},
4139
"type": {
4240
"type": "string",
43-
"description": "Defines the function type. Is either `rest`, `openapi`,`asyncapi, `rpc`, `graphql`, `odata`, `expression`, or `custom`. Default is `openapi`.",
41+
"description": "Defines the function type. Is either `http`, `openapi`,`asyncapi, `rpc`, `graphql`, `odata`, `expression`, or `custom`. Default is `openapi`.",
4442
"enum": [
45-
"rest",
43+
"http",
4644
"openapi",
4745
"asyncapi",
4846
"rpc",
@@ -77,9 +75,7 @@
7775
}
7876
},
7977
"additionalProperties": false,
80-
"required": [
81-
"resource"
82-
]
78+
"required": ["resource"]
8379
}
8480
]
8581
},
@@ -88,10 +84,7 @@
8884
}
8985
},
9086
"additionalProperties": false,
91-
"required": [
92-
"name",
93-
"operation"
94-
]
87+
"required": ["name", "operation"]
9588
},
9689
"operation": {
9790
"oneOf": [
@@ -109,8 +102,39 @@
109102
"type": "object"
110103
}
111104
}
105+
},
106+
{
107+
"type": "object",
108+
"description": "HTTP Function operation definition",
109+
"properties": {
110+
"method": {
111+
"enum": [
112+
"GET",
113+
"HEAD",
114+
"POST",
115+
"PUT",
116+
"DELETE",
117+
"CONNECT",
118+
"OPTIONS",
119+
"TRACE"
120+
],
121+
"default": "GET"
122+
},
123+
"uri": {
124+
"type": "string"
125+
},
126+
"headers": {
127+
"type": "object",
128+
"additionalProperties": { "type": "string" }
129+
},
130+
"cookies": {
131+
"type": "object",
132+
"additionalProperties": { "type": "string" }
133+
}
134+
},
135+
"required": ["method", "uri"]
112136
}
113137
]
114138
}
115139
}
116-
}
140+
}

specification.md

Lines changed: 119 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
+ [Data Merging](#data-merging)
2525
* [Workflow Functions](#workflow-functions)
2626
+ [Using Functions for OpenAPI Service Invocations](#using-functions-for-openapi-service-invocations)
27-
+ [Using Functions for RESTful Service Invocations](#using-functions-for-restful-service-invocations)
27+
+ [Using Functions for HTTP Service Invocations](#using-functions-for-http-service-invocations)
2828
+ [Using Functions for Async API Service Invocations](#using-functions-for-async-api-service-invocations)
2929
+ [Using Functions for RPC Service Invocations](#using-functions-for-rpc-service-invocations)
3030
+ [Using Functions for GraphQL Service Invocations](#using-functions-for-graphql-service-invocations)
@@ -1032,7 +1032,7 @@ They can be referenced by their domain-specific names inside workflow [states](#
10321032
Reference the following sections to learn more about workflow functions:
10331033

10341034
* [Using functions for OpenAPI Service invocations](#using-functions-for-openapi-service-invocations)
1035-
+ [Using functions for RESTful Service Invocations](#using-functions-for-rest-service-invocations)
1035+
+ [Using functions for HTTP Service Invocations](#using-functions-for-http-service-invocations)
10361036
* [Using functions for Async API Service Invocations](#Using-Functions-for-Async-API-Service-Invocations)
10371037
* [Using functions for gRPC service invocation](#Using-Functions-For-RPC-Service-Invocations)
10381038
* [Using functions for GraphQL service invocation](#Using-Functions-For-GraphQL-Service-Invocations)
@@ -1098,11 +1098,7 @@ For example:
10981098

10991099
Note that the referenced function definition type in this case must be `openapi` (default type).
11001100

1101-
For more information about functions, reference the [Functions definitions](#Function-Definition) section.
1102-
1103-
#### Using functions for RESTful Service Invocations
1104-
1105-
The specification also supports describing REST invocations in the [functions definition](#Function-Definition) using [OpenAPI Paths Object](https://spec.openapis.org/oas/v3.1.0#paths-object).
1101+
The specification also supports describing OpenAPI for REST invocations inline in the [functions definition](#Function-Definition) using [OpenAPI Paths Object](https://spec.openapis.org/oas/v3.1.0#paths-object).
11061102

11071103
Here is an example function definition for REST requests with method `GET` and request target corresponding with [URI Template](https://www.rfc-editor.org/rfc/rfc6570.html) `/users/{id}`:
11081104

@@ -1122,7 +1118,7 @@ Here is an example function definition for REST requests with method `GET` and r
11221118
}
11231119
}
11241120
},
1125-
"type":"rest"
1121+
"type":"openapi"
11261122
}
11271123
]
11281124
}
@@ -1159,7 +1155,7 @@ Example of the `POST` request sending the state data as part of the body:
11591155
"functions":[
11601156
{
11611157
"name": "createUser",
1162-
"type": "rest",
1158+
"type": "openapi",
11631159
"operation": {
11641160
"/users": {
11651161
"post": {
@@ -1256,7 +1252,119 @@ In this case, only the contents of the `user` attribute will be passed to the fu
12561252
}
12571253
```
12581254

1259-
The specification does not support the [Security Requirement Object](https://spec.openapis.org/oas/v3.1.0#security-requirement-object) since its redundat to function [Auth Definition](#Auth-Definition). If provided, this field is ignored.
1255+
When inlining the OpenAPI operation, the specification does not support the [Security Requirement Object](https://spec.openapis.org/oas/v3.1.0#security-requirement-object) since its redundat to function [Auth Definition](#Auth-Definition). If provided, this field is ignored.
1256+
1257+
For more information about functions, reference the [Functions definitions](#Function-Definition) section.
1258+
1259+
#### Using functions for HTTP Service Invocations
1260+
1261+
The HTTP function can make HTTP requests to a given endpoint. It can be used in cases a service doesn't have an OpenAPI definition or users require a simple HTTP, curl-style invocation.
1262+
1263+
The table below lists the `operation` properties for the `http` function type.
1264+
1265+
| Property | Description | Type | Required |
1266+
| --- | --- | --- | --- |
1267+
1268+
| uri | The URI where to send the request | String | yes |
1269+
| method | The HTTP method according to the [RFC 2616](https://datatracker.ietf.org/doc/html/rfc2616#page-36) | String | yes |
1270+
| headers | Headers to send in the HTTP call. The `Content-Type` header mandates the body convertion. | Map | no |
1271+
| cookies | Cookies to send in the HTTP call. | Map | no |
1272+
1273+
Note that in the function definition, these values are static. When invoking the function in the `actions` definition, `jq` can be used to set the attribute values.
1274+
1275+
Here is a function definition example for a HTTP service operation.
1276+
1277+
```json
1278+
{
1279+
"functions": [
1280+
{
1281+
"name": "getPetById",
1282+
"type": "http",
1283+
"operation": {
1284+
"method": "GET",
1285+
"uri": "https://petstore.swagger.io/v2/pet/{petId}"
1286+
}
1287+
}
1288+
]
1289+
}
1290+
```
1291+
1292+
This function can be used later in the workflow definition:
1293+
1294+
```json
1295+
{
1296+
"states":[
1297+
{
1298+
"name": "getpet",
1299+
"type": "operation",
1300+
"actions":[
1301+
{
1302+
"functionRef": "getPetById",
1303+
"arguments":{
1304+
"petId": "${ .pet.id }"
1305+
}
1306+
}
1307+
],
1308+
"end":true
1309+
}
1310+
]
1311+
}
1312+
```
1313+
1314+
Not that the `arguments` attribute must map the template in the `uri` definition so the underlying engine can map the arguments correctly.
1315+
1316+
The `arguments` attribute accepts the following reserved properties when calling a HTTP function type:
1317+
1318+
| Property | Description | Type | Required |
1319+
| --- | --- | --- | --- |
1320+
1321+
| body | The HTTP body. If an object, it will be sent as a JSON payload by default if the `Content-Type` header is missing. Otherwise, it will try to convert it based on the `Content-Type` header definition | Object or String | no |
1322+
| headers | Headers to send in the HTTP call. The `Content-Type` header mandates the body convertion. | Map | no |
1323+
| cookies | Cookies to send in the HTTP call. | Map | no |
1324+
1325+
These attributes are merged with the ones in the function definition.
1326+
1327+
The listing below exemplifies how to define and call a HTTP POST endpoint.
1328+
1329+
```json
1330+
{
1331+
"functions": [
1332+
{
1333+
"name": "createPet",
1334+
"type": "http",
1335+
"operation": {
1336+
"method": "POST",
1337+
"uri": "https://petstore.swagger.io/v2/pet/",
1338+
"headers": {
1339+
"Content-Type": "application/json"
1340+
}
1341+
}
1342+
}
1343+
]
1344+
},
1345+
{
1346+
"states":[
1347+
{
1348+
"name":"create-pet",
1349+
"type":"operation",
1350+
"actions":[
1351+
{
1352+
"functionRef":"createPet",
1353+
"arguments":{
1354+
"body": {
1355+
"name": "Lulu"
1356+
},
1357+
"headers": {
1358+
"my-header": "my-value"
1359+
}
1360+
}
1361+
}
1362+
],
1363+
"end":true
1364+
}
1365+
]
1366+
}
1367+
```
12601368

12611369
#### Using Functions for Async API Service Invocations
12621370

@@ -3330,7 +3438,7 @@ Note that `transition` and `end` properties are mutually exclusive, meaning that
33303438
| --- | --- | --- | --- |
33313439
| name | Unique function name. Must follow the [Serverless Workflow Naming Convention](#naming-convention) | string | yes |
33323440
| operation | See the table "Function Operation description by type" below. | string or object | yes |
3333-
| type | Defines the function type. Can be either `rest`, `openapi`, `asyncapi`, `rpc`, `graphql`, `odata`, `expression`, or [`custom`](#defining-custom-function-types). Default is `openapi` | enum | no |
3441+
| type | Defines the function type. Can be either `http`, `openapi`, `asyncapi`, `rpc`, `graphql`, `odata`, `expression`, or [`custom`](#defining-custom-function-types). Default is `openapi` | enum | no |
33343442
| authRef | References an [auth definition](#Auth-Definition) name to be used to access to resource defined in the operation parameter | string | no |
33353443
| [metadata](#Workflow-Metadata) | Metadata information. Can be used to define custom function information | object | no |
33363444

0 commit comments

Comments
 (0)