add 'controller path-finding' + 'method check' + [TODO: issue with ParseMultipartForm() that is slow]

This commit is contained in:
Adrien Marquès 2018-05-21 13:02:15 +02:00
parent 7301f2065c
commit 18f4bcbbae
5 changed files with 83 additions and 17 deletions

View File

@ -23,5 +23,5 @@ type Controller struct {
PUT *Method `json:"PUT"` PUT *Method `json:"PUT"`
DELETE *Method `json:"DELETE"` DELETE *Method `json:"DELETE"`
Children map[string]Controller `json:"/"` Children map[string]*Controller `json:"/"`
} }

View File

@ -2,12 +2,15 @@ package gfw
import ( import (
"encoding/json" "encoding/json"
"fmt"
"log" "log"
"math"
"net/http" "net/http"
"strings" "strings"
"time"
) )
// buildRequest builds an interface request
// from a http.Request
func buildRequest(req *http.Request) (*Request, error) { func buildRequest(req *http.Request) (*Request, error) {
/* (1) Init request */ /* (1) Init request */
@ -16,7 +19,9 @@ func buildRequest(req *http.Request) (*Request, error) {
Uri: strings.Split(uri, "/"), Uri: strings.Split(uri, "/"),
GetData: FetchGetData(req), GetData: FetchGetData(req),
FormData: FetchFormData(req), FormData: FetchFormData(req),
Data: make(map[string]interface{}),
} }
inst.ControllerUri = make([]string, 0, len(inst.Uri))
return inst, nil return inst, nil
} }
@ -91,8 +96,9 @@ func FetchFormData(req *http.Request) map[string]interface{} {
} else { // form-data or anything } else { // form-data or anything
startn := time.Now().UnixNano()
// 1. Parse form-data // 1. Parse form-data
if err := req.ParseMultipartForm(math.MaxInt32); err != nil { if err := req.ParseMultipartForm(req.ContentLength + 1); err != nil {
log.Printf("[read.multipart] %s\n", err) log.Printf("[read.multipart] %s\n", err)
return res return res
} }
@ -101,6 +107,7 @@ func FetchFormData(req *http.Request) map[string]interface{} {
for name, value := range req.PostForm { for name, value := range req.PostForm {
res[name] = value res[name] = value
} }
fmt.Printf("* %.3f us\n", float64(time.Now().UnixNano()-startn)/1e3)
} }

View File

@ -2,11 +2,12 @@ package gfw
import ( import (
"fmt" "fmt"
"git.xdrm.io/gfw/internal/config"
"log" "log"
"net/http" "net/http"
) )
func route(res http.ResponseWriter, req *http.Request) { func (s Server) route(res http.ResponseWriter, req *http.Request) {
/* (1) Build request /* (1) Build request
---------------------------------------------------------*/ ---------------------------------------------------------*/
@ -16,17 +17,73 @@ func route(res http.ResponseWriter, req *http.Request) {
log.Fatal(req) log.Fatal(req)
} }
fmt.Printf("Uri: %v\n", request.Uri) // fmt.Printf("Uri: %v\n", request.Uri)
fmt.Printf("GET: %v\n", request.GetData) // fmt.Printf("GET: %v\n", request.GetData)
fmt.Printf("POST: %v\n", request.FormData) // fmt.Printf("POST: %v\n", request.FormData)
// 1. Query parameters /* (2) Find a controller
// fmt.Printf("query: %v\n", req.URL.Query()) ---------------------------------------------------------*/
/* (1) Init browsing cursors */
ctl := s.config
uriIndex := 0
// 2. URI path /* (2) Browse while there is uri parts */
// fmt.Printf("uri: %v\n", req.URL.Path) for uriIndex < len(request.Uri) {
uri := request.Uri[uriIndex]
// 3. Form values child, hasKey := ctl.Children[uri]
// fmt.Printf("form: %v\n", req.FormValue("asa"))
// stop if no matchind child
if !hasKey {
break
}
request.ControllerUri = append(request.ControllerUri, uri)
ctl = child
uriIndex++
}
/* (3) Check method
---------------------------------------------------------*/
/* (1) Unavailable method */
if req.Method == "GET" && ctl.GET == nil ||
req.Method == "POST" && ctl.POST == nil ||
req.Method == "PUT" && ctl.PUT == nil ||
req.Method == "DELETE" && ctl.DELETE == nil {
Json, _ := ErrUnknownMethod.MarshalJSON()
res.Header().Add("Content-Type", "application/json")
res.Write(Json)
log.Printf("[err] %s\n", ErrUnknownMethod.Reason)
return
}
/* (2) Extract method cursor */
var method *config.Method
if req.Method == "GET" {
method = ctl.GET
} else if req.Method == "POST" {
method = ctl.POST
} else if req.Method == "PUT" {
method = ctl.PUT
} else if req.Method == "DELETE" {
method = ctl.DELETE
}
/* (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
}
/* (4) Check arguments
---------------------------------------------------------*/
fmt.Printf("OK\n")
return
} }

View File

@ -9,7 +9,7 @@ import (
func (s *Server) Launch(port uint16) error { func (s *Server) Launch(port uint16) error {
/* (1) Bind router */ /* (1) Bind router */
http.HandleFunc("/", route) http.HandleFunc("/", s.route)
/* (2) Bind listener */ /* (2) Bind listener */
return http.ListenAndServe(fmt.Sprintf(":%d", port), nil) return http.ListenAndServe(fmt.Sprintf(":%d", port), nil)

View File

@ -11,7 +11,9 @@ type Server struct {
} }
type Request struct { type Request struct {
Uri []string Uri []string
FormData map[string]interface{} ControllerUri []string
GetData map[string]interface{} FormData map[string]interface{}
GetData map[string]interface{}
Data map[string]interface{}
} }