ref 0: internal/request

This commit is contained in:
Adrien Marquès 2019-05-01 00:02:28 +02:00
parent b428c75f25
commit a63e227538
8 changed files with 108 additions and 106 deletions

View File

@ -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

View File

@ -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
}

View File

@ -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

View File

@ -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() {

View File

@ -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
}

View File

@ -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{}
}

View File

@ -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)
} }

View File

@ -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 {