new configuration format (more explicit + cleaner)

This commit is contained in:
Adrien Marquès 2018-06-03 15:08:47 +02:00
parent aef8d74bb9
commit 43779b8644
3 changed files with 42 additions and 88 deletions

View File

@ -42,9 +42,6 @@ func Load(path string) (*Controller, error) {
return nil, err return nil, err
} }
/* (5) Set default optional fields */
receiver.setDefaults()
return receiver, nil return receiver, nil
} }
@ -148,9 +145,8 @@ func (c *Controller) format(controllerName string) error {
/* check parameters */ /* check parameters */
for pName, pData := range method.Ptr.Parameters { for pName, pData := range method.Ptr.Parameters {
/* (4) Fail on invalid rename (set but empty) */ if len(pData.Rename) < 1 {
if pData.Rename != nil && len(*pData.Rename) < 1 { pData.Rename = pName
return fmt.Errorf("Empty rename for %s.%s parameter '%s'", controllerName, method.Name, pName)
} }
/* (5) Check for name/rename conflict */ /* (5) Check for name/rename conflict */
@ -162,31 +158,43 @@ func (c *Controller) format(controllerName string) error {
} }
// 1. Same rename field // 1. Same rename field
if pData.Rename != nil && param.Rename != nil && *pData.Rename == *param.Rename { if pData.Rename == param.Rename {
return fmt.Errorf("Rename conflict for %s.%s parameter '%s'", controllerName, method.Name, *pData.Rename) return fmt.Errorf("Rename conflict for %s.%s parameter '%s'", controllerName, method.Name, pData.Rename)
} }
// 2. Not-renamed field matches a renamed field // 2. Not-renamed field matches a renamed field
if pData.Rename == nil && param.Rename != nil && pName == *param.Rename { if pName == param.Rename {
return fmt.Errorf("Name conflict for %s.%s parameter '%s'", controllerName, method.Name, pName) return fmt.Errorf("Name conflict for %s.%s parameter '%s'", controllerName, method.Name, pName)
} }
// 3. Renamed field matches name // 3. Renamed field matches name
if pData.Rename != nil && param.Rename == nil && *pData.Rename == paramName { if pData.Rename == paramName {
return fmt.Errorf("Name conflict for %s.%s parameter '%s'", controllerName, method.Name, pName) return fmt.Errorf("Name conflict for %s.%s parameter '%s'", controllerName, method.Name, pName)
} }
} }
/* (6) Fail on missing description */ /* (6) Manage invalid type */
if len(pData.Type) < 1 {
return fmt.Errorf("Invalid type for %s.%s parameter '%s'", controllerName, method.Name, pName)
}
/* (7) Fail on missing description */
if len(pData.Description) < 1 { if len(pData.Description) < 1 {
return fmt.Errorf("Missing description for %s.%s parameter '%s'", controllerName, method.Name, pName) return fmt.Errorf("Missing description for %s.%s parameter '%s'", controllerName, method.Name, pName)
} }
/* (7) Fail on missing type */ /* (8) Fail on missing type */
if len(pData.Type) < 1 { if len(pData.Type) < 1 {
return fmt.Errorf("Missing type for %s.%s parameter '%s'", controllerName, method.Name, pName) return fmt.Errorf("Missing type for %s.%s parameter '%s'", controllerName, method.Name, pName)
} }
/* (9) Set optional + type */
if pData.Type[0] == '?' {
pData.Optional = true
pData.Type = pData.Type[1:]
}
} }
} }
@ -217,54 +225,3 @@ func (c *Controller) format(controllerName string) error {
return nil return nil
} }
// setDefaults sets the defaults for optional configuration fields
func (c *Controller) setDefaults() {
/* (1) Get methods */
methods := []*Method{
c.GET,
c.POST,
c.PUT,
c.DELETE,
}
/* (2) Browse methods */
for _, m := range methods {
// ignore if not set
if m == nil {
continue
}
/* (3) Browse parameters */
for name, param := range m.Parameters {
// 1. Default 'opt': required //
if param.Optional == nil {
param.Optional = new(bool)
}
// 2. Default 'rename': same as name
if param.Rename == nil {
param.Rename = new(string)
*param.Rename = name
}
}
}
/* (4) Stop here if no children */
if c.Children == nil || len(c.Children) < 1 {
return
}
/* (5) Iterate over children */
for _, child := range c.Children {
child.setDefaults()
}
return
}

View File

@ -4,17 +4,17 @@ package config
---------------------------------------------------------*/ ---------------------------------------------------------*/
type Parameter struct { type Parameter struct {
Description string `json:"des"` Description string `json:"info"`
Type string `json:"typ"` Type string `json:"type"`
Rename *string `json:"ren"` Rename string `json:"name,omitempty"`
Optional *bool `json:"opt"` Optional bool
Default *interface{} `json:"def"` Default *interface{} `json:"default"`
} }
type Method struct { type Method struct {
Description string `json:"des"` Description string `json:"info"`
Permission [][]string `json:"per"` Permission [][]string `json:"scope"`
Parameters map[string]*Parameter `json:"par"` Parameters map[string]*Parameter `json:"in"`
Options map[string]interface{} `json:"opt"` Download *bool `json:"download"`
} }
type Controller struct { type Controller struct {

View File

@ -41,20 +41,17 @@ func (s *Server) route(res http.ResponseWriter, httpReq *http.Request) {
parameters := make(map[string]interface{}) parameters := make(map[string]interface{})
for name, param := range method.Parameters { for name, param := range method.Parameters {
/* (1) Rename */ /* (1) Extract value */
rename := *param.Rename
/* (2) Extract value */
p, isset := req.Data.Set[name] p, isset := req.Data.Set[name]
/* (3) Required & missing */ /* (2) Required & missing */
if !isset && !*param.Optional { if !isset && !param.Optional {
paramError = err.MissingParam paramError = err.MissingParam
paramError.BindArgument(name) paramError.BindArgument(name)
break break
} }
/* (4) Optional & missing: set default value */ /* (3) Optional & missing: set default value */
if !isset { if !isset {
p = &request.Parameter{ p = &request.Parameter{
Parsed: true, Parsed: true,
@ -66,42 +63,42 @@ func (s *Server) route(res http.ResponseWriter, httpReq *http.Request) {
} }
// we are done // we are done
parameters[rename] = p.Value parameters[param.Rename] = p.Value
continue continue
} }
/* (5) Parse parameter if not file */ /* (4) Parse parameter if not file */
if !p.File { if !p.File {
p.Parse() p.Parse()
} }
/* (6) Fail on unexpected multipart file */ /* (5) Fail on unexpected multipart file */
waitFile, gotFile := param.Type == "FILE", p.File waitFile, gotFile := param.Type == "FILE", p.File
if gotFile && !waitFile || !gotFile && waitFile { if gotFile && !waitFile || !gotFile && waitFile {
paramError = err.InvalidParam paramError = err.InvalidParam
paramError.BindArgument(rename) paramError.BindArgument(param.Rename)
paramError.BindArgument("FILE") paramError.BindArgument("FILE")
break break
} }
/* (7) Do not check if file */ /* (6) Do not check if file */
if gotFile { if gotFile {
parameters[rename] = p.Value parameters[param.Rename] = p.Value
continue continue
} }
/* (8) Check type */ /* (7) Check type */
if s.Checker.Run(param.Type, p.Value) != nil { if s.Checker.Run(param.Type, p.Value) != nil {
paramError = err.InvalidParam paramError = err.InvalidParam
paramError.BindArgument(rename) paramError.BindArgument(param.Rename)
paramError.BindArgument(param.Type) paramError.BindArgument(param.Type)
paramError.BindArgument(p.Value) paramError.BindArgument(p.Value)
break break
} }
parameters[rename] = p.Value parameters[param.Rename] = p.Value
} }