Added json postfilter, HttpRequest custom type
This commit is contained in:
@@ -7,11 +7,18 @@ import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/automation/service"
|
||||
atypes "github.com/cortezaproject/corteza-server/automation/types"
|
||||
agctx "github.com/cortezaproject/corteza-server/pkg/apigw/ctx"
|
||||
"github.com/cortezaproject/corteza-server/pkg/apigw/types"
|
||||
pe "github.com/cortezaproject/corteza-server/pkg/errors"
|
||||
errors "github.com/cortezaproject/corteza-server/pkg/errors"
|
||||
"github.com/cortezaproject/corteza-server/pkg/expr"
|
||||
)
|
||||
|
||||
type (
|
||||
typesRegistry interface {
|
||||
Type(ref string) expr.Type
|
||||
}
|
||||
redirection struct {
|
||||
types.FilterMeta
|
||||
|
||||
@@ -33,6 +40,17 @@ type (
|
||||
}
|
||||
}
|
||||
|
||||
jsonResponse struct {
|
||||
types.FilterMeta
|
||||
|
||||
reg typesRegistry
|
||||
|
||||
params struct {
|
||||
Exp *atypes.Expr
|
||||
Evaluable expr.Evaluable
|
||||
}
|
||||
}
|
||||
|
||||
defaultJsonResponse struct {
|
||||
types.FilterMeta
|
||||
}
|
||||
@@ -80,6 +98,10 @@ func (h redirection) Weight() int {
|
||||
func (h *redirection) Merge(params []byte) (types.Handler, error) {
|
||||
err := json.NewDecoder(bytes.NewBuffer(params)).Decode(&h.params)
|
||||
|
||||
if err != nil {
|
||||
return h, err
|
||||
}
|
||||
|
||||
loc, err := url.ParseRequestURI(h.params.Location)
|
||||
|
||||
if err != nil {
|
||||
@@ -135,7 +157,7 @@ func (j defaultJsonResponse) Handler() types.HandlerFunc {
|
||||
rw.WriteHeader(http.StatusAccepted)
|
||||
|
||||
if _, err := rw.Write([]byte(`{}`)); err != nil {
|
||||
return pe.Internal("could not write to body: %v", err)
|
||||
return errors.Internal("could not write to body: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -150,3 +172,106 @@ func checkStatus(typ string, status int) bool {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
func NewJsonResponse(reg typesRegistry) (e *jsonResponse) {
|
||||
e = &jsonResponse{}
|
||||
|
||||
e.Name = "jsonResponse"
|
||||
e.Label = "JSON response"
|
||||
e.Kind = types.PostFilter
|
||||
|
||||
e.Args = []*types.FilterMetaArg{
|
||||
{
|
||||
Type: "input",
|
||||
Label: "input",
|
||||
Options: map[string]interface{}{},
|
||||
},
|
||||
}
|
||||
|
||||
e.reg = reg
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (j jsonResponse) New() types.Handler {
|
||||
return NewJsonResponse(service.Registry())
|
||||
}
|
||||
|
||||
func (j jsonResponse) String() string {
|
||||
return fmt.Sprintf("apigw filter %s (%s)", j.Name, j.Label)
|
||||
}
|
||||
|
||||
func (j jsonResponse) Meta() types.FilterMeta {
|
||||
return j.FilterMeta
|
||||
}
|
||||
|
||||
func (j *jsonResponse) Merge(params []byte) (h types.Handler, err error) {
|
||||
var (
|
||||
parser = expr.NewParser()
|
||||
)
|
||||
|
||||
err = json.NewDecoder(bytes.NewBuffer(params)).Decode(&j.params.Exp)
|
||||
|
||||
if err != nil {
|
||||
return j, err
|
||||
}
|
||||
|
||||
j.params.Evaluable, err = parser.Parse(j.params.Exp.Expr)
|
||||
|
||||
if err != nil {
|
||||
return j, fmt.Errorf("could not evaluate expression: %s", err)
|
||||
}
|
||||
|
||||
j.params.Exp.SetEval(j.params.Evaluable)
|
||||
|
||||
return j, err
|
||||
}
|
||||
|
||||
func (j jsonResponse) Handler() types.HandlerFunc {
|
||||
return func(rw http.ResponseWriter, r *http.Request) (err error) {
|
||||
var (
|
||||
ctx = r.Context()
|
||||
scope = agctx.ScopeFromContext(ctx)
|
||||
|
||||
evald interface{}
|
||||
)
|
||||
|
||||
in, err := expr.NewVars(scope.Dict())
|
||||
|
||||
if err != nil {
|
||||
return errors.Internal("could not validate request data: %v", err)
|
||||
}
|
||||
|
||||
// set type to the registered expression from
|
||||
// any of the already registered types
|
||||
j.params.Exp.SetType(func(name string) (e expr.Type, err error) {
|
||||
if name == "" {
|
||||
name = "Any"
|
||||
}
|
||||
|
||||
if typ := j.reg.Type(name); typ != nil {
|
||||
return typ, nil
|
||||
} else {
|
||||
return nil, errors.Internal("unknown or unregistered type %s", name)
|
||||
}
|
||||
})
|
||||
|
||||
evald, err = j.params.Exp.Eval(ctx, in)
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
rw.Header().Add("Content-Type", "application/json")
|
||||
|
||||
switch v := evald.(type) {
|
||||
case string:
|
||||
rw.Write([]byte(v))
|
||||
default:
|
||||
e := json.NewEncoder(rw)
|
||||
err = e.Encode(v)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,16 +91,17 @@ func (h workflow) Handler() types.HandlerFunc {
|
||||
scope = agctx.ScopeFromContext(ctx)
|
||||
)
|
||||
|
||||
payload, err := scope.Get("payload")
|
||||
// original request with body as io.Reader
|
||||
// read-only
|
||||
ar, err := scope.Get("request")
|
||||
|
||||
if err != nil {
|
||||
return pe.Internal("could not get payload: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
// setup scope for workflow
|
||||
vv := map[string]interface{}{
|
||||
"payload": payload,
|
||||
"request": r,
|
||||
"request": ar,
|
||||
}
|
||||
|
||||
// get the request data and put it into vars
|
||||
@@ -152,8 +153,7 @@ func (h workflow) Handler() types.HandlerFunc {
|
||||
|
||||
scope = ss
|
||||
|
||||
scope.Set("request", r)
|
||||
scope.Set("payload", payload)
|
||||
scope.Set("request", ar)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -69,6 +69,7 @@ func (r *Registry) Preload() {
|
||||
|
||||
// postfilters
|
||||
r.Add("redirection", filter.NewRedirection())
|
||||
r.Add("jsonResponse", filter.NewJsonResponse(service.Registry()))
|
||||
r.Add("defaultJsonResponse", filter.NewDefaultJsonResponse())
|
||||
}
|
||||
|
||||
|
||||
+8
-14
@@ -1,18 +1,15 @@
|
||||
package apigw
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"time"
|
||||
|
||||
actx "github.com/cortezaproject/corteza-server/pkg/apigw/ctx"
|
||||
"github.com/cortezaproject/corteza-server/pkg/apigw/types"
|
||||
"github.com/cortezaproject/corteza-server/pkg/auth"
|
||||
"github.com/cortezaproject/corteza-server/pkg/options"
|
||||
"github.com/cortezaproject/corteza-server/system/automation"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
@@ -45,19 +42,16 @@ func (r route) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
|
||||
r.log.Debug("started serving route")
|
||||
|
||||
b, _ := io.ReadAll(req.Body)
|
||||
body := string(b)
|
||||
// create a new automation HttpRequest
|
||||
ar, err := automation.NewHttpRequest(req)
|
||||
|
||||
// write again
|
||||
req.Body = ioutil.NopCloser(bytes.NewBuffer(b))
|
||||
if err != nil {
|
||||
r.log.Error("could not prepare a request holder", zap.Error(err))
|
||||
return
|
||||
}
|
||||
|
||||
scope.Set("opts", r.opts)
|
||||
scope.Set("payload", body)
|
||||
|
||||
if r.opts.LogEnabled {
|
||||
o, _ := httputil.DumpRequest(req, r.opts.LogRequestBody)
|
||||
r.log.Debug("incoming request", zap.Any("request", string(o)))
|
||||
}
|
||||
scope.Set("request", ar)
|
||||
|
||||
req = req.WithContext(actx.ScopeToContext(ctx, &scope))
|
||||
|
||||
|
||||
@@ -65,6 +65,10 @@ func (s Scp) Get(k string) (v interface{}, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (s *Scp) Dict() map[string]interface{} {
|
||||
return *s
|
||||
}
|
||||
|
||||
func (s *Scp) Filter(fn func(k string, v interface{}) bool) *Scp {
|
||||
ss := Scp{}
|
||||
|
||||
@@ -78,3 +82,8 @@ func (s *Scp) Filter(fn func(k string, v interface{}) bool) *Scp {
|
||||
|
||||
return &ss
|
||||
}
|
||||
|
||||
func (s Scp) Has(k string) (has bool) {
|
||||
_, has = s[k]
|
||||
return
|
||||
}
|
||||
|
||||
Generated
+436
@@ -119,6 +119,203 @@ func (t *DocumentType) Assign(val interface{}) error {
|
||||
}
|
||||
}
|
||||
|
||||
// HttpRequest is an expression type, wrapper for *types.HttpRequest type
|
||||
type HttpRequest struct {
|
||||
value *types.HttpRequest
|
||||
mux sync.RWMutex
|
||||
}
|
||||
|
||||
// NewHttpRequest creates new instance of HttpRequest expression type
|
||||
func NewHttpRequest(val interface{}) (*HttpRequest, error) {
|
||||
if c, err := CastToHttpRequest(val); err != nil {
|
||||
return nil, fmt.Errorf("unable to create HttpRequest: %w", err)
|
||||
} else {
|
||||
return &HttpRequest{value: c}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Get return underlying value on HttpRequest
|
||||
func (t *HttpRequest) Get() interface{} {
|
||||
t.mux.RLock()
|
||||
defer t.mux.RUnlock()
|
||||
return t.value
|
||||
}
|
||||
|
||||
// GetValue returns underlying value on HttpRequest
|
||||
func (t *HttpRequest) GetValue() *types.HttpRequest {
|
||||
t.mux.RLock()
|
||||
defer t.mux.RUnlock()
|
||||
return t.value
|
||||
}
|
||||
|
||||
// Type return type name
|
||||
func (HttpRequest) Type() string { return "HttpRequest" }
|
||||
|
||||
// Cast converts value to *types.HttpRequest
|
||||
func (HttpRequest) Cast(val interface{}) (TypedValue, error) {
|
||||
return NewHttpRequest(val)
|
||||
}
|
||||
|
||||
// Assign new value to HttpRequest
|
||||
//
|
||||
// value is first passed through CastToHttpRequest
|
||||
func (t *HttpRequest) Assign(val interface{}) error {
|
||||
if c, err := CastToHttpRequest(val); err != nil {
|
||||
return err
|
||||
} else {
|
||||
t.value = c
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (t *HttpRequest) AssignFieldValue(key string, val TypedValue) error {
|
||||
t.mux.Lock()
|
||||
defer t.mux.Unlock()
|
||||
return assignToHttpRequest(t.value, key, val)
|
||||
}
|
||||
|
||||
// SelectGVal implements gval.Selector requirements
|
||||
//
|
||||
// It allows gval lib to access HttpRequest's underlying value (*types.HttpRequest)
|
||||
// and it's fields
|
||||
//
|
||||
func (t *HttpRequest) SelectGVal(ctx context.Context, k string) (interface{}, error) {
|
||||
t.mux.RLock()
|
||||
defer t.mux.RUnlock()
|
||||
return httpRequestGValSelector(t.value, k)
|
||||
}
|
||||
|
||||
// Select is field accessor for *types.HttpRequest
|
||||
//
|
||||
// Similar to SelectGVal but returns typed values
|
||||
func (t *HttpRequest) Select(k string) (TypedValue, error) {
|
||||
t.mux.RLock()
|
||||
defer t.mux.RUnlock()
|
||||
return httpRequestTypedValueSelector(t.value, k)
|
||||
}
|
||||
|
||||
func (t *HttpRequest) Has(k string) bool {
|
||||
t.mux.RLock()
|
||||
defer t.mux.RUnlock()
|
||||
switch k {
|
||||
case "Method":
|
||||
return true
|
||||
case "URL":
|
||||
return true
|
||||
case "Header":
|
||||
return true
|
||||
case "Body":
|
||||
return true
|
||||
case "Form":
|
||||
return true
|
||||
case "PostForm":
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// httpRequestGValSelector is field accessor for *types.HttpRequest
|
||||
func httpRequestGValSelector(res *types.HttpRequest, k string) (interface{}, error) {
|
||||
if res == nil {
|
||||
return nil, nil
|
||||
}
|
||||
switch k {
|
||||
case "Method":
|
||||
return res.Method, nil
|
||||
case "URL":
|
||||
return res.URL, nil
|
||||
case "Header":
|
||||
return res.Header, nil
|
||||
case "Body":
|
||||
return res.Body, nil
|
||||
case "Form":
|
||||
return res.Form, nil
|
||||
case "PostForm":
|
||||
return res.PostForm, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("unknown field '%s'", k)
|
||||
}
|
||||
|
||||
// httpRequestTypedValueSelector is field accessor for *types.HttpRequest
|
||||
func httpRequestTypedValueSelector(res *types.HttpRequest, k string) (TypedValue, error) {
|
||||
if res == nil {
|
||||
return nil, nil
|
||||
}
|
||||
switch k {
|
||||
case "Method":
|
||||
return NewString(res.Method)
|
||||
case "URL":
|
||||
return NewUrl(res.URL)
|
||||
case "Header":
|
||||
return NewKVV(res.Header)
|
||||
case "Body":
|
||||
return NewReader(res.Body)
|
||||
case "Form":
|
||||
return NewKVV(res.Form)
|
||||
case "PostForm":
|
||||
return NewKVV(res.PostForm)
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("unknown field '%s'", k)
|
||||
}
|
||||
|
||||
// assignToHttpRequest is field value setter for *types.HttpRequest
|
||||
func assignToHttpRequest(res *types.HttpRequest, k string, val interface{}) error {
|
||||
switch k {
|
||||
case "Method":
|
||||
aux, err := CastToString(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
res.Method = aux
|
||||
return nil
|
||||
case "URL":
|
||||
aux, err := CastToUrl(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
res.URL = aux
|
||||
return nil
|
||||
case "Header":
|
||||
aux, err := CastToKVV(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
res.Header = aux
|
||||
return nil
|
||||
case "Body":
|
||||
aux, err := CastToReader(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
res.Body = aux
|
||||
return nil
|
||||
case "Form":
|
||||
aux, err := CastToKVV(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
res.Form = aux
|
||||
return nil
|
||||
case "PostForm":
|
||||
aux, err := CastToKVV(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
res.PostForm = aux
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("unknown field '%s'", k)
|
||||
}
|
||||
|
||||
// QueueMessage is an expression type, wrapper for *types.QueueMessage type
|
||||
type QueueMessage struct {
|
||||
value *types.QueueMessage
|
||||
@@ -1102,6 +1299,245 @@ func assignToTemplateMeta(res types.TemplateMeta, k string, val interface{}) err
|
||||
return fmt.Errorf("unknown field '%s'", k)
|
||||
}
|
||||
|
||||
// Url is an expression type, wrapper for *types.Url type
|
||||
type Url struct {
|
||||
value *types.Url
|
||||
mux sync.RWMutex
|
||||
}
|
||||
|
||||
// NewUrl creates new instance of Url expression type
|
||||
func NewUrl(val interface{}) (*Url, error) {
|
||||
if c, err := CastToUrl(val); err != nil {
|
||||
return nil, fmt.Errorf("unable to create Url: %w", err)
|
||||
} else {
|
||||
return &Url{value: c}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Get return underlying value on Url
|
||||
func (t *Url) Get() interface{} {
|
||||
t.mux.RLock()
|
||||
defer t.mux.RUnlock()
|
||||
return t.value
|
||||
}
|
||||
|
||||
// GetValue returns underlying value on Url
|
||||
func (t *Url) GetValue() *types.Url {
|
||||
t.mux.RLock()
|
||||
defer t.mux.RUnlock()
|
||||
return t.value
|
||||
}
|
||||
|
||||
// Type return type name
|
||||
func (Url) Type() string { return "Url" }
|
||||
|
||||
// Cast converts value to *types.Url
|
||||
func (Url) Cast(val interface{}) (TypedValue, error) {
|
||||
return NewUrl(val)
|
||||
}
|
||||
|
||||
// Assign new value to Url
|
||||
//
|
||||
// value is first passed through CastToUrl
|
||||
func (t *Url) Assign(val interface{}) error {
|
||||
if c, err := CastToUrl(val); err != nil {
|
||||
return err
|
||||
} else {
|
||||
t.value = c
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Url) AssignFieldValue(key string, val TypedValue) error {
|
||||
t.mux.Lock()
|
||||
defer t.mux.Unlock()
|
||||
return assignToUrl(t.value, key, val)
|
||||
}
|
||||
|
||||
// SelectGVal implements gval.Selector requirements
|
||||
//
|
||||
// It allows gval lib to access Url's underlying value (*types.Url)
|
||||
// and it's fields
|
||||
//
|
||||
func (t *Url) SelectGVal(ctx context.Context, k string) (interface{}, error) {
|
||||
t.mux.RLock()
|
||||
defer t.mux.RUnlock()
|
||||
return urlGValSelector(t.value, k)
|
||||
}
|
||||
|
||||
// Select is field accessor for *types.Url
|
||||
//
|
||||
// Similar to SelectGVal but returns typed values
|
||||
func (t *Url) Select(k string) (TypedValue, error) {
|
||||
t.mux.RLock()
|
||||
defer t.mux.RUnlock()
|
||||
return urlTypedValueSelector(t.value, k)
|
||||
}
|
||||
|
||||
func (t *Url) Has(k string) bool {
|
||||
t.mux.RLock()
|
||||
defer t.mux.RUnlock()
|
||||
switch k {
|
||||
case "Scheme":
|
||||
return true
|
||||
case "Opaque":
|
||||
return true
|
||||
case "Host":
|
||||
return true
|
||||
case "Path":
|
||||
return true
|
||||
case "RawPath":
|
||||
return true
|
||||
case "ForceQuery":
|
||||
return true
|
||||
case "RawQuery":
|
||||
return true
|
||||
case "Fragment":
|
||||
return true
|
||||
case "RawFragment":
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// urlGValSelector is field accessor for *types.Url
|
||||
func urlGValSelector(res *types.Url, k string) (interface{}, error) {
|
||||
if res == nil {
|
||||
return nil, nil
|
||||
}
|
||||
switch k {
|
||||
case "Scheme":
|
||||
return res.Scheme, nil
|
||||
case "Opaque":
|
||||
return res.Opaque, nil
|
||||
case "Host":
|
||||
return res.Host, nil
|
||||
case "Path":
|
||||
return res.Path, nil
|
||||
case "RawPath":
|
||||
return res.RawPath, nil
|
||||
case "ForceQuery":
|
||||
return res.ForceQuery, nil
|
||||
case "RawQuery":
|
||||
return res.RawQuery, nil
|
||||
case "Fragment":
|
||||
return res.Fragment, nil
|
||||
case "RawFragment":
|
||||
return res.RawFragment, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("unknown field '%s'", k)
|
||||
}
|
||||
|
||||
// urlTypedValueSelector is field accessor for *types.Url
|
||||
func urlTypedValueSelector(res *types.Url, k string) (TypedValue, error) {
|
||||
if res == nil {
|
||||
return nil, nil
|
||||
}
|
||||
switch k {
|
||||
case "Scheme":
|
||||
return NewString(res.Scheme)
|
||||
case "Opaque":
|
||||
return NewString(res.Opaque)
|
||||
case "Host":
|
||||
return NewString(res.Host)
|
||||
case "Path":
|
||||
return NewString(res.Path)
|
||||
case "RawPath":
|
||||
return NewString(res.RawPath)
|
||||
case "ForceQuery":
|
||||
return NewBoolean(res.ForceQuery)
|
||||
case "RawQuery":
|
||||
return NewString(res.RawQuery)
|
||||
case "Fragment":
|
||||
return NewString(res.Fragment)
|
||||
case "RawFragment":
|
||||
return NewString(res.RawFragment)
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("unknown field '%s'", k)
|
||||
}
|
||||
|
||||
// assignToUrl is field value setter for *types.Url
|
||||
func assignToUrl(res *types.Url, k string, val interface{}) error {
|
||||
switch k {
|
||||
case "Scheme":
|
||||
aux, err := CastToString(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
res.Scheme = aux
|
||||
return nil
|
||||
case "Opaque":
|
||||
aux, err := CastToString(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
res.Opaque = aux
|
||||
return nil
|
||||
case "Host":
|
||||
aux, err := CastToString(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
res.Host = aux
|
||||
return nil
|
||||
case "Path":
|
||||
aux, err := CastToString(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
res.Path = aux
|
||||
return nil
|
||||
case "RawPath":
|
||||
aux, err := CastToString(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
res.RawPath = aux
|
||||
return nil
|
||||
case "ForceQuery":
|
||||
aux, err := CastToBoolean(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
res.ForceQuery = aux
|
||||
return nil
|
||||
case "RawQuery":
|
||||
aux, err := CastToString(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
res.RawQuery = aux
|
||||
return nil
|
||||
case "Fragment":
|
||||
aux, err := CastToString(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
res.Fragment = aux
|
||||
return nil
|
||||
case "RawFragment":
|
||||
aux, err := CastToString(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
res.RawFragment = aux
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("unknown field '%s'", k)
|
||||
}
|
||||
|
||||
// User is an expression type, wrapper for *types.User type
|
||||
type User struct {
|
||||
value *types.User
|
||||
|
||||
@@ -5,6 +5,8 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/pkg/actionlog"
|
||||
"github.com/cortezaproject/corteza-server/pkg/expr"
|
||||
@@ -184,6 +186,54 @@ func CastToQueueMessage(val interface{}) (out *types.QueueMessage, err error) {
|
||||
}
|
||||
}
|
||||
|
||||
func CastToHttpRequest(val interface{}) (out *types.HttpRequest, err error) {
|
||||
switch val := val.(type) {
|
||||
case expr.Iterator:
|
||||
out = &types.HttpRequest{}
|
||||
return out, val.Each(func(k string, v expr.TypedValue) error {
|
||||
return assignToHttpRequest(out, k, v)
|
||||
})
|
||||
}
|
||||
|
||||
switch val := expr.UntypedValue(val).(type) {
|
||||
case *http.Request:
|
||||
rr := &types.HttpRequest{}
|
||||
|
||||
assignToHttpRequest(rr, "Method", val.Method)
|
||||
assignToHttpRequest(rr, "URL", val.URL)
|
||||
assignToHttpRequest(rr, "Header", val.Header)
|
||||
assignToHttpRequest(rr, "Body", val.Body)
|
||||
assignToHttpRequest(rr, "Form", val.Form)
|
||||
assignToHttpRequest(rr, "PostForm", val.PostForm)
|
||||
|
||||
return rr, nil
|
||||
case *types.HttpRequest:
|
||||
return val, nil
|
||||
case nil:
|
||||
return &types.HttpRequest{}, nil
|
||||
default:
|
||||
return &types.HttpRequest{}, fmt.Errorf("unable to cast type %T to %T", val, out)
|
||||
}
|
||||
}
|
||||
|
||||
func CastToUrl(val interface{}) (out *types.Url, err error) {
|
||||
switch val := expr.UntypedValue(val).(type) {
|
||||
case *url.URL:
|
||||
u := &types.Url{}
|
||||
|
||||
m, _ := json.Marshal(val)
|
||||
_ = json.Unmarshal(m, u)
|
||||
|
||||
return u, nil
|
||||
case *types.Url:
|
||||
return val, nil
|
||||
case nil:
|
||||
return &types.Url{}, nil
|
||||
default:
|
||||
return &types.Url{}, fmt.Errorf("unable to cast type %T to %T", val, out)
|
||||
}
|
||||
}
|
||||
|
||||
func (doc renderedDocument) String() string {
|
||||
aux, _ := ioutil.ReadAll(doc.Document)
|
||||
return string(aux)
|
||||
|
||||
@@ -72,6 +72,29 @@ types:
|
||||
- { name: 'Queue', exprType: 'String', goType: 'string' }
|
||||
- { name: 'Payload', exprType: 'Bytes', goType: '[]byte' }
|
||||
|
||||
HttpRequest:
|
||||
as: '*types.HttpRequest'
|
||||
struct:
|
||||
- { name: 'Method', exprType: 'String', goType: 'string' }
|
||||
- { name: 'URL', exprType: 'Url', goType: 'url.Url' }
|
||||
- { name: 'Header', exprType: 'KVV', goType: 'map[string][]string' }
|
||||
- { name: 'Body', exprType: 'Reader', goType: 'io.Reader' }
|
||||
- { name: 'Form', exprType: 'KVV', goType: 'map[string][]string' }
|
||||
- { name: 'PostForm', exprType: 'KVV', goType: 'map[string][]string' }
|
||||
|
||||
Url:
|
||||
as: '*types.Url'
|
||||
struct:
|
||||
- { name: 'Scheme', exprType: 'String', goType: 'string' }
|
||||
- { name: 'Opaque', exprType: 'String', goType: 'string' }
|
||||
- { name: 'Host', exprType: 'String', goType: 'string' }
|
||||
- { name: 'Path', exprType: 'String', goType: 'string' }
|
||||
- { name: 'RawPath', exprType: 'String', goType: 'string' }
|
||||
- { name: 'ForceQuery', exprType: 'Boolean', goType: 'bool' }
|
||||
- { name: 'RawQuery', exprType: 'String', goType: 'string' }
|
||||
- { name: 'Fragment', exprType: 'String', goType: 'string' }
|
||||
- { name: 'RawFragment', exprType: 'String', goType: 'string' }
|
||||
|
||||
RbacResource:
|
||||
as: 'rbac.Resource'
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
type (
|
||||
HttpRequest struct {
|
||||
Method string `json:"method"`
|
||||
URL *Url `json:"url"`
|
||||
Header map[string][]string `json:"header"`
|
||||
Body io.Reader `json:"body"`
|
||||
Form map[string][]string `json:"form"`
|
||||
PostForm map[string][]string `json:"post_form"`
|
||||
}
|
||||
|
||||
Url struct {
|
||||
Scheme string
|
||||
Opaque string
|
||||
Host string
|
||||
Path string
|
||||
RawPath string
|
||||
ForceQuery bool
|
||||
RawQuery string
|
||||
Fragment string
|
||||
RawFragment string
|
||||
}
|
||||
)
|
||||
Reference in New Issue
Block a user