3
0

Added registry, updated handlers

Updated modules

Added function definition endpoint
This commit is contained in:
Peter Grlica
2021-07-06 17:21:29 +02:00
parent 2388158141
commit 4e43020bf0
18 changed files with 529 additions and 248 deletions

View File

@@ -173,3 +173,16 @@ func (s *apigw) Init(ctx context.Context, route ...*route) {
}
}
}
func (s *apigw) Funcs(kind string) (list functionMetaList) {
list = s.reg.All()
if kind != "" {
list, _ = list.Filter(func(fm *functionMeta) (bool, error) {
// return fm.
return fm.Kind == kind, nil
})
}
return
}

View File

@@ -2,51 +2,56 @@ package apigw
import (
"context"
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"github.com/cortezaproject/corteza-server/pkg/expr"
"github.com/cortezaproject/corteza-server/pkg/wfexec"
"github.com/cortezaproject/corteza-server/system/types"
"github.com/davecgh/go-spew/spew"
)
type (
redirectExpediterArgs struct {
Location string
expediterRedirection struct{}
errorHandler struct {
name string
args []string
weight int
step int
}
)
func redirectExpediter(c context.Context, params *expr.Vars) wfHandler {
var (
clv = redirectExpediterArgs{}
)
return func(c context.Context, er *wfexec.ExecRequest) (r wfexec.ExecResponse, err error) {
params.Decode(&clv)
spew.Dump("redirect expediter fn()", clv)
e := er.Scope.GetValue()["envelope"]
ee := e.Get().(envelope)
http.Redirect(ee.Writer, ee.Request, clv.Location, http.StatusTemporaryRedirect)
r = &expr.Vars{}
return
func (h expediterRedirection) Meta(f *types.Function) functionMeta {
return functionMeta{
Step: 3,
Name: "expediterRedirection",
Label: "Redirection expediter",
Kind: "expediter",
Weight: int(f.Weight),
Params: f.Params,
}
}
func expediterErrorFn(c context.Context, er *wfexec.ExecRequest) (r wfexec.ExecResponse, err error) {
// spew.Dump("expediter error fn()", er)
func (h expediterRedirection) Handler() handlerFunc {
return func(ctx context.Context, scope *scp, params map[string]interface{}, ff functionHandler) error {
scope.writer.Header().Add(fmt.Sprintf("step_%d", ff.step), ff.name)
http.Redirect(scope.writer, scope.req, params["location"].(string), http.StatusFound)
e := er.Scope.GetValue()["error"]
values := er.Scope.GetValue()["writer"]
writer := values.Get()
eValue := e.Get()
fmt.Fprintf(writer.(*httptest.ResponseRecorder), fmt.Sprintf(`{"msg": "%s"}`, eValue))
writer.(*httptest.ResponseRecorder).Code = http.StatusBadGateway
r = &expr.Vars{}
return
return nil
}
}
func (pp errorHandler) Exec(ctx context.Context, scope *scp, err error) {
type (
responseHelper struct {
Msg string `json:"msg"`
}
)
resp := responseHelper{
Msg: err.Error(),
}
spew.Dump("ERR in expediter", err, resp)
json.NewEncoder(scope.writer).Encode(resp)
}

View File

@@ -7,6 +7,8 @@ import (
)
type (
functionMetaList []*functionMeta
Handler interface {
Handler() handlerFunc
Meta(f *types.Function) functionMeta
@@ -15,12 +17,20 @@ type (
handlerFunc func(context.Context, *scp, map[string]interface{}, functionHandler) error
functionMeta struct {
step int
weight int
name string
label string
kind string
params map[string]interface{}
Step int `json:"step"`
Weight int `json:"-"`
Name string `json:"name"`
Label string `json:"label"`
Kind string `json:"kind"`
Params map[string]interface{} `json:"-"`
Args []*functionMetaArg `json:"params,omitempty"`
}
functionMetaArg struct {
Label string `json:"label"`
Type string `json:"type"`
Example string `json:"example"`
Options map[string]interface{} `json:"options"`
}
functionHandler struct {
@@ -43,12 +53,12 @@ func (ff *functionHandler) SetHandler(h handlerFunc) {
}
func (ff *functionHandler) Merge(ctx context.Context, p functionMeta) {
ff.step = p.step
ff.kind = p.kind
ff.label = p.label
ff.name = p.name
ff.weight = p.weight
ff.params = p.params
ff.step = p.Step
ff.kind = p.Kind
ff.label = p.Label
ff.name = p.Name
ff.weight = p.Weight
ff.params = p.Params
}
func (ff functionHandler) Weight() int {
@@ -56,3 +66,17 @@ func (ff functionHandler) Weight() int {
// per step, we're doing something wrong
return ff.step*1000 + ff.weight
}
func (fm functionMetaList) Filter(f func(*functionMeta) (bool, error)) (out functionMetaList, err error) {
var ok bool
out = functionMetaList{}
for i := range fm {
if ok, err = f(fm[i]); err != nil {
return
} else if ok {
out = append(out, fm[i])
}
}
return
}

View File

@@ -1,42 +0,0 @@
package apigw
import (
"context"
"errors"
"github.com/cortezaproject/corteza-server/pkg/expr"
"github.com/cortezaproject/corteza-server/pkg/wfexec"
"github.com/davecgh/go-spew/spew"
)
type (
authenticationOriginMatcherArgs struct {
Origin string
}
)
func authenticationOriginMatcher(c context.Context, params *expr.Vars) wfHandler {
var (
aomp = authenticationOriginMatcherArgs{}
)
return func(c context.Context, er *wfexec.ExecRequest) (r wfexec.ExecResponse, err error) {
params.Decode(&aomp)
spew.Dump("authentication origin matcher fn()", aomp)
e := er.Scope.GetValue()["envelope"]
ee := e.Get().(envelope)
origin := ee.Request.Header.Get("Origin")
spew.Dump("input, real", aomp.Origin, origin)
if aomp.Origin != origin {
err = errors.New("origin fail")
return
}
r = &expr.Vars{}
return
}
}

View File

@@ -3,53 +3,88 @@ package apigw
import (
"context"
"github.com/cortezaproject/corteza-server/pkg/expr"
"github.com/cortezaproject/corteza-server/pkg/wfexec"
"github.com/davecgh/go-spew/spew"
"github.com/cortezaproject/corteza-server/pkg/eventbus"
"github.com/cortezaproject/corteza-server/system/types"
)
func formDataProcesserFn(c context.Context, er *wfexec.ExecRequest) (r wfexec.ExecResponse, err error) {
type (
formDataProcesserResponse struct {
Name string `json:"name"`
}
)
type (
dispatcher interface {
Dispatch(ctx context.Context, ev eventbus.Event)
}
spew.Dump("step processer fn()")
processerWorkflow struct {
d dispatcher
}
)
e := er.Scope.GetValue()["envelope"]
ee := e.Get()
// ee.(envelope).Writer.WriteHeader(int(id))
ee.(envelope).Writer.Write([]byte(`{"test":"foobar"}`))
e.Assign(ee)
// req := values.Get()
// ww := wr.Get()
// writer := ww.(http.ResponseWriter)
// formValue := req.(*http.Request).PostFormValue("name")
// resp := formDataProcesserResponse{
// // Name: fmt.Sprintf("AA %s AA", formValue),
// Name: "formValue",
// }
// encoder := json.NewEncoder(writer)
// encoder.Encode(resp)
// writer.(*httptest.ResponseRecorder).Header()["Content-Type"] = []string{"application/json"}
// writer.Header().Set("Content-Type", "application/json3")
// spew.Dump(writer.(*httptest.ResponseRecorder).Header())
// a, b := expr.NewKV(writer)
// spew.Dump("Aaaaaaaaaaa", a)
vv := &expr.Vars{}
// vv.Set("writer", writer)
r = vv
return
func (h processerWorkflow) Meta(f *types.Function) functionMeta {
return functionMeta{
Step: 2,
Name: "processerWorkflow",
Label: "Workflow processer",
Kind: "processer",
Weight: int(f.Weight),
Params: f.Params,
Args: []*functionMetaArg{
{
Type: "workflow",
Label: "workflow",
Options: map[string]interface{}{},
},
},
}
}
func (h processerWorkflow) Handler() handlerFunc {
return func(ctx context.Context, scope *scp, params map[string]interface{}, ff functionHandler) error {
// h.d.Dispatch(c, event.ApiOnProcess(&envlp))
return nil
}
}
// func formDataProcesserFn(c context.Context, er *wfexec.ExecRequest) (r wfexec.ExecResponse, err error) {
// type (
// formDataProcesserResponse struct {
// Name string `json:"name"`
// }
// )
// spew.Dump("step processer fn()")
// e := er.Scope.GetValue()["envelope"]
// ee := e.Get()
// // ee.(envelope).Writer.WriteHeader(int(id))
// ee.(envelope).Writer.Write([]byte(`{"test":"foobar"}`))
// e.Assign(ee)
// // req := values.Get()
// // ww := wr.Get()
// // writer := ww.(http.ResponseWriter)
// // formValue := req.(*http.Request).PostFormValue("name")
// // resp := formDataProcesserResponse{
// // // Name: fmt.Sprintf("AA %s AA", formValue),
// // Name: "formValue",
// // }
// // encoder := json.NewEncoder(writer)
// // encoder.Encode(resp)
// // writer.(*httptest.ResponseRecorder).Header()["Content-Type"] = []string{"application/json"}
// // writer.Header().Set("Content-Type", "application/json3")
// // spew.Dump(writer.(*httptest.ResponseRecorder).Header())
// // a, b := expr.NewKV(writer)
// // spew.Dump("Aaaaaaaaaaa", a)
// vv := &expr.Vars{}
// // vv.Set("writer", writer)
// r = vv
// return
// }

52
pkg/apigw/registry.go Normal file
View File

@@ -0,0 +1,52 @@
package apigw
import (
"fmt"
"github.com/cortezaproject/corteza-server/system/types"
)
type (
registry struct {
h map[string]Handler
}
)
func NewRegistry() *registry {
return &registry{
h: map[string]Handler{},
}
}
func (r *registry) Add(n string, h Handler) {
r.h[n] = h
}
func (r *registry) Get(identifier string) (Handler, error) {
var (
ok bool
f Handler
)
if f, ok = r.h[identifier]; !ok {
return nil, fmt.Errorf("could not get element from registry: %s", identifier)
}
return f, nil
}
func (r *registry) All() (list functionMetaList) {
for _, handler := range r.h {
m := handler.Meta(&types.Function{})
list = append(list, &m)
}
return
}
func (r *registry) Preload() {
r.Add("verifierQueryParam", verifierQueryParam{})
r.Add("verifierOrigin", verifierOrigin{})
r.Add("expediterRedirection", expediterRedirection{})
r.Add("processerWorkflow", processerWorkflow{})
}

View File

@@ -3,62 +3,30 @@ package apigw
import (
"context"
"net/http"
"github.com/cortezaproject/corteza-server/pkg/expr"
"github.com/cortezaproject/corteza-server/pkg/logger"
"github.com/cortezaproject/corteza-server/pkg/wfexec"
"github.com/davecgh/go-spew/spew"
)
type (
route struct {
ID uint64
endpoint string
method string
graph *wfexec.Graph
steps []wfexec.Step
fns wfHandlerList
pipe *pl
}
)
func (r route) validate(req *http.Request) (err error) {
// if req.Method != r.method {
// err = errors.New("http method invalid")
// }
return
}
func (r route) ServeHTTP(w http.ResponseWriter, req *http.Request) {
if err := r.validate(req); err != nil {
spew.Dump("ERR", err)
return
}
var (
ctx = context.Background()
scope = scp{
req: req,
writer: w,
}
)
sess := wfexec.NewSession(context.Background(), r.graph, wfexec.SetLogger(logger.Default()), wfexec.SetHandler(func(ss wfexec.SessionStatus, s1 *wfexec.State, s2 *wfexec.Session) {
// spew.Dump("event handler here!", ss)
}))
scope := &expr.Vars{}
scope.Set("envelope", envelope{
Request: req,
Writer: w,
})
if len(r.steps) == 0 {
// dont serve, do what? return default response?
return
}
err := sess.Exec(context.Background(), r.steps[0], scope)
// if err != nil {
// fmt.Fprintf(w, "no go, err on exec: %s", err)
// return
// }
err = sess.Wait(context.Background())
err := r.pipe.Exec(ctx, &scope)
if err != nil {
// log error
}
}

View File

@@ -1,40 +0,0 @@
package apigw
import (
"context"
"errors"
"github.com/cortezaproject/corteza-server/pkg/expr"
"github.com/cortezaproject/corteza-server/pkg/wfexec"
"github.com/davecgh/go-spew/spew"
)
type (
contentLengthValidatorArgs struct {
Length int
}
)
func contentLengthValidator(c context.Context, params *expr.Vars) wfHandler {
var (
clv = contentLengthValidatorArgs{}
)
return func(c context.Context, er *wfexec.ExecRequest) (r wfexec.ExecResponse, err error) {
params.Decode(&clv)
spew.Dump("body size validator fn()", clv)
e := er.Scope.GetValue()["envelope"]
ee := e.Get().(envelope)
cl := ee.Request.ContentLength
if clv.Length < int(cl) {
err = errors.New("content length overriden")
return
}
r = &expr.Vars{}
return
}
}

157
pkg/apigw/verifier.go Normal file
View File

@@ -0,0 +1,157 @@
package apigw
import (
"context"
"fmt"
"github.com/cortezaproject/corteza-server/pkg/expr"
"github.com/cortezaproject/corteza-server/system/types"
"github.com/davecgh/go-spew/spew"
)
type (
verifierQueryParam struct{}
verifierOrigin struct{}
)
func (h verifierQueryParam) Meta(f *types.Function) functionMeta {
return functionMeta{
Step: 0,
Name: "verifierQueryParam",
Label: "Query parameters verifier",
Kind: "verifier",
Weight: int(f.Weight),
Params: f.Params,
Args: []*functionMetaArg{
{
Type: "expr",
Label: "expr",
Options: map[string]interface{}{},
},
},
}
}
func (h verifierOrigin) Meta(f *types.Function) functionMeta {
return functionMeta{
Step: 0,
Name: "verifierOrigin",
Label: "Origin verifier",
Kind: "verifier",
Weight: int(f.Weight),
Params: f.Params,
Args: []*functionMetaArg{
{
Type: "expr",
Label: "expr",
Options: map[string]interface{}{},
},
},
}
}
func (h verifierQueryParam) Handler() handlerFunc {
return func(ctx context.Context, scope *scp, params map[string]interface{}, ff functionHandler) error {
for k := range ff.params {
v, ok := params[k]
if !ok {
spew.Dump("not in params", k)
continue
}
vv := map[string]interface{}{}
vals := scope.req.URL.Query()
for k, v := range vals {
vv[k] = v[0]
}
// get the request data and put it into vars
out, err := expr.NewVars(vv)
if err != nil {
// spew.Dump("ERR!", err)
return err
}
pp := expr.NewParser()
tt, err := pp.Parse(v.(string))
if err != nil {
// spew.Dump("ERR!", err)
return err
}
b, err := tt.Test(ctx, out)
if err != nil {
// spew.Dump("ERR!", err)
return err
}
spew.Dump("BBBB", b)
if !b {
return fmt.Errorf("failed on step %d, function %s", ff.step, ff.name)
}
}
// testing
scope.req.Header.Add(fmt.Sprintf("step_%d", ff.step), ff.name)
return nil
}
}
func (h verifierOrigin) Handler() handlerFunc {
return func(ctx context.Context, scope *scp, params map[string]interface{}, ff functionHandler) error {
for k := range ff.params {
v, ok := params[k]
if !ok {
spew.Dump("not in params", k)
continue
}
vv := map[string]interface{}{
"origin": scope.req.Header.Get("Origin"),
}
// get the request data and put it into vars
out, err := expr.NewVars(vv)
if err != nil {
spew.Dump("ERR!", err)
return err
}
pp := expr.NewParser()
tt, err := pp.Parse(v.(string))
if err != nil {
spew.Dump("ERR!", err)
return err
}
b, err := tt.Test(ctx, out)
if err != nil {
spew.Dump("ERR!", err)
return err
}
spew.Dump("BBBB", b)
if !b {
return fmt.Errorf("failed on step %d, function %s", ff.step, ff.name)
}
}
// testing
scope.req.Header.Add(fmt.Sprintf("step_%d", ff.step), ff.name)
return nil
}
}