diff options
author | Wolfy-J <[email protected]> | 2018-05-31 15:19:54 +0300 |
---|---|---|
committer | Wolfy-J <[email protected]> | 2018-05-31 15:19:54 +0300 |
commit | 91a081e3ec43302ca1df8d436e48c2a14d7c76b9 (patch) | |
tree | 7c644b8bccf04f1a8dd5c07314665152dbea6d63 /http | |
parent | 48f4f7a39a2336be24cc74b4116c02cc941dbd9a (diff) |
psr7 support
Diffstat (limited to 'http')
-rw-r--r-- | http/files.go | 58 | ||||
-rw-r--r-- | http/post.go | 45 | ||||
-rw-r--r-- | http/request.go | 127 | ||||
-rw-r--r-- | http/response.go | 34 | ||||
-rw-r--r-- | http/server.go | 129 |
5 files changed, 0 insertions, 393 deletions
diff --git a/http/files.go b/http/files.go deleted file mode 100644 index 06e5fd24..00000000 --- a/http/files.go +++ /dev/null @@ -1,58 +0,0 @@ -package http - -import ( - "mime/multipart" - "strings" - "github.com/sirupsen/logrus" -) - -type fileData map[string]interface{} - -type FileUpload struct { - Name string `json:"name"` - MimeType string `json:"mimetype"` -} - -func (d fileData) push(k string, v []*multipart.FileHeader) { - if len(v) == 0 { - // doing nothing - return - } - - chunks := make([]string, 0) - for _, chunk := range strings.Split(k, "[") { - chunks = append(chunks, strings.Trim(chunk, "]")) - } - - d.pushChunk(chunks, v) -} - -func (d fileData) pushChunk(k []string, v []*multipart.FileHeader) { - logrus.Print(v) - if len(v) == 0 || v[0] == nil { - return - } - - head := k[0] - tail := k[1:] - if len(k) == 1 { - d[head] = FileUpload{ - Name: v[0].Filename, - MimeType: v[0].Header.Get("Content-Type"), - } - return - } - - // unnamed array - if len(tail) == 1 && tail[0] == "" { - d[head] = v - return - } - - if p, ok := d[head]; !ok { - d[head] = make(fileData) - d[head].(fileData).pushChunk(tail, v) - } else { - p.(fileData).pushChunk(tail, v) - } -} diff --git a/http/post.go b/http/post.go deleted file mode 100644 index 64c60d98..00000000 --- a/http/post.go +++ /dev/null @@ -1,45 +0,0 @@ -package http - -import "strings" - -type postData map[string]interface{} - -func (d postData) push(k string, v []string) { - if len(v) == 0 { - // doing nothing - return - } - - chunks := make([]string, 0) - for _, chunk := range strings.Split(k, "[") { - chunks = append(chunks, strings.Trim(chunk, "]")) - } - - d.pushChunk(chunks, v) -} - -func (d postData) pushChunk(k []string, v []string) { - if len(v) == 0 || v[0] == "" { - return - } - - head := k[0] - tail := k[1:] - if len(k) == 1 { - d[head] = v[0] - return - } - - // unnamed array - if len(tail) == 1 && tail[0] == "" { - d[head] = v - return - } - - if p, ok := d[head]; !ok { - d[head] = make(postData) - d[head].(postData).pushChunk(tail, v) - } else { - p.(postData).pushChunk(tail, v) - } -} diff --git a/http/request.go b/http/request.go deleted file mode 100644 index 032c70b5..00000000 --- a/http/request.go +++ /dev/null @@ -1,127 +0,0 @@ -package http - -import ( - "net/http" - "fmt" - "encoding/json" - "github.com/spiral/roadrunner" - "github.com/sirupsen/logrus" - "strings" - "io/ioutil" -) - -type Request struct { - Protocol string `json:"protocol"` - Uri string `json:"uri"` - Method string `json:"method"` - Headers http.Header `json:"headers"` - Cookies map[string]string `json:"cookies"` - RawQuery string `json:"rawQuery"` - Uploads fileData `json:"fileUploads"` - ParsedBody bool `json:"parsedBody"` - - // buffers - postData postData - body []byte -} - -func ParseRequest(r *http.Request) (req *Request, err error) { - req = &Request{ - Protocol: r.Proto, - Uri: fmt.Sprintf("%s%s", r.Host, r.URL.String()), - Method: r.Method, - Headers: r.Header, - Cookies: make(map[string]string), - RawQuery: r.URL.RawQuery, - } - - for _, c := range r.Cookies() { - req.Cookies[c.Name] = c.Value - } - - if req.HasBody() { - r.ParseMultipartForm(32 << 20) - - if req.postData, err = parseData(r); err != nil { - return nil, err - } - - if req.Uploads, err = parseFiles(r); err != nil { - return nil, err - } - - if req.Uploads != nil { - logrus.Debug("opening files") - } - req.ParsedBody = true - } else { - req.body, _ = ioutil.ReadAll(r.Body) - } - - return req, nil -} - -func (r *Request) Payload() *roadrunner.Payload { - ctx, err := json.Marshal(r) - if err != nil { - panic(err) //todo: change it - } - - var body []byte - if r.ParsedBody { - // todo: non parseble payloads - body, err = json.Marshal(r.postData) - if err != nil { - panic(err) //todo: change it - } - } else { - body = r.body - } - - return &roadrunner.Payload{Context: ctx, Body: body} -} - -func (r *Request) Close() { - if r.Uploads != nil { - - } -} - -// HasBody returns true if request might include POST data or file uploads. -func (r *Request) HasBody() bool { - if r.Method != "POST" && r.Method != "PUT" && r.Method != "PATCH" { - return false - } - - contentType := r.Headers.Get("content-type") - - if strings.Contains(contentType, "multipart/form-data") { - return true - } - - if contentType == "application/x-www-form-urlencoded" { - return true - } - - return false -} - -// parse incoming data request into JSON (including multipart form data) -func parseData(r *http.Request) (postData, error) { - data := make(postData) - for k, v := range r.MultipartForm.Value { - data.push(k, v) - } - - return data, nil -} - -// parse incoming data request into JSON (including multipart form data) -func parseFiles(r *http.Request) (fileData, error) { - data := make(fileData) - for k, v := range r.MultipartForm.File { - data.push(k, v) - } - - return data, nil -} diff --git a/http/response.go b/http/response.go deleted file mode 100644 index 6a094bf3..00000000 --- a/http/response.go +++ /dev/null @@ -1,34 +0,0 @@ -package http - -import ( - "net/http" - "github.com/sirupsen/logrus" -) - -type Response struct { - Status int `json:"status"` - Headers map[string][]string `json:"headers"` -} - -func (r *Response) Write(w http.ResponseWriter) { - push := make([]string, 0) - for k, v := range r.Headers { - for _, h := range v { - if k == "http2-push" { - push = append(push, h) - } else { - w.Header().Add(k, h) - } - } - } - - if p, ok := w.(http.Pusher); ok { - logrus.Info("PUSH SUPPORTED") - for _, f := range push { - logrus.Info("pushing HTTP2 file ", f) - p.Push(f, nil) - } - } - - w.WriteHeader(r.Status) -} diff --git a/http/server.go b/http/server.go deleted file mode 100644 index b0d0b56a..00000000 --- a/http/server.go +++ /dev/null @@ -1,129 +0,0 @@ -package http - -import ( - "github.com/spiral/roadrunner" - "net/http" - "strings" - "path" - "github.com/sirupsen/logrus" - "os" - "path/filepath" - "encoding/json" -) - -var ( - excludeFiles = []string{".php", ".htaccess"} -) - -// Configures http rr -type Config struct { - // ServeStatic enables static file serving from desired root directory. - ServeStatic bool - - // Root directory, required when ServeStatic set to true. - Root string -} - -// Server serves http connections to underlying PHP application using PSR-7 protocol. Context will include request headers, -// parsed files and query, payload will include parsed form data (if any) - todo: do we need to do that?. -type Server struct { - cfg Config - root http.Dir - rr *roadrunner.Server -} - -// NewServer returns new instance of Server PSR7 server. -func NewServer(cfg Config, server *roadrunner.Server) *Server { - h := &Server{cfg: cfg, rr: server} - if cfg.ServeStatic { - h.root = http.Dir(h.cfg.Root) - } - - return h -} - -// ServeHTTP serve using PSR-7 requests passed to underlying application. -func (svr *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) () { - if svr.cfg.ServeStatic && svr.serveStatic(w, r) { - // server always attempt to serve static files first - return - } - - req, err := ParseRequest(r) - if err != nil { - w.WriteHeader(500) - w.Write([]byte(err.Error())) //todo: better errors - return - } - defer req.Close() - - rsp, err := svr.rr.Exec(req.Payload()) - if err != nil { - w.WriteHeader(500) - w.Write([]byte(err.Error())) //todo: better errors - return - } - - resp := &Response{} - if err = json.Unmarshal(rsp.Context, resp); err != nil { - w.WriteHeader(500) - w.Write([]byte(err.Error())) //todo: better errors - return - } - - resp.Write(w) - w.Write(rsp.Body) -} - -// serveStatic attempts to serve static file and returns true in case of success, will return false in case if file not -// found, not allowed or on read error. -func (svr *Server) serveStatic(w http.ResponseWriter, r *http.Request) bool { - fpath := r.URL.Path - if !strings.HasPrefix(fpath, "/") { - fpath = "/" + fpath - } - fpath = path.Clean(fpath) - - if svr.excluded(fpath) { - logrus.Warningf("attempt to access forbidden file %s", fpath) - return false - } - - f, err := svr.root.Open(fpath) - if err != nil { - if !os.IsNotExist(err) { - // rr or access error - logrus.Error(err) - } - - return false - } - defer f.Close() - - d, err := f.Stat() - if err != nil { - // rr error - logrus.Error(err) - return false - } - - if d.IsDir() { - // we are not serving directories - return false - } - - http.ServeContent(w, r, d.Name(), d.ModTime(), f) - return true -} - -// excluded returns true if file has forbidden extension. -func (svr *Server) excluded(path string) bool { - ext := strings.ToLower(filepath.Ext(path)) - for _, exl := range excludeFiles { - if ext == exl { - return true - } - } - - return false -} |