summaryrefslogtreecommitdiff
path: root/server/psr7
diff options
context:
space:
mode:
Diffstat (limited to 'server/psr7')
-rw-r--r--server/psr7/files.go58
-rw-r--r--server/psr7/post.go45
-rw-r--r--server/psr7/request.go101
-rw-r--r--server/psr7/response.go21
4 files changed, 225 insertions, 0 deletions
diff --git a/server/psr7/files.go b/server/psr7/files.go
new file mode 100644
index 00000000..31ddfec8
--- /dev/null
+++ b/server/psr7/files.go
@@ -0,0 +1,58 @@
+package psr7
+
+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/server/psr7/post.go b/server/psr7/post.go
new file mode 100644
index 00000000..30af7e3a
--- /dev/null
+++ b/server/psr7/post.go
@@ -0,0 +1,45 @@
+package psr7
+
+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/server/psr7/request.go b/server/psr7/request.go
new file mode 100644
index 00000000..f8dedd8f
--- /dev/null
+++ b/server/psr7/request.go
@@ -0,0 +1,101 @@
+package psr7
+
+import (
+ "net/http"
+ "fmt"
+ "encoding/json"
+ "github.com/spiral/roadrunner"
+ "github.com/sirupsen/logrus"
+)
+
+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"`
+
+ // buffers
+ postData postData
+}
+
+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")
+ }
+ }
+
+ return req, nil
+}
+
+func (r *Request) Payload() *roadrunner.Payload {
+ ctx, err := json.Marshal(r)
+ if err != nil {
+ panic(err) //todo: change it
+ }
+
+ // todo: non parseble payloads
+ body, err := json.Marshal(r.postData)
+ if err != nil {
+ panic(err) //todo: change it
+ }
+
+ 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 {
+ return r.Method == "POST" || r.Method == "PUT" || r.Method == "PATCH"
+}
+
+// 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/server/psr7/response.go b/server/psr7/response.go
new file mode 100644
index 00000000..c0d739a7
--- /dev/null
+++ b/server/psr7/response.go
@@ -0,0 +1,21 @@
+package psr7
+
+import (
+ "net/http"
+)
+
+type Response struct {
+ Status int `json:"status"`
+ Headers map[string][]string `json:"headers"`
+}
+
+func (r *Response) Write(w http.ResponseWriter) {
+ for k, v := range r.Headers {
+ for _, h := range v {
+ w.Header().Add(k, h)
+
+ }
+ }
+
+ w.WriteHeader(r.Status)
+}