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
// 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
// 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
// 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*
// directly into the response as JSON alongside response output fields.
type Error struct {
Code int `json:"error"`
Code int `json:"code"`
Reason string `json:"reason"`
Arguments []interface{} `json:"error_args"`
Arguments []interface{} `json:"arguments"`
}
// Put adds an argument to the error

View File

@ -35,13 +35,16 @@ func (i *Response) GetData(name string) interface{} {
return value
}
type jsonResponse struct {
Error
ResponseData
}
// MarshalJSON implements the 'json.Marshaler' interface and is used
// to generate the JSON representation of the response
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.
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{
URI: make([]*Parameter, 0),
Get: make(map[string]*Parameter),
Form: 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)
// 2. We are done if GET method
// 3. We are done if GET method
if req.Method == http.MethodGet {
return ds
}
// 2. POST (body) data
// 4. POST (body) data
ds.fetchForm(req)
return ds
}
// SetURIParameters stores URL orderedURIParams and fills 'Set'
// with creating pointers inside 'Url'
func (i *Store) SetURIParameters(orderedUParams []string) {
// setURIParameters fills 'Set' with creating pointers inside 'Url'
func (i *Store) setURIParams(orderedUParams []string) {
for index, value := range orderedUParams {

View File

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

View File

@ -1,6 +1,11 @@
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
type Float64 struct{}
@ -17,7 +22,24 @@ func (Float64) Checker(typeName string) typecheck.Checker {
return nil
}
return func(value interface{}) bool {
_, isFloat64 := value.(bool)
return isFloat64
strVal, isString := value.(string)
_, 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"
)
var fixedLengthRegex = regexp.MustCompile(`^string\((\d+))$`)
var fixedLengthRegex = regexp.MustCompile(`^string\((\d+)\)$`)
var variableLengthRegex = regexp.MustCompile(`^string\((\d+), ?(\d+)\)$`)
// String checks if a value is a string

14
util.go
View File

@ -4,24 +4,12 @@ import (
"encoding/json"
"log"
"net/http"
"strings"
"git.xdrm.io/go/aicra/api"
"git.xdrm.io/go/aicra/internal/config"
"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
// every single one according to configuration options
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 */
if s.checkers.Run(param.Type, p.Value) != nil {
if s.Checkers.Run(param.Type, p.Value) != nil {
apiError = api.ErrorInvalidParam()
apiError.Put(param.Rename)