-
Notifications
You must be signed in to change notification settings - Fork 40
/
http.go
104 lines (86 loc) · 2.86 KB
/
http.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
package builtin
import (
"errors"
"fmt"
"strings"
"github.com/fission/fission-workflows/pkg/fnenv/http"
"github.com/fission/fission-workflows/pkg/types"
"github.com/fission/fission-workflows/pkg/types/typedvalues"
"github.com/golang/protobuf/proto"
)
const (
Http = "http"
HttpInputUrl = "url"
httpDefaultProtocol = "http"
)
/*
HttpFunction is a general utility function to perform simple HTTP requests.
It is useful for prototyping and managing low overhead HTTP requests.
To this end it offers basic functionality, such as setting headers, query, method, url, and body inputs.
**Specification**
**input** | required | types | description
----------------|----------|-------------------|--------------------------------------------------------
url/default | yes | string | URL of the request.
headers | no | map[string|string | The action to perform for every element.
content-type | no | string | Force a specific content-type for the request.
method | no | string | HTTP Method of the request. (default: GET)
body | no | * | The body of the request. (default: application/octet-stream)
Unless the content type is specified explicitly, the workflow engine will infer the content-type based on the body.
**output** (*) the body of the response.
Note: currently you cannot access the metadata of the response.
**Example**
```yaml
# ...
httpExample:
run: http
inputs:
url: http://fission.io
method: post
body: "foo"
# ...
```
A complete example of this function can be found in the [httpwhale](../examples/whales/httpwhale.wf.yaml) example.
*/
type FunctionHTTP struct {
runtime *http.Runtime
}
func NewFunctionHTTP() *FunctionHTTP {
return &FunctionHTTP{
runtime: http.New(),
}
}
func (fn *FunctionHTTP) Invoke(spec *types.TaskInvocationSpec) (*typedvalues.TypedValue, error) {
// Get the actual url
targetUrl, err := fn.determineTargetURL(spec.Inputs)
if err != nil {
return nil, err
}
fnref, err := types.ParseFnRef(targetUrl)
if err != nil {
return nil, err
}
clonedSpec := proto.Clone(spec).(*types.TaskInvocationSpec)
clonedSpec.FnRef = &fnref
result, err := fn.runtime.Invoke(clonedSpec)
if err != nil {
return nil, err
}
if result.GetStatus() == types.TaskInvocationStatus_FAILED {
return nil, result.GetError()
}
return result.GetOutput(), nil
}
func (fn *FunctionHTTP) determineTargetURL(inputs map[string]*typedvalues.TypedValue) (string, error) {
_, tv := getFirstDefinedTypedValue(inputs, HttpInputUrl, types.InputMain)
if tv == nil {
return "", errors.New("target URL is required for HTTP function")
}
s, err := typedvalues.UnwrapString(tv)
if err != nil {
return "", err
}
if !strings.HasPrefix(s, "http") {
s = fmt.Sprintf("%s://%s", httpDefaultProtocol, s)
}
return s, err
}