ref 0: first working version ; totest

This commit is contained in:
Adrien Marquès 2019-05-01 15:14:49 +02:00
parent 7e66b6ddd5
commit cd2bcdd8bc
8 changed files with 57 additions and 39 deletions

View File

@ -48,11 +48,11 @@ var (
// ErrorUncallableService is set when there the requested controller's // ErrorUncallableService is set when there the requested controller's
// implementation (plugin file) is not found/callable // implementation (plugin file) is not found/callable
// ErrorUncallableService = func() Error { return Error{202, "uncallable service", nil} } ErrorUncallableService = func() Error { return Error{202, "uncallable service", nil} }
// ErrorUncallableMethod is set when there the requested controller's // ErrorUncallableMethod is set when there the requested controller's
// implementation does not features the requested method // implementation does not features the requested method
// ErrorUncallableMethod = func() Error { return Error{203, "uncallable method", nil} } ErrorUncallableMethod = func() Error { return Error{203, "uncallable method", nil} }
// ErrorPermission is set when there is a permission error by default // ErrorPermission is set when there is a permission error by default
// the api returns a permission error when the current scope (built // the api returns a permission error when the current scope (built

View File

@ -8,9 +8,9 @@ import (
// These are used by the controllers to set the *execution status* // These are used by the controllers to set the *execution status*
// directly into the response as JSON alongside response output fields. // directly into the response as JSON alongside response output fields.
type Error struct { type Error struct {
Code int `json:"error"` Code int `json:"code"`
Reason string `json:"reason"` Reason string `json:"reason"`
Arguments []interface{} `json:"error_args"` Arguments []interface{} `json:"arguments"`
} }
// Put adds an argument to the error // Put adds an argument to the error

View File

@ -35,13 +35,16 @@ func (i *Response) GetData(name string) interface{} {
return value return value
} }
type jsonResponse struct {
Error
ResponseData
}
// MarshalJSON implements the 'json.Marshaler' interface and is used // MarshalJSON implements the 'json.Marshaler' interface and is used
// to generate the JSON representation of the response // to generate the JSON representation of the response
func (i *Response) MarshalJSON() ([]byte, error) { func (i *Response) MarshalJSON() ([]byte, error) {
return json.Marshal(jsonResponse{i.Err, i.Data}) fmt := make(map[string]interface{})
for k, v := range i.Data {
fmt[k] = v
}
fmt["error"] = i.Err
return json.Marshal(fmt)
} }

View File

@ -44,30 +44,35 @@ type Store struct {
} }
// New creates a new store from an http request. // New creates a new store from an http request.
func New(req *http.Request) *Store { // URI params is required because it only takes into account after service path
// we do not know in this scope.
func New(uriParams []string, req *http.Request) *Store {
ds := &Store{ ds := &Store{
URI: make([]*Parameter, 0), URI: make([]*Parameter, 0),
Get: make(map[string]*Parameter), Get: make(map[string]*Parameter),
Form: make(map[string]*Parameter), Form: make(map[string]*Parameter),
Set: make(map[string]*Parameter), Set: make(map[string]*Parameter),
} }
// 1. GET (query) data
// 1. set URI parameters
ds.setURIParams(uriParams)
// 2. GET (query) data
ds.fetchGet(req) ds.fetchGet(req)
// 2. We are done if GET method // 3. We are done if GET method
if req.Method == http.MethodGet { if req.Method == http.MethodGet {
return ds return ds
} }
// 2. POST (body) data // 4. POST (body) data
ds.fetchForm(req) ds.fetchForm(req)
return ds return ds
} }
// SetURIParameters stores URL orderedURIParams and fills 'Set' // setURIParameters fills 'Set' with creating pointers inside 'Url'
// with creating pointers inside 'Url' func (i *Store) setURIParams(orderedUParams []string) {
func (i *Store) SetURIParameters(orderedUParams []string) {
for index, value := range orderedUParams { for index, value := range orderedUParams {

View File

@ -16,7 +16,7 @@ import (
// Server represents an AICRA instance featuring: type checkers, services // Server represents an AICRA instance featuring: type checkers, services
type Server struct { type Server struct {
services *config.Service services *config.Service
checkers *checker.Set Checkers *checker.Set
handlers []*api.Handler handlers []*api.Handler
} }
@ -28,7 +28,7 @@ func New(configPath string) (*Server, error) {
// 1. init instance // 1. init instance
var i = &Server{ var i = &Server{
services: nil, services: nil,
checkers: checker.New(), Checkers: checker.New(),
handlers: make([]*api.Handler, 0), handlers: make([]*api.Handler, 0),
} }
@ -81,7 +81,7 @@ func (s *Server) ServeHTTP(res http.ResponseWriter, req *http.Request) {
} }
// 4. parse every input data from the request // 4. parse every input data from the request
store := reqdata.New(req) store := reqdata.New(apiRequest.URI[pathIndex:], req)
/* (4) Check parameters /* (4) Check parameters
---------------------------------------------------------*/ ---------------------------------------------------------*/
@ -112,10 +112,10 @@ func (s *Server) ServeHTTP(res http.ResponseWriter, req *http.Request) {
// fail if found no handler // fail if found no handler
if serviceHandler == nil { if serviceHandler == nil {
if serviceFound { if serviceFound {
httpError(res, api.ErrorUnknownMethod()) httpError(res, api.ErrorUncallableMethod())
return return
} }
httpError(res, api.ErrorUnknownService()) httpError(res, api.ErrorUncallableService())
return return
} }

View File

@ -1,6 +1,11 @@
package builtin package builtin
import "git.xdrm.io/go/aicra/typecheck" import (
"log"
"strconv"
"git.xdrm.io/go/aicra/typecheck"
)
// Float64 checks if a value is a float64 // Float64 checks if a value is a float64
type Float64 struct{} type Float64 struct{}
@ -17,7 +22,24 @@ func (Float64) Checker(typeName string) typecheck.Checker {
return nil return nil
} }
return func(value interface{}) bool { return func(value interface{}) bool {
_, isFloat64 := value.(bool) strVal, isString := value.(string)
return isFloat64 _, isFloat64 := value.(float64)
log.Printf("1")
// raw float
if isFloat64 {
return true
}
// string float
if !isString {
return false
}
_, err := strconv.ParseFloat(strVal, 64)
if err != nil {
return false
}
return true
} }
} }

View File

@ -7,7 +7,7 @@ import (
"git.xdrm.io/go/aicra/typecheck" "git.xdrm.io/go/aicra/typecheck"
) )
var fixedLengthRegex = regexp.MustCompile(`^string\((\d+))$`) var fixedLengthRegex = regexp.MustCompile(`^string\((\d+)\)$`)
var variableLengthRegex = regexp.MustCompile(`^string\((\d+), ?(\d+)\)$`) var variableLengthRegex = regexp.MustCompile(`^string\((\d+), ?(\d+)\)$`)
// String checks if a value is a string // String checks if a value is a string

14
util.go
View File

@ -4,24 +4,12 @@ import (
"encoding/json" "encoding/json"
"log" "log"
"net/http" "net/http"
"strings"
"git.xdrm.io/go/aicra/api" "git.xdrm.io/go/aicra/api"
"git.xdrm.io/go/aicra/internal/config" "git.xdrm.io/go/aicra/internal/config"
"git.xdrm.io/go/aicra/internal/reqdata" "git.xdrm.io/go/aicra/internal/reqdata"
) )
func (s *Server) findServiceDef(req *api.Request) (serviceDef *config.Service, servicePath string) {
// 1. try to find definition
serviceDef, pathi := s.services.Browse(req.URI)
// 2. set service uri
servicePath = strings.Join(req.URI[:pathi], "/")
return
}
// extractParameters extracts parameters for the request and checks // extractParameters extracts parameters for the request and checks
// every single one according to configuration options // every single one according to configuration options
func (s *Server) extractParameters(store *reqdata.Store, methodParam map[string]*config.Parameter) (map[string]interface{}, api.Error) { func (s *Server) extractParameters(store *reqdata.Store, methodParam map[string]*config.Parameter) (map[string]interface{}, api.Error) {
@ -80,7 +68,7 @@ func (s *Server) extractParameters(store *reqdata.Store, methodParam map[string]
} }
/* (7) Check type */ /* (7) Check type */
if s.checkers.Run(param.Type, p.Value) != nil { if s.Checkers.Run(param.Type, p.Value) != nil {
apiError = api.ErrorInvalidParam() apiError = api.ErrorInvalidParam()
apiError.Put(param.Rename) apiError.Put(param.Rename)