From 7301f2065c4ff2e0de7b6ee2c31dc2908edfc777 Mon Sep 17 00:00:00 2001 From: xdrm-brackets Date: Mon, 21 May 2018 12:02:24 +0200 Subject: [PATCH] created initialiser + request builder (which supports form-data, urlencoded, json) --- errors.go | 38 ++++++++-------- loader.go | 23 ++++++++++ request_builder.go | 108 +++++++++++++++++++++++++++++++++++++++++++++ router.go | 32 ++++++++++++++ server.go | 17 +++++++ types.go | 17 +++++++ 6 files changed, 216 insertions(+), 19 deletions(-) create mode 100644 loader.go create mode 100644 request_builder.go create mode 100644 router.go create mode 100644 server.go create mode 100644 types.go diff --git a/errors.go b/errors.go index 871ed8e..34a4e06 100644 --- a/errors.go +++ b/errors.go @@ -13,35 +13,35 @@ type Err struct { var ( /* Base */ - ErrSuccess = &Err{0, "all right", nil} - ErrFailure = &Err{1, "it failed", nil} - ErrUnknown = &Err{-1, "", nil} + 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} + ErrNoMatchFound = Err{2, "no resource found", nil} + ErrAlreadyExists = Err{3, "resource already exists", nil} - ErrConfig = &Err{4, "configuration error", 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} + 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} + 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} + 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} + 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 diff --git a/loader.go b/loader.go new file mode 100644 index 0000000..5de9785 --- /dev/null +++ b/loader.go @@ -0,0 +1,23 @@ +package gfw + +import "git.xdrm.io/gfw/internal/config" + +// Init initilises a new framework instance +func Init(path string) (*Server, error) { + + /* (1) Init instance */ + inst := &Server{ + config: nil, + Params: make(map[string]interface{}), + err: ErrSuccess, + } + + /* (2) Load configuration */ + config, err := config.Load(path) + if err != nil { + return nil, err + } + inst.config = config + + return inst, nil +} diff --git a/request_builder.go b/request_builder.go new file mode 100644 index 0000000..bfc251a --- /dev/null +++ b/request_builder.go @@ -0,0 +1,108 @@ +package gfw + +import ( + "encoding/json" + "log" + "math" + "net/http" + "strings" +) + +func buildRequest(req *http.Request) (*Request, error) { + + /* (1) Init request */ + uri := NormaliseUri(req.URL.Path) + inst := &Request{ + Uri: strings.Split(uri, "/"), + GetData: FetchGetData(req), + FormData: FetchFormData(req), + } + + return inst, nil +} + +// NormaliseUri removes the trailing '/' to always +// have the same Uri format for later processing +func NormaliseUri(uri string) string { + + if len(uri) < 1 { + return uri + } + + if uri[0] == '/' { + uri = uri[1:] + } + + if uri[len(uri)-1] == '/' { + uri = uri[0 : len(uri)-1] + } + + return uri +} + +// FetchGetData extracts the GET data +// from an HTTP request +func FetchGetData(req *http.Request) map[string]interface{} { + + res := make(map[string]interface{}) + + for name, value := range req.URL.Query() { + res[name] = value + } + + return res + +} + +// FetchFormData extracts FORM data +// +// - parse 'form-data' if not supported (not POST requests) +// - parse 'x-www-form-urlencoded' +// - parse 'application/json' +func FetchFormData(req *http.Request) map[string]interface{} { + + res := make(map[string]interface{}) + + ct := req.Header.Get("Content-Type") + + if strings.HasPrefix(ct, "application/json") { + + receiver := make(map[string]interface{}, 0) + + // 1. Init JSON reader + decoder := json.NewDecoder(req.Body) + if err := decoder.Decode(&receiver); err != nil { + log.Printf("[parse.json] %s\n", err) + return res + } + + // 2. Return result + return receiver + + } else if strings.HasPrefix(ct, "application/x-www-form-urlencoded") { + + // 1. Parse url encoded data + req.ParseForm() + + // 2. Extract values + for name, value := range req.PostForm { + res[name] = value + } + + } else { // form-data or anything + + // 1. Parse form-data + if err := req.ParseMultipartForm(math.MaxInt32); err != nil { + log.Printf("[read.multipart] %s\n", err) + return res + } + + // 2. Extract values + for name, value := range req.PostForm { + res[name] = value + } + + } + + return res +} diff --git a/router.go b/router.go new file mode 100644 index 0000000..653245c --- /dev/null +++ b/router.go @@ -0,0 +1,32 @@ +package gfw + +import ( + "fmt" + "log" + "net/http" +) + +func route(res http.ResponseWriter, req *http.Request) { + + /* (1) Build request + ---------------------------------------------------------*/ + /* (1) Try to build request */ + request, err := buildRequest(req) + if err != nil { + log.Fatal(req) + } + + fmt.Printf("Uri: %v\n", request.Uri) + fmt.Printf("GET: %v\n", request.GetData) + fmt.Printf("POST: %v\n", request.FormData) + + // 1. Query parameters + // fmt.Printf("query: %v\n", req.URL.Query()) + + // 2. URI path + // fmt.Printf("uri: %v\n", req.URL.Path) + + // 3. Form values + // fmt.Printf("form: %v\n", req.FormValue("asa")) + +} diff --git a/server.go b/server.go new file mode 100644 index 0000000..8c11819 --- /dev/null +++ b/server.go @@ -0,0 +1,17 @@ +package gfw + +import ( + "fmt" + "net/http" +) + +// Launch listens and binds the server to the given port +func (s *Server) Launch(port uint16) error { + + /* (1) Bind router */ + http.HandleFunc("/", route) + + /* (2) Bind listener */ + return http.ListenAndServe(fmt.Sprintf(":%d", port), nil) + +} diff --git a/types.go b/types.go new file mode 100644 index 0000000..183722a --- /dev/null +++ b/types.go @@ -0,0 +1,17 @@ +package gfw + +import ( + "git.xdrm.io/gfw/internal/config" +) + +type Server struct { + config *config.Controller + Params map[string]interface{} + err Err +} + +type Request struct { + Uri []string + FormData map[string]interface{} + GetData map[string]interface{} +}