Skip to content

Commit 9ddd96d

Browse files
authored
feat(before_request): impl/allow editing req body, or setting it if nil (#257)
Signed-off-by: Pierre Fenoll <[email protected]>
1 parent 41fb36d commit 9ddd96d

File tree

5 files changed

+105
-12
lines changed

5 files changed

+105
-12
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,11 @@ def add_special_headers(ctx):
160160
token = monkey.env("DEV_API_TOKEN", "dev token is unset!")
161161
req.headers.set("authorization".title(), "Bearer " + token)
162162

163+
# Let's edit (a possibly-empty) body
164+
if req.body == None:
165+
req.body = {}
166+
req.body["key"] = 42
167+
163168
monkey.check(
164169
name = "adds_special_headers",
165170
before_request = add_special_headers,

Tagfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.51.0
1+
0.52.0

fuzzymonkey.star

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ def add_special_headers(ctx):
5454
token = monkey.env("DEV_API_TOKEN", "dev token is unset!")
5555
req.headers.set("authorization".title(), "Bearer " + token)
5656

57+
# Let's edit (a possibly-empty) body
58+
if req.body == None:
59+
req.body = {}
60+
req.body["key"] = 42
61+
5762
monkey.check(
5863
name = "adds_special_headers",
5964
before_request = add_special_headers,

pkg/runtime/cx_request_before_request.go

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,21 +23,26 @@ type cxRequestBeforeRequest struct {
2323

2424
method, url starlark.String
2525
headers *cxHead
26-
body *structpb.Value //FIXME: starlark.Value + test that edits .body (as num and as dict/list, and as set)
26+
body starlark.Value
2727
}
2828

2929
func newCxRequestBeforeRequest(input *fm.Srv_Call_Input) *cxRequestBeforeRequest {
3030
switch x := input.GetInput().(type) {
3131

3232
case *fm.Srv_Call_Input_HttpRequest_:
3333
r := input.GetHttpRequest()
34+
// var bodyValue starlark.Value = starlark.None
35+
var bodyValue starlark.Value = nil
36+
if body := r.GetBody(); body != nil {
37+
bodyValue = starlarkvalue.FromProtoValue(body)
38+
}
3439
return &cxRequestBeforeRequest{
3540
ty: cxRequestHttp,
3641
method: starlark.String(r.GetMethod()),
3742
url: starlark.String(r.GetUrl()),
3843
headers: newcxHead(r.GetHeaders()),
3944
//content: absent as encoding will only happen later
40-
body: r.GetBody(),
45+
body: bodyValue,
4146
}
4247

4348
default:
@@ -55,24 +60,25 @@ func (cr *cxRequestBeforeRequest) IntoProto(err error) *fm.Clt_CallRequestRaw {
5560
switch cr.ty {
5661
case cxRequestHttp:
5762
var body []byte
63+
var bodyDecoded *structpb.Value
5864
if cr.body != nil {
59-
if body, err = protojson.Marshal(cr.body); err != nil {
65+
bodyDecoded = starlarkvalue.ToProtoValue(cr.body)
66+
if body, err = protojson.Marshal(bodyDecoded); err != nil {
6067
log.Println("[ERR]", err)
6168
// return after sending msg
6269
if len(reason) == 0 && err != nil {
6370
reason = strings.Split(err.Error(), "\n")
6471
}
6572
}
6673
}
67-
//TODO: impl ToProtoValue
6874
return &fm.Clt_CallRequestRaw_Input{
6975
Input: &fm.Clt_CallRequestRaw_Input_HttpRequest_{
7076
HttpRequest: &fm.Clt_CallRequestRaw_Input_HttpRequest{
7177
Method: string(cr.method),
7278
Url: string(cr.url),
7379
Headers: cr.headers.IntoProto(),
7480
Body: body,
75-
BodyDecoded: cr.body,
81+
BodyDecoded: bodyDecoded,
7682
}}}
7783

7884
default:
@@ -97,8 +103,10 @@ func (cr *cxRequestBeforeRequest) Truth() starlark.Bool { return true }
97103
func (cr *cxRequestBeforeRequest) Type() string { return cr.ty }
98104

99105
func (cr *cxRequestBeforeRequest) Freeze() {
100-
// cr.body.Freeze() FIXME
106+
cr.body.Freeze()
101107
cr.headers.Freeze()
108+
cr.method.Freeze()
109+
cr.url.Freeze()
102110
}
103111

104112
func (cr *cxRequestBeforeRequest) AttrNames() []string {
@@ -113,13 +121,10 @@ func (cr *cxRequestBeforeRequest) AttrNames() []string {
113121
func (cr *cxRequestBeforeRequest) Attr(name string) (starlark.Value, error) {
114122
switch name {
115123
case "body":
116-
var body starlark.Value = starlark.None
117124
if cr.body != nil {
118-
body = starlarkvalue.FromProtoValue(cr.body)
125+
return cr.body, nil
119126
}
120-
body.Freeze()
121-
// TODO: call ProtoCompatible here
122-
return body, nil
127+
return starlark.None, nil
123128
case "headers":
124129
return cr.headers, nil
125130
case "method":
@@ -130,3 +135,12 @@ func (cr *cxRequestBeforeRequest) Attr(name string) (starlark.Value, error) {
130135
return nil, nil // no such method
131136
}
132137
}
138+
139+
var _ starlark.HasSetField = (*cxRequestBeforeRequest)(nil)
140+
141+
func (cr *cxRequestBeforeRequest) SetField(name string, val starlark.Value) error {
142+
if name == "body" && cr.body == nil {
143+
cr.body = val
144+
}
145+
return nil
146+
}

pkg/starlarkvalue/to_protovalue.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package starlarkvalue
2+
3+
import (
4+
"fmt"
5+
6+
"go.starlark.net/starlark"
7+
"google.golang.org/protobuf/types/known/structpb"
8+
)
9+
10+
// ToProtoValue converts a Starlark value to a Google Well-Known-Type value.
11+
// Panics on unexpected starlark value.
12+
func ToProtoValue(x starlark.Value) *structpb.Value {
13+
switch x := x.(type) {
14+
15+
case starlark.NoneType:
16+
return &structpb.Value{Kind: &structpb.Value_NullValue{
17+
NullValue: structpb.NullValue_NULL_VALUE}}
18+
19+
case starlark.Bool:
20+
return &structpb.Value{Kind: &structpb.Value_BoolValue{
21+
BoolValue: bool(x)}}
22+
23+
case starlark.Float:
24+
return &structpb.Value{Kind: &structpb.Value_NumberValue{
25+
NumberValue: float64(x)}}
26+
27+
case starlark.Int:
28+
if x, ok := x.Int64(); ok {
29+
return &structpb.Value{Kind: &structpb.Value_NumberValue{
30+
NumberValue: float64(x)}}
31+
}
32+
panic(fmt.Errorf("unexpected value of type %s: %s", x.Type(), x.String()))
33+
34+
case starlark.String:
35+
return &structpb.Value{Kind: &structpb.Value_StringValue{
36+
StringValue: x.GoString()}}
37+
38+
case *starlark.List:
39+
n := x.Len()
40+
vs := make([]*structpb.Value, 0, n)
41+
for i := 0; i < n; i++ {
42+
vs = append(vs, ToProtoValue(x.Index(i)))
43+
}
44+
return &structpb.Value{Kind: &structpb.Value_ListValue{ListValue: &structpb.ListValue{
45+
Values: vs}}}
46+
47+
// case starlark.Tuple: // Encodes starlark.Tuple as array.
48+
// n := x.Len()
49+
// vs := make([]*structpb.Value, 0, n)
50+
// for i := 0; i < n; i++ {
51+
// vs = append(vs, ToProtoValue(x.Index(i)))
52+
// }
53+
// return &structpb.Value{Kind: &structpb.Value_ListValue{ListValue: &structpb.ListValue{
54+
// Values: vs}}}
55+
56+
case *starlark.Dict:
57+
vs := make(map[string]*structpb.Value, x.Len())
58+
for _, kv := range x.Items() {
59+
k := kv.Index(0).(starlark.String).GoString()
60+
v := ToProtoValue(kv.Index(1))
61+
vs[k] = v
62+
}
63+
return &structpb.Value{Kind: &structpb.Value_StructValue{StructValue: &structpb.Struct{
64+
Fields: vs}}}
65+
66+
default:
67+
panic(fmt.Errorf("unexpected value of type %s: %s", x.Type(), x.String()))
68+
}
69+
}

0 commit comments

Comments
 (0)