moved 'err' into package
This commit is contained in:
parent
84d14dfd50
commit
f0727cb9ca
|
@ -0,0 +1,34 @@
|
||||||
|
package err
|
||||||
|
|
||||||
|
var (
|
||||||
|
/* Base */
|
||||||
|
Success = Error{0, "all right", nil}
|
||||||
|
Failure = Error{1, "it failed", nil}
|
||||||
|
Unknown = Error{-1, "", nil}
|
||||||
|
|
||||||
|
NoMatchFound = Error{2, "no resource found", nil}
|
||||||
|
AlreadyExists = Error{3, "resource already exists", nil}
|
||||||
|
|
||||||
|
Config = Error{4, "configuration error", nil}
|
||||||
|
|
||||||
|
/* I/O */
|
||||||
|
Upload = Error{100, "upload failed", nil}
|
||||||
|
Download = Error{101, "download failed", nil}
|
||||||
|
MissingDownloadHeaders = Error{102, "download headers are missing", nil}
|
||||||
|
MissingDownloadBody = Error{103, "download body is missing", nil}
|
||||||
|
|
||||||
|
/* Controllers */
|
||||||
|
UnknownController = Error{200, "unknown controller", nil}
|
||||||
|
UnknownMethod = Error{201, "unknown method", nil}
|
||||||
|
UncallableController = Error{202, "uncallable controller", nil}
|
||||||
|
UncallableMethod = Error{203, "uncallable method", nil}
|
||||||
|
|
||||||
|
/* Permissions */
|
||||||
|
Permission = Error{300, "permission error", nil}
|
||||||
|
Token = Error{301, "token error", nil}
|
||||||
|
|
||||||
|
/* Check */
|
||||||
|
MissingParam = Error{400, "missing parameter", nil}
|
||||||
|
InvalidParam = Error{401, "invalid parameter", nil}
|
||||||
|
InvalidDefaultParam = Error{402, "invalid default param", nil}
|
||||||
|
)
|
|
@ -0,0 +1,52 @@
|
||||||
|
package err
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Error struct {
|
||||||
|
Code int
|
||||||
|
Reason string
|
||||||
|
Arguments []interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BindArgument adds an argument to the error
|
||||||
|
// to be displayed back to API caller
|
||||||
|
func (e *Error) BindArgument(arg interface{}) {
|
||||||
|
|
||||||
|
/* (1) Make slice if not */
|
||||||
|
if e.Arguments == nil {
|
||||||
|
e.Arguments = make([]interface{}, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (2) Append argument */
|
||||||
|
e.Arguments = append(e.Arguments, arg)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implements 'error'
|
||||||
|
func (e Error) Error() string {
|
||||||
|
|
||||||
|
return fmt.Sprintf("[%d] %s", e.Code, e.Reason)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implements json.Marshaler
|
||||||
|
func (e Error) MarshalJSON() ([]byte, error) {
|
||||||
|
|
||||||
|
var json_arguments string
|
||||||
|
|
||||||
|
/* (1) Marshal 'Arguments' if set */
|
||||||
|
if e.Arguments != nil && len(e.Arguments) > 0 {
|
||||||
|
arg_representation, err := json.Marshal(e.Arguments)
|
||||||
|
if err == nil {
|
||||||
|
json_arguments = fmt.Sprintf(",\"arguments\":%s", arg_representation)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (2) Render JSON manually */
|
||||||
|
return []byte(fmt.Sprintf("{\"error\":%d,\"reason\":\"%s\"%s}", e.Code, e.Reason, json_arguments)), nil
|
||||||
|
|
||||||
|
}
|
85
errors.go
85
errors.go
|
@ -1,85 +0,0 @@
|
||||||
package gfw
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Err struct {
|
|
||||||
Code int
|
|
||||||
Reason string
|
|
||||||
Arguments []interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
/* Base */
|
|
||||||
ErrSuccess = Err{0, "all right", nil}
|
|
||||||
ErrFailure = Err{1, "it failed", nil}
|
|
||||||
ErrUnknown = Err{-1, "", nil}
|
|
||||||
|
|
||||||
ErrNoMatchFound = Err{2, "no resource found", nil}
|
|
||||||
ErrAlreadyExists = Err{3, "resource already exists", nil}
|
|
||||||
|
|
||||||
ErrConfig = Err{4, "configuration error", nil}
|
|
||||||
|
|
||||||
/* I/O */
|
|
||||||
ErrUpload = Err{100, "upload failed", nil}
|
|
||||||
ErrDownload = Err{101, "download failed", nil}
|
|
||||||
ErrMissingDownloadHeaders = Err{102, "download headers are missing", nil}
|
|
||||||
ErrMissingDownloadBody = Err{103, "download body is missing", nil}
|
|
||||||
|
|
||||||
/* Controllers */
|
|
||||||
ErrUnknownController = Err{200, "unknown controller", nil}
|
|
||||||
ErrUnknownMethod = Err{201, "unknown method", nil}
|
|
||||||
ErrUncallableController = Err{202, "uncallable controller", nil}
|
|
||||||
ErrUncallableMethod = Err{203, "uncallable method", nil}
|
|
||||||
|
|
||||||
/* Permissions */
|
|
||||||
ErrPermission = Err{300, "permission error", nil}
|
|
||||||
ErrToken = Err{301, "token error", nil}
|
|
||||||
|
|
||||||
/* Check */
|
|
||||||
ErrMissingParam = Err{400, "missing parameter", nil}
|
|
||||||
ErrInvalidParam = Err{401, "invalid parameter", nil}
|
|
||||||
ErrInvalidDefaultParam = Err{402, "invalid default param", nil}
|
|
||||||
)
|
|
||||||
|
|
||||||
// BindArgument adds an argument to the error
|
|
||||||
// to be displayed back to API caller
|
|
||||||
func (e *Err) BindArgument(arg interface{}) {
|
|
||||||
|
|
||||||
/* (1) Make slice if not */
|
|
||||||
if e.Arguments == nil {
|
|
||||||
e.Arguments = make([]interface{}, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (2) Append argument */
|
|
||||||
e.Arguments = append(e.Arguments, arg)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Implements 'error'
|
|
||||||
func (e Err) Error() string {
|
|
||||||
|
|
||||||
return fmt.Sprintf("[%d] %s", e.Code, e.Reason)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Implements json.Marshaler
|
|
||||||
func (e Err) MarshalJSON() ([]byte, error) {
|
|
||||||
|
|
||||||
var json_arguments string
|
|
||||||
|
|
||||||
/* (1) Marshal 'Arguments' if set */
|
|
||||||
if e.Arguments != nil && len(e.Arguments) > 0 {
|
|
||||||
arg_representation, err := json.Marshal(e.Arguments)
|
|
||||||
if err == nil {
|
|
||||||
json_arguments = fmt.Sprintf(",\"arguments\":%s", arg_representation)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (2) Render JSON manually */
|
|
||||||
return []byte(fmt.Sprintf("{\"error\":%d,\"reason\":\"%s\"%s}", e.Code, e.Reason, json_arguments)), nil
|
|
||||||
|
|
||||||
}
|
|
|
@ -3,6 +3,7 @@ package gfw
|
||||||
import (
|
import (
|
||||||
"git.xdrm.io/xdrm-brackets/gfw/checker"
|
"git.xdrm.io/xdrm-brackets/gfw/checker"
|
||||||
"git.xdrm.io/xdrm-brackets/gfw/config"
|
"git.xdrm.io/xdrm-brackets/gfw/config"
|
||||||
|
"git.xdrm.io/xdrm-brackets/gfw/err"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Init initilises a new framework instance
|
// Init initilises a new framework instance
|
||||||
|
@ -18,7 +19,7 @@ func Init(path string, typeChecker *checker.TypeRegistry) (*Server, error) {
|
||||||
inst := &Server{
|
inst := &Server{
|
||||||
config: nil,
|
config: nil,
|
||||||
Params: make(map[string]interface{}),
|
Params: make(map[string]interface{}),
|
||||||
err: ErrSuccess,
|
err: err.Success,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (2) Load configuration */
|
/* (2) Load configuration */
|
||||||
|
|
|
@ -3,8 +3,10 @@ package gfw
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"git.xdrm.io/xdrm-brackets/gfw/err"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"plugin"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
@ -189,3 +191,40 @@ func parseHttpData(data interface{}) interface{} {
|
||||||
return dvalue
|
return dvalue
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// loadController tries to load a controller from its uri
|
||||||
|
// checks for its given method ('Get', 'Post', 'Put', or 'Delete')
|
||||||
|
func (i *Request) loadController(method string) (func(map[string]interface{}) (map[string]interface{}, err.Error), error) {
|
||||||
|
|
||||||
|
/* (1) Build controller path */
|
||||||
|
path := fmt.Sprintf("%si.so", i.ControllerUri)
|
||||||
|
|
||||||
|
/* (2) Format url */
|
||||||
|
tmp := []byte(strings.ToLower(method))
|
||||||
|
tmp[0] = tmp[0] - ('a' - 'A')
|
||||||
|
method = string(tmp)
|
||||||
|
|
||||||
|
fmt.Printf("method is '%s'\n", method)
|
||||||
|
return nil, nil
|
||||||
|
|
||||||
|
/* (2) Try to load plugin */
|
||||||
|
p, err2 := plugin.Open(path)
|
||||||
|
if err2 != nil {
|
||||||
|
return nil, err2
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (3) Try to extract method */
|
||||||
|
m, err2 := p.Lookup(method)
|
||||||
|
if err2 != nil {
|
||||||
|
return nil, err2
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (4) Check signature */
|
||||||
|
callable, validSignature := m.(func(map[string]interface{}) (map[string]interface{}, err.Error))
|
||||||
|
if !validSignature {
|
||||||
|
return nil, fmt.Errorf("Invalid signature for method %s", method)
|
||||||
|
}
|
||||||
|
|
||||||
|
return callable, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -9,15 +9,15 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// buildRequestDataFromRequest builds a 'RequestData'
|
// buildRequestDataFromRequest builds a 'requestData'
|
||||||
// from an http request
|
// from an http request
|
||||||
func buildRequestDataFromRequest(req *http.Request) *RequestData {
|
func buildRequestDataFromRequest(req *http.Request) *requestData {
|
||||||
|
|
||||||
i := &RequestData{
|
i := &requestData{
|
||||||
Url: make([]*RequestParameter, 0),
|
Url: make([]*requestParameter, 0),
|
||||||
Get: make(map[string]*RequestParameter),
|
Get: make(map[string]*requestParameter),
|
||||||
Form: make(map[string]*RequestParameter),
|
Form: make(map[string]*requestParameter),
|
||||||
Set: make(map[string]*RequestParameter),
|
Set: make(map[string]*requestParameter),
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET (query) data
|
// GET (query) data
|
||||||
|
@ -37,7 +37,7 @@ func buildRequestDataFromRequest(req *http.Request) *RequestData {
|
||||||
|
|
||||||
// bindUrl stores URL data and fills 'Set'
|
// bindUrl stores URL data and fills 'Set'
|
||||||
// with creating pointers inside 'Url'
|
// with creating pointers inside 'Url'
|
||||||
func (i *RequestData) fillUrl(data []string) {
|
func (i *requestData) fillUrl(data []string) {
|
||||||
|
|
||||||
for index, value := range data {
|
for index, value := range data {
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ func (i *RequestData) fillUrl(data []string) {
|
||||||
setindex := fmt.Sprintf("URL#%d", index)
|
setindex := fmt.Sprintf("URL#%d", index)
|
||||||
|
|
||||||
// store value in 'Set'
|
// store value in 'Set'
|
||||||
i.Set[setindex] = &RequestParameter{
|
i.Set[setindex] = &requestParameter{
|
||||||
Parsed: false,
|
Parsed: false,
|
||||||
Value: value,
|
Value: value,
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ func (i *RequestData) fillUrl(data []string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// fetchGet stores data from the QUERY (in url parameters)
|
// fetchGet stores data from the QUERY (in url parameters)
|
||||||
func (i *RequestData) fetchGet(req *http.Request) {
|
func (i *requestData) fetchGet(req *http.Request) {
|
||||||
|
|
||||||
for name, value := range req.URL.Query() {
|
for name, value := range req.URL.Query() {
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ func (i *RequestData) fetchGet(req *http.Request) {
|
||||||
setindex := fmt.Sprintf("GET@%s", name)
|
setindex := fmt.Sprintf("GET@%s", name)
|
||||||
|
|
||||||
// store value in 'Set'
|
// store value in 'Set'
|
||||||
i.Set[setindex] = &RequestParameter{
|
i.Set[setindex] = &requestParameter{
|
||||||
Parsed: false,
|
Parsed: false,
|
||||||
Value: value,
|
Value: value,
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,7 @@ func (i *RequestData) fetchGet(req *http.Request) {
|
||||||
// - parse 'form-data' if not supported (not POST requests)
|
// - parse 'form-data' if not supported (not POST requests)
|
||||||
// - parse 'x-www-form-urlencoded'
|
// - parse 'x-www-form-urlencoded'
|
||||||
// - parse 'application/json'
|
// - parse 'application/json'
|
||||||
func (i *RequestData) fetchForm(req *http.Request) {
|
func (i *requestData) fetchForm(req *http.Request) {
|
||||||
|
|
||||||
contentType := req.Header.Get("Content-Type")
|
contentType := req.Header.Get("Content-Type")
|
||||||
|
|
||||||
|
@ -116,7 +116,7 @@ func (i *RequestData) fetchForm(req *http.Request) {
|
||||||
|
|
||||||
// parseJsonForm parses JSON from the request body inside 'Form'
|
// parseJsonForm parses JSON from the request body inside 'Form'
|
||||||
// and 'Set'
|
// and 'Set'
|
||||||
func (i *RequestData) parseJsonForm(req *http.Request) {
|
func (i *requestData) parseJsonForm(req *http.Request) {
|
||||||
|
|
||||||
parsed := make(map[string]interface{}, 0)
|
parsed := make(map[string]interface{}, 0)
|
||||||
|
|
||||||
|
@ -137,7 +137,7 @@ func (i *RequestData) parseJsonForm(req *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// store value in 'Set'
|
// store value in 'Set'
|
||||||
i.Set[name] = &RequestParameter{
|
i.Set[name] = &requestParameter{
|
||||||
Parsed: true,
|
Parsed: true,
|
||||||
Value: value,
|
Value: value,
|
||||||
}
|
}
|
||||||
|
@ -151,7 +151,7 @@ func (i *RequestData) parseJsonForm(req *http.Request) {
|
||||||
|
|
||||||
// parseUrlencodedForm parses urlencoded from the request body inside 'Form'
|
// parseUrlencodedForm parses urlencoded from the request body inside 'Form'
|
||||||
// and 'Set'
|
// and 'Set'
|
||||||
func (i *RequestData) parseUrlencodedForm(req *http.Request) {
|
func (i *requestData) parseUrlencodedForm(req *http.Request) {
|
||||||
|
|
||||||
// use http.Request interface
|
// use http.Request interface
|
||||||
req.ParseForm()
|
req.ParseForm()
|
||||||
|
@ -165,7 +165,7 @@ func (i *RequestData) parseUrlencodedForm(req *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// store value in 'Set'
|
// store value in 'Set'
|
||||||
i.Set[name] = &RequestParameter{
|
i.Set[name] = &requestParameter{
|
||||||
Parsed: false,
|
Parsed: false,
|
||||||
Value: value,
|
Value: value,
|
||||||
}
|
}
|
||||||
|
@ -178,7 +178,7 @@ func (i *RequestData) parseUrlencodedForm(req *http.Request) {
|
||||||
|
|
||||||
// parseMultipartForm parses multi-part from the request body inside 'Form'
|
// parseMultipartForm parses multi-part from the request body inside 'Form'
|
||||||
// and 'Set'
|
// and 'Set'
|
||||||
func (i *RequestData) parseMultipartForm(req *http.Request) {
|
func (i *requestData) parseMultipartForm(req *http.Request) {
|
||||||
|
|
||||||
/* (1) Create reader */
|
/* (1) Create reader */
|
||||||
mpr := multipart.CreateReader(req)
|
mpr := multipart.CreateReader(req)
|
||||||
|
@ -196,7 +196,7 @@ func (i *RequestData) parseMultipartForm(req *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// store value in 'Set'
|
// store value in 'Set'
|
||||||
i.Set[name] = &RequestParameter{
|
i.Set[name] = &requestParameter{
|
||||||
Parsed: false,
|
Parsed: false,
|
||||||
File: component.File,
|
File: component.File,
|
||||||
Value: component.Data,
|
Value: component.Data,
|
||||||
|
|
123
router.go
123
router.go
|
@ -3,6 +3,7 @@ package gfw
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"git.xdrm.io/xdrm-brackets/gfw/config"
|
"git.xdrm.io/xdrm-brackets/gfw/config"
|
||||||
|
"git.xdrm.io/xdrm-brackets/gfw/err"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -13,65 +14,30 @@ func (s *Server) route(res http.ResponseWriter, req *http.Request) {
|
||||||
/* (1) Build request
|
/* (1) Build request
|
||||||
---------------------------------------------------------*/
|
---------------------------------------------------------*/
|
||||||
/* (1) Try to build request */
|
/* (1) Try to build request */
|
||||||
request, err := buildRequest(req)
|
request, err2 := buildRequest(req)
|
||||||
if err != nil {
|
if err2 != nil {
|
||||||
log.Fatal(req)
|
log.Fatal(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (2) Find a controller
|
/* (2) Find a controller
|
||||||
---------------------------------------------------------*/
|
---------------------------------------------------------*/
|
||||||
/* (1) Init browsing cursors */
|
controller := s.findController(request)
|
||||||
ctl := s.config
|
|
||||||
uriIndex := 0
|
|
||||||
|
|
||||||
/* (2) Browse while there is uri parts */
|
|
||||||
for uriIndex < len(request.Uri) {
|
|
||||||
uri := request.Uri[uriIndex]
|
|
||||||
|
|
||||||
child, hasKey := ctl.Children[uri]
|
|
||||||
|
|
||||||
// stop if no matchind child
|
|
||||||
if !hasKey {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
request.ControllerUri = append(request.ControllerUri, uri)
|
|
||||||
ctl = child
|
|
||||||
uriIndex++
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (3) Extract & store URI params */
|
|
||||||
request.Data.fillUrl(request.Uri[uriIndex:])
|
|
||||||
|
|
||||||
/* (3) Check method
|
/* (3) Check method
|
||||||
---------------------------------------------------------*/
|
---------------------------------------------------------*/
|
||||||
/* (1) Unavailable method */
|
method := s.getMethod(controller, req.Method)
|
||||||
if !config.IsMethodAvailable(req.Method) {
|
|
||||||
|
|
||||||
Json, _ := ErrUnknownMethod.MarshalJSON()
|
if method == nil {
|
||||||
|
Json, _ := err.UnknownMethod.MarshalJSON()
|
||||||
res.Header().Add("Content-Type", "application/json")
|
res.Header().Add("Content-Type", "application/json")
|
||||||
res.Write(Json)
|
res.Write(Json)
|
||||||
log.Printf("[err] %s\n", ErrUnknownMethod.Reason)
|
log.Printf("[err] %s\n", err.UnknownMethod.Reason)
|
||||||
return
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (2) Extract method cursor */
|
|
||||||
var method = ctl.Method(req.Method)
|
|
||||||
|
|
||||||
/* (3) Unmanaged HTTP method */
|
|
||||||
if method == nil { // unknown method
|
|
||||||
Json, _ := ErrUnknownMethod.MarshalJSON()
|
|
||||||
res.Header().Add("Content-Type", "application/json")
|
|
||||||
res.Write(Json)
|
|
||||||
log.Printf("[err] %s\n", ErrUnknownMethod.Reason)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (4) Check parameters
|
/* (4) Check parameters
|
||||||
---------------------------------------------------------*/
|
---------------------------------------------------------*/
|
||||||
var paramError Err = ErrSuccess
|
var paramError err.Error = err.Success
|
||||||
parameters := make(map[string]interface{})
|
parameters := make(map[string]interface{})
|
||||||
for name, param := range method.Parameters {
|
for name, param := range method.Parameters {
|
||||||
|
|
||||||
|
@ -80,14 +46,14 @@ func (s *Server) route(res http.ResponseWriter, req *http.Request) {
|
||||||
|
|
||||||
/* (2) Required & missing */
|
/* (2) Required & missing */
|
||||||
if !isset && !*param.Optional {
|
if !isset && !*param.Optional {
|
||||||
paramError = ErrMissingParam
|
paramError = err.MissingParam
|
||||||
paramError.BindArgument(name)
|
paramError.BindArgument(name)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (3) Optional & missing: set default value */
|
/* (3) Optional & missing: set default value */
|
||||||
if !isset {
|
if !isset {
|
||||||
p = &RequestParameter{
|
p = &requestParameter{
|
||||||
Parsed: true,
|
Parsed: true,
|
||||||
File: param.Type == "FILE",
|
File: param.Type == "FILE",
|
||||||
Value: nil,
|
Value: nil,
|
||||||
|
@ -105,7 +71,7 @@ func (s *Server) route(res http.ResponseWriter, req *http.Request) {
|
||||||
/* (4) Fail on unexpected multipart file */
|
/* (4) 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 = ErrInvalidParam
|
paramError = err.InvalidParam
|
||||||
paramError.BindArgument(name)
|
paramError.BindArgument(name)
|
||||||
paramError.BindArgument("FILE")
|
paramError.BindArgument("FILE")
|
||||||
break
|
break
|
||||||
|
@ -120,7 +86,7 @@ func (s *Server) route(res http.ResponseWriter, req *http.Request) {
|
||||||
/* (6) Check type */
|
/* (6) Check type */
|
||||||
if s.Checker.Run(param.Type, p.Value) != nil {
|
if s.Checker.Run(param.Type, p.Value) != nil {
|
||||||
|
|
||||||
paramError = ErrInvalidParam
|
paramError = err.InvalidParam
|
||||||
paramError.BindArgument(name)
|
paramError.BindArgument(name)
|
||||||
paramError.BindArgument(param.Type)
|
paramError.BindArgument(param.Type)
|
||||||
paramError.BindArgument(p.Value)
|
paramError.BindArgument(p.Value)
|
||||||
|
@ -131,10 +97,9 @@ func (s *Server) route(res http.ResponseWriter, req *http.Request) {
|
||||||
parameters[name] = p.Value
|
parameters[name] = p.Value
|
||||||
|
|
||||||
}
|
}
|
||||||
fmt.Printf("\n")
|
|
||||||
|
|
||||||
// Fail if argument check failed
|
// Fail if argument check failed
|
||||||
if paramError.Code != ErrSuccess.Code {
|
if paramError.Code != err.Success.Code {
|
||||||
Json, _ := paramError.MarshalJSON()
|
Json, _ := paramError.MarshalJSON()
|
||||||
res.Header().Add("Content-Type", "application/json")
|
res.Header().Add("Content-Type", "application/json")
|
||||||
res.Write(Json)
|
res.Write(Json)
|
||||||
|
@ -142,9 +107,69 @@ func (s *Server) route(res http.ResponseWriter, req *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* (5) Load controller
|
||||||
|
---------------------------------------------------------*/
|
||||||
|
callable, err := request.loadController(req.Method)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[err] %s\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
fmt.Printf("OK\nplugin: '%si.so'\n", strings.Join(request.ControllerUri, "/"))
|
fmt.Printf("OK\nplugin: '%si.so'\n", strings.Join(request.ControllerUri, "/"))
|
||||||
for name, value := range parameters {
|
for name, value := range parameters {
|
||||||
fmt.Printf(" $%s = %v\n", name, value)
|
fmt.Printf(" $%s = %v\n", name, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* (6) Execute and get response
|
||||||
|
---------------------------------------------------------*/
|
||||||
|
out, _ := callable(parameters)
|
||||||
|
fmt.Printf("-- OUT --\n")
|
||||||
|
for name, value := range out {
|
||||||
|
fmt.Printf(" $%s = %v\n", name, value)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Server) findController(req *Request) *config.Controller {
|
||||||
|
/* (1) Init browsing cursors */
|
||||||
|
ctl := s.config
|
||||||
|
uriIndex := 0
|
||||||
|
|
||||||
|
/* (2) Browse while there is uri parts */
|
||||||
|
for uriIndex < len(req.Uri) {
|
||||||
|
uri := req.Uri[uriIndex]
|
||||||
|
|
||||||
|
child, hasKey := ctl.Children[uri]
|
||||||
|
|
||||||
|
// stop if no matchind child
|
||||||
|
if !hasKey {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
req.ControllerUri = append(req.ControllerUri, uri)
|
||||||
|
ctl = child
|
||||||
|
uriIndex++
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (3) Extract & store URI params */
|
||||||
|
req.Data.fillUrl(req.Uri[uriIndex:])
|
||||||
|
|
||||||
|
/* (4) Return controller */
|
||||||
|
return ctl
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) getMethod(controller *config.Controller, method string) *config.Method {
|
||||||
|
|
||||||
|
/* (1) Unavailable method */
|
||||||
|
if !config.IsMethodAvailable(method) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (2) Extract method cursor */
|
||||||
|
var foundMethod = controller.Method(method)
|
||||||
|
|
||||||
|
/* (3) Return method | nil on error */
|
||||||
|
return foundMethod
|
||||||
|
|
||||||
|
}
|
||||||
|
|
19
types.go
19
types.go
|
@ -3,13 +3,14 @@ package gfw
|
||||||
import (
|
import (
|
||||||
"git.xdrm.io/xdrm-brackets/gfw/checker"
|
"git.xdrm.io/xdrm-brackets/gfw/checker"
|
||||||
"git.xdrm.io/xdrm-brackets/gfw/config"
|
"git.xdrm.io/xdrm-brackets/gfw/config"
|
||||||
|
"git.xdrm.io/xdrm-brackets/gfw/err"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Server struct {
|
type Server struct {
|
||||||
config *config.Controller
|
config *config.Controller
|
||||||
Params map[string]interface{}
|
Params map[string]interface{}
|
||||||
Checker *checker.TypeRegistry // type check
|
Checker *checker.TypeRegistry // type check
|
||||||
err Err
|
err err.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
type Request struct {
|
type Request struct {
|
||||||
|
@ -21,21 +22,21 @@ type Request struct {
|
||||||
ControllerUri []string
|
ControllerUri []string
|
||||||
|
|
||||||
// contains all data from URL, GET, and FORM
|
// contains all data from URL, GET, and FORM
|
||||||
Data *RequestData
|
Data *requestData
|
||||||
}
|
}
|
||||||
|
|
||||||
type RequestData struct {
|
type requestData struct {
|
||||||
|
|
||||||
// ordered values from the URI
|
// ordered values from the URI
|
||||||
// catches all after the controller path
|
// catches all after the controller path
|
||||||
//
|
//
|
||||||
// points to Request.Data
|
// points to Request.Data
|
||||||
Url []*RequestParameter
|
Url []*requestParameter
|
||||||
|
|
||||||
// uri parameters following the QUERY format
|
// uri parameters following the QUERY format
|
||||||
//
|
//
|
||||||
// points to Request.Data
|
// points to Request.Data
|
||||||
Get map[string]*RequestParameter
|
Get map[string]*requestParameter
|
||||||
|
|
||||||
// form data depending on the Content-Type:
|
// form data depending on the Content-Type:
|
||||||
// 'application/json' => key-value pair is parsed as json into the map
|
// 'application/json' => key-value pair is parsed as json into the map
|
||||||
|
@ -43,18 +44,18 @@ type RequestData struct {
|
||||||
// 'multipart/form-data' => parse form-data format
|
// 'multipart/form-data' => parse form-data format
|
||||||
//
|
//
|
||||||
// points to Request.Data
|
// points to Request.Data
|
||||||
Form map[string]*RequestParameter
|
Form map[string]*requestParameter
|
||||||
|
|
||||||
// contains URL+GET+FORM data with prefixes:
|
// contains URL+GET+FORM data with prefixes:
|
||||||
// - FORM: no prefix
|
// - FORM: no prefix
|
||||||
// - URL: 'URL#' followed by the index in Uri
|
// - URL: 'URL#' followed by the index in Uri
|
||||||
// - GET: 'GET@' followed by the key in GET
|
// - GET: 'GET@' followed by the key in GET
|
||||||
Set map[string]*RequestParameter
|
Set map[string]*requestParameter
|
||||||
}
|
}
|
||||||
|
|
||||||
// RequestParameter represents an http request parameter
|
// requestParameter represents an http request parameter
|
||||||
// that can be of type URL, GET, or FORM (multipart, json, urlencoded)
|
// that can be of type URL, GET, or FORM (multipart, json, urlencoded)
|
||||||
type RequestParameter struct {
|
type requestParameter struct {
|
||||||
// whether the value has been json-parsed
|
// whether the value has been json-parsed
|
||||||
// for optimisation purpose, parameters are only parsed
|
// for optimisation purpose, parameters are only parsed
|
||||||
// if they are required by the current controller
|
// if they are required by the current controller
|
||||||
|
|
Loading…
Reference in New Issue