-
-
Notifications
You must be signed in to change notification settings - Fork 299
/
response.go
119 lines (93 loc) · 2.72 KB
/
response.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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package drivers
import (
"context"
"github.com/wI2L/jettison"
"github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
)
// HTTPResponse HTTP response object.
type HTTPResponse struct {
URL string
StatusCode int
Status string
Headers *HTTPHeaders
ResponseTime float64
}
func (resp *HTTPResponse) Type() core.Type {
return HTTPResponseType
}
func (resp *HTTPResponse) String() string {
return resp.Status
}
func (resp *HTTPResponse) Compare(other core.Value) int64 {
if other.Type() != HTTPResponseType {
return Compare(HTTPResponseType, other.Type())
}
// this is a safe cast. Only *HTTPResponse implements core.Value.
// HTTPResponse does not.
otherResp := other.(*HTTPResponse)
comp := resp.Headers.Compare(otherResp.Headers)
if comp != 0 {
return comp
}
// it makes no sense to compare Status strings
// because they are always equal if StatusCode's are equal
return values.NewInt(resp.StatusCode).
Compare(values.NewInt(resp.StatusCode))
}
func (resp *HTTPResponse) Unwrap() interface{} {
return resp
}
func (resp *HTTPResponse) Copy() core.Value {
return *(&resp)
}
func (resp *HTTPResponse) Hash() uint64 {
return values.Parse(resp).Hash()
}
// responseMarshal is a structure that repeats HTTPResponse. It allows
// easily Marshal the HTTPResponse object.
type responseMarshal struct {
URL string `json:"url"`
StatusCode int `json:"status_code"`
Status string `json:"status"`
Headers *HTTPHeaders `json:"headers"`
ResponseTime float64 `json:"response_time"`
}
func (resp *HTTPResponse) MarshalJSON() ([]byte, error) {
if resp == nil {
return values.None.MarshalJSON()
}
return jettison.MarshalOpts(responseMarshal(*resp), jettison.NoHTMLEscaping())
}
func (resp *HTTPResponse) GetIn(ctx context.Context, path []core.Value) (core.Value, core.PathError) {
if len(path) == 0 {
return resp, nil
}
segmentIdx := 0
segment := path[segmentIdx]
if typ := segment.Type(); typ != types.String {
return values.None, core.NewPathError(core.TypeError(typ, types.String), segmentIdx)
}
field := segment.String()
switch field {
case "url", "URL":
return values.NewString(resp.URL), nil
case "status":
return values.NewString(resp.Status), nil
case "statusCode":
return values.NewInt(resp.StatusCode), nil
case "headers":
if len(path) == 1 {
return resp.Headers, nil
}
out, pathErr := resp.Headers.GetIn(ctx, path[1:])
if pathErr != nil {
return values.None, core.NewPathErrorFrom(pathErr, segmentIdx)
}
return out, nil
case "responseTime":
return values.NewFloat(resp.ResponseTime), nil
}
return values.None, nil
}