github.com/MontFerret/ferret@v0.18.0/pkg/stdlib/io/net/http/request.go (about) 1 package http 2 3 import ( 4 "bytes" 5 "context" 6 "io" 7 h "net/http" 8 9 "github.com/MontFerret/ferret/pkg/runtime/core" 10 "github.com/MontFerret/ferret/pkg/runtime/values" 11 "github.com/MontFerret/ferret/pkg/runtime/values/types" 12 ) 13 14 type Params struct { 15 Method values.String 16 URL values.String 17 Headers *values.Object 18 Body values.Binary 19 } 20 21 // REQUEST makes a HTTP request. 22 // @param {Object} params - Request parameters. 23 // @param {String} params.method - HTTP method 24 // @param {String} params.url - Target url 25 // @param {Binary} params.body - Request data 26 // @param {Object} [params.headers] - HTTP headers 27 // @return {Binary} - Response in binary format 28 func REQUEST(ctx context.Context, args ...core.Value) (core.Value, error) { 29 return execMethod(ctx, "", args) 30 } 31 32 func execMethod(ctx context.Context, method values.String, args []core.Value) (core.Value, error) { 33 if err := core.ValidateArgs(args, 1, 1); err != nil { 34 return values.None, err 35 } 36 37 arg := args[0] 38 39 if err := core.ValidateType(arg, types.Object); err != nil { 40 return values.None, err 41 } 42 43 p, err := newParamsFrom(arg.(*values.Object)) 44 45 if err != nil { 46 return values.None, err 47 } 48 49 if method != "" { 50 p.Method = method 51 } 52 53 return makeRequest(ctx, p) 54 } 55 56 func makeRequest(ctx context.Context, params Params) (core.Value, error) { 57 client := h.Client{} 58 req, err := h.NewRequest(params.Method.String(), params.URL.String(), bytes.NewBuffer(params.Body)) 59 60 if err != nil { 61 return values.None, err 62 } 63 64 req.Header = h.Header{} 65 66 if params.Headers != nil { 67 params.Headers.ForEach(func(value core.Value, key string) bool { 68 req.Header.Set(key, value.String()) 69 70 return true 71 }) 72 } 73 74 resp, err := client.Do(req.WithContext(ctx)) 75 76 if err != nil { 77 return values.None, err 78 } 79 80 data, err := io.ReadAll(resp.Body) 81 82 if err != nil { 83 return values.None, err 84 } 85 86 defer resp.Body.Close() 87 88 return values.NewBinary(data), nil 89 } 90 91 func newParamsFrom(obj *values.Object) (Params, error) { 92 p := Params{} 93 94 method, exists := obj.Get("method") 95 96 if exists { 97 p.Method = values.ToString(method) 98 } 99 100 url, exists := obj.Get("url") 101 102 if !exists { 103 return Params{}, core.Error(core.ErrMissedArgument, ".url") 104 } 105 106 p.URL = values.NewString(url.String()) 107 108 headers, exists := obj.Get("headers") 109 110 if exists { 111 if err := core.ValidateType(headers, types.Object); err != nil { 112 return Params{}, core.Error(err, ".headers") 113 } 114 115 p.Headers = headers.(*values.Object) 116 } 117 118 body, exists := obj.Get("body") 119 120 if exists { 121 if core.IsTypeOf(body, types.Binary) { 122 p.Body = body.(values.Binary) 123 } else { 124 j, err := body.MarshalJSON() 125 126 if err != nil { 127 return Params{}, core.Error(err, ".body") 128 } 129 130 p.Body = values.NewBinary(j) 131 132 if p.Headers == nil { 133 p.Headers = values.NewObject() 134 } 135 136 p.Headers.Set("Content-Type", values.NewString("application/json")) 137 } 138 } 139 140 return p, nil 141 }