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"`
DELETE *Method `json:"DELETE"`
Children map[string]Controller `json:"/"`
Children map[string]*Controller `json:"/"`
}

View File

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

View File

@ -2,11 +2,12 @@ package gfw
import (
"fmt"
"git.xdrm.io/gfw/internal/config"
"log"
"net/http"
)
func route(res http.ResponseWriter, req *http.Request) {
func (s Server) route(res http.ResponseWriter, req *http.Request) {
/* (1) Build request
---------------------------------------------------------*/
@ -16,17 +17,73 @@ func route(res http.ResponseWriter, req *http.Request) {
log.Fatal(req)
}
fmt.Printf("Uri: %v\n", request.Uri)
fmt.Printf("GET: %v\n", request.GetData)
fmt.Printf("POST: %v\n", request.FormData)
// 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) Find a controller
---------------------------------------------------------*/
/* (1) Init browsing cursors */
ctl := s.config
uriIndex := 0
// 2. URI path
// fmt.Printf("uri: %v\n", req.URL.Path)
/* (2) Browse while there is uri parts */
for uriIndex < len(request.Uri) {
uri := request.Uri[uriIndex]
// 3. Form values
// fmt.Printf("form: %v\n", req.FormValue("asa"))
child, hasKey := ctl.Children[uri]
// 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 {
/* (1) Bind router */
http.HandleFunc("/", route)
http.HandleFunc("/", s.route)
/* (2) Bind listener */
return http.ListenAndServe(fmt.Sprintf(":%d", port), nil)

View File

@ -12,6 +12,8 @@ type Server struct {
type Request struct {
Uri []string
ControllerUri []string
FormData map[string]interface{}
GetData map[string]interface{}
Data map[string]interface{}
}