ref 0: internal/request
This commit is contained in:
parent
b428c75f25
commit
a63e227538
|
@ -2,9 +2,10 @@ package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"git.xdrm.io/go/aicra/driver"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
"git.xdrm.io/go/aicra/driver"
|
||||||
)
|
)
|
||||||
|
|
||||||
// InferFromFolder fills the 'Map' by browsing recursively the
|
// InferFromFolder fills the 'Map' by browsing recursively the
|
||||||
|
|
|
@ -3,12 +3,45 @@ package request
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"git.xdrm.io/go/aicra/internal/multipart"
|
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"git.xdrm.io/go/aicra/internal/multipart"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// DataSet represents all data that can be caught:
|
||||||
|
// - URI (guessed from the URI by removing the controller path)
|
||||||
|
// - GET (default url data)
|
||||||
|
// - POST (from json, form-data, url-encoded)
|
||||||
|
type DataSet struct {
|
||||||
|
|
||||||
|
// ordered values from the URI
|
||||||
|
// catches all after the controller path
|
||||||
|
//
|
||||||
|
// points to DataSet.Data
|
||||||
|
URI []*Parameter
|
||||||
|
|
||||||
|
// uri parameters following the QUERY format
|
||||||
|
//
|
||||||
|
// points to DataSet.Data
|
||||||
|
Get map[string]*Parameter
|
||||||
|
|
||||||
|
// form data depending on the Content-Type:
|
||||||
|
// 'application/json' => key-value pair is parsed as json into the map
|
||||||
|
// 'application/x-www-form-urlencoded' => standard parameters as QUERY parameters
|
||||||
|
// 'multipart/form-data' => parse form-data format
|
||||||
|
//
|
||||||
|
// points to DataSet.Data
|
||||||
|
Form map[string]*Parameter
|
||||||
|
|
||||||
|
// contains URL+GET+FORM data with prefixes:
|
||||||
|
// - FORM: no prefix
|
||||||
|
// - URL: 'URL#' followed by the index in Uri
|
||||||
|
// - GET: 'GET@' followed by the key in GET
|
||||||
|
Set map[string]*Parameter
|
||||||
|
}
|
||||||
|
|
||||||
// NewDataset creates an empty request dataset
|
// NewDataset creates an empty request dataset
|
||||||
func NewDataset() *DataSet {
|
func NewDataset() *DataSet {
|
||||||
return &DataSet{
|
return &DataSet{
|
||||||
|
@ -245,3 +278,17 @@ func (i *DataSet) parseMultipart(req *http.Request) {
|
||||||
return
|
return
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// nameInjection returns whether there is
|
||||||
|
// a parameter name injection:
|
||||||
|
// - inferred GET parameters
|
||||||
|
// - inferred URL parameters
|
||||||
|
func nameInjection(pName string) bool {
|
||||||
|
return strings.HasPrefix(pName, "GET@") || strings.HasPrefix(pName, "URL#")
|
||||||
|
}
|
||||||
|
|
||||||
|
// validName returns whether a parameter name (without the GET@ or URL# prefix) is valid
|
||||||
|
// if fails if the name begins/ends with underscores
|
||||||
|
func validName(pName string) bool {
|
||||||
|
return strings.Trim(pName, "_") == pName
|
||||||
|
}
|
||||||
|
|
|
@ -4,42 +4,8 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// 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 len(uri) > 1 && uri[len(uri)-1] == '/' {
|
|
||||||
uri = uri[0 : len(uri)-1]
|
|
||||||
}
|
|
||||||
|
|
||||||
return uri
|
|
||||||
}
|
|
||||||
|
|
||||||
// nameInjection returns whether there is
|
|
||||||
// a parameter name injection:
|
|
||||||
// - inferred GET parameters
|
|
||||||
// - inferred URL parameters
|
|
||||||
func nameInjection(pName string) bool {
|
|
||||||
return strings.HasPrefix(pName, "GET@") || strings.HasPrefix(pName, "URL#")
|
|
||||||
}
|
|
||||||
|
|
||||||
// validName returns whether a parameter name (without the GET@ or URL# prefix) is valid
|
|
||||||
// if fails if the name begins/ends with underscores
|
|
||||||
func validName(pName string) bool {
|
|
||||||
return strings.Trim(pName, "_") == pName
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseParameter parses http GET/POST data
|
// parseParameter parses http GET/POST data
|
||||||
// - []string
|
// - []string
|
||||||
// - size = 1 : return json of first element
|
// - size = 1 : return json of first element
|
|
@ -1,5 +1,20 @@
|
||||||
package request
|
package request
|
||||||
|
|
||||||
|
// Parameter represents an http request parameter
|
||||||
|
// that can be of type URL, GET, or FORM (multipart, json, urlencoded)
|
||||||
|
type Parameter struct {
|
||||||
|
// whether the value has been json-parsed
|
||||||
|
// for optimisation purpose, parameters are only parsed
|
||||||
|
// if they are required by the current controller
|
||||||
|
Parsed bool
|
||||||
|
|
||||||
|
// whether the value is a file
|
||||||
|
File bool
|
||||||
|
|
||||||
|
// the actual parameter value
|
||||||
|
Value interface{}
|
||||||
|
}
|
||||||
|
|
||||||
// Parse parameter (json-like) if not already done
|
// Parse parameter (json-like) if not already done
|
||||||
func (i *Parameter) Parse() {
|
func (i *Parameter) Parse() {
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,21 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FromHTTP builds an interface request from a http.Request
|
// Request represents an API request i.e. HTTP
|
||||||
func FromHTTP(req *http.Request) (*Request, error) {
|
type Request struct {
|
||||||
|
// corresponds to the list of uri components
|
||||||
|
// featuring in the request URI
|
||||||
|
URI []string
|
||||||
|
|
||||||
|
// controller path (portion of 'Uri')
|
||||||
|
Path []string
|
||||||
|
|
||||||
|
// contains all data from URL, GET, and FORM
|
||||||
|
Data *DataSet
|
||||||
|
}
|
||||||
|
|
||||||
|
// New builds an interface request from a http.Request
|
||||||
|
func New(req *http.Request) (*Request, error) {
|
||||||
|
|
||||||
/* (1) Get useful data */
|
/* (1) Get useful data */
|
||||||
uri := normaliseURI(req.URL.Path)
|
uri := normaliseURI(req.URL.Path)
|
||||||
|
@ -24,3 +37,22 @@ func FromHTTP(req *http.Request) (*Request, error) {
|
||||||
|
|
||||||
return inst, nil
|
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 len(uri) > 1 && uri[len(uri)-1] == '/' {
|
||||||
|
uri = uri[0 : len(uri)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
return uri
|
||||||
|
}
|
||||||
|
|
|
@ -1,61 +0,0 @@
|
||||||
package request
|
|
||||||
|
|
||||||
// Request represents a request by its URI, controller path and data (uri, get, post)
|
|
||||||
type Request struct {
|
|
||||||
// corresponds to the list of uri components
|
|
||||||
// featuring in the request URI
|
|
||||||
URI []string
|
|
||||||
|
|
||||||
// controller path (portion of 'Uri')
|
|
||||||
Path []string
|
|
||||||
|
|
||||||
// contains all data from URL, GET, and FORM
|
|
||||||
Data *DataSet
|
|
||||||
}
|
|
||||||
|
|
||||||
// DataSet represents all data that can be caught:
|
|
||||||
// - URI (guessed from the URI by removing the controller path)
|
|
||||||
// - GET (default url data)
|
|
||||||
// - POST (from json, form-data, url-encoded)
|
|
||||||
type DataSet struct {
|
|
||||||
|
|
||||||
// ordered values from the URI
|
|
||||||
// catches all after the controller path
|
|
||||||
//
|
|
||||||
// points to DataSet.Data
|
|
||||||
URI []*Parameter
|
|
||||||
|
|
||||||
// uri parameters following the QUERY format
|
|
||||||
//
|
|
||||||
// points to DataSet.Data
|
|
||||||
Get map[string]*Parameter
|
|
||||||
|
|
||||||
// form data depending on the Content-Type:
|
|
||||||
// 'application/json' => key-value pair is parsed as json into the map
|
|
||||||
// 'application/x-www-form-urlencoded' => standard parameters as QUERY parameters
|
|
||||||
// 'multipart/form-data' => parse form-data format
|
|
||||||
//
|
|
||||||
// points to DataSet.Data
|
|
||||||
Form map[string]*Parameter
|
|
||||||
|
|
||||||
// contains URL+GET+FORM data with prefixes:
|
|
||||||
// - FORM: no prefix
|
|
||||||
// - URL: 'URL#' followed by the index in Uri
|
|
||||||
// - GET: 'GET@' followed by the key in GET
|
|
||||||
Set map[string]*Parameter
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parameter represents an http request parameter
|
|
||||||
// that can be of type URL, GET, or FORM (multipart, json, urlencoded)
|
|
||||||
type Parameter struct {
|
|
||||||
// whether the value has been json-parsed
|
|
||||||
// for optimisation purpose, parameters are only parsed
|
|
||||||
// if they are required by the current controller
|
|
||||||
Parsed bool
|
|
||||||
|
|
||||||
// whether the value is a file
|
|
||||||
File bool
|
|
||||||
|
|
||||||
// the actual parameter value
|
|
||||||
Value interface{}
|
|
||||||
}
|
|
11
server.go
11
server.go
|
@ -2,6 +2,11 @@ package aicra
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"git.xdrm.io/go/aicra/api"
|
"git.xdrm.io/go/aicra/api"
|
||||||
"git.xdrm.io/go/aicra/driver"
|
"git.xdrm.io/go/aicra/driver"
|
||||||
e "git.xdrm.io/go/aicra/err"
|
e "git.xdrm.io/go/aicra/err"
|
||||||
|
@ -10,10 +15,6 @@ import (
|
||||||
"git.xdrm.io/go/aicra/internal/config"
|
"git.xdrm.io/go/aicra/internal/config"
|
||||||
apirequest "git.xdrm.io/go/aicra/internal/request"
|
apirequest "git.xdrm.io/go/aicra/internal/request"
|
||||||
"git.xdrm.io/go/aicra/middleware"
|
"git.xdrm.io/go/aicra/middleware"
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Server represents an AICRA instance featuring:
|
// Server represents an AICRA instance featuring:
|
||||||
|
@ -111,7 +112,7 @@ func (s *Server) ServeHTTP(res http.ResponseWriter, req *http.Request) {
|
||||||
defer req.Body.Close()
|
defer req.Body.Close()
|
||||||
|
|
||||||
/* (1) Build request */
|
/* (1) Build request */
|
||||||
apiRequest, err := apirequest.FromHTTP(req)
|
apiRequest, err := apirequest.New(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
5
util.go
5
util.go
|
@ -2,12 +2,13 @@ package aicra
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"git.xdrm.io/go/aicra/api"
|
"git.xdrm.io/go/aicra/api"
|
||||||
"git.xdrm.io/go/aicra/err"
|
"git.xdrm.io/go/aicra/err"
|
||||||
"git.xdrm.io/go/aicra/internal/apidef"
|
"git.xdrm.io/go/aicra/internal/apidef"
|
||||||
apireq "git.xdrm.io/go/aicra/internal/request"
|
apireq "git.xdrm.io/go/aicra/internal/request"
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Server) matchController(req *apireq.Request) *apidef.Controller {
|
func (s *Server) matchController(req *apireq.Request) *apidef.Controller {
|
||||||
|
|
Loading…
Reference in New Issue