diff --git a/g/net/ghttp/http_client_request.go b/g/net/ghttp/http_client_request.go index 251ba8166..694cb0a4d 100644 --- a/g/net/ghttp/http_client_request.go +++ b/g/net/ghttp/http_client_request.go @@ -8,14 +8,14 @@ package ghttp import ( - "os" - "io" "time" "bytes" "strings" "net/http" - "mime/multipart" "fmt" + "mime/multipart" + "os" + "io" ) // http客户端 @@ -46,40 +46,44 @@ func (c *Client) Put(url, data string) (*ClientResponse, error) { // POST请求提交数据 // 支持文件上传,需要字段格式为:FieldName=@file: func (c *Client) Post(url, data string) (*ClientResponse, error) { - isfile := false - buffer := new(bytes.Buffer) - writer := multipart.NewWriter(buffer) - for _, item := range strings.Split(data, "&") { - array := strings.Split(item, "=") - // 判断是否文件上传 - if len(array[1]) > 6 && strings.Compare(array[1][0:6], "@file:") == 0 { - isfile = true - if file, err := writer.CreateFormFile(array[0], array[1][6:]); err == nil { - if f, err := os.Open(array[1][6:]); err == nil { - defer f.Close() - if _, err = io.Copy(file, f); err != nil { + var req *http.Request + hasfile := strings.Contains(data, "@file:") + if hasfile { + buffer := new(bytes.Buffer) + writer := multipart.NewWriter(buffer) + for _, item := range strings.Split(data, "&") { + array := strings.Split(item, "=") + if len(array[1]) > 6 && strings.Compare(array[1][0:6], "@file:") == 0 { + if file, err := writer.CreateFormFile(array[0], array[1][6:]); err == nil { + if f, err := os.Open(array[1][6:]); err == nil { + defer f.Close() + if _, err = io.Copy(file, f); err != nil { + return nil, err + } + } else { return nil, err } } else { return nil, err } } else { - return nil, err + writer.WriteField(array[0], array[1]) } - } else { - writer.WriteField(array[0], array[1]) } - } - writer.Close() - req, err := http.NewRequest("POST", url, buffer) - if err != nil { - return nil, err - } - // 表单类型处理 - if isfile { - req.Header.Set("Content-Type", writer.FormDataContentType()) + writer.Close() + if r, err := http.NewRequest("POST", url, buffer); err != nil { + return nil, err + } else { + req = r + req.Header.Set("Content-Type", writer.FormDataContentType()) + } } else { - req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + if r, err := http.NewRequest("POST", url, bytes.NewReader([]byte(data))); err != nil { + return nil, err + } else { + req = r + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + } } // 执行请求 resp, err := c.Do(req) @@ -118,9 +122,9 @@ func (c *Client) Trace(url, data string) (*ClientResponse, error) { // 请求并返回response对象,该方法支持二进制提交数据 func (c *Client) DoRequest(method, url string, data []byte) (*ClientResponse, error) { - //if strings.Compare("POST", strings.ToUpper(method)) == 0 { - // return c.Post(url, string(data)) - //} + if strings.Compare("POST", strings.ToUpper(method)) == 0 { + return c.Post(url, string(data)) + } fmt.Println(method) req, err := http.NewRequest(strings.ToUpper(method), url, bytes.NewReader(data)) if err != nil { diff --git a/g/net/ghttp/http_func.go b/g/net/ghttp/http_func.go new file mode 100644 index 000000000..1ea8402b3 --- /dev/null +++ b/g/net/ghttp/http_func.go @@ -0,0 +1,18 @@ +// Copyright 2017 gf Author(https://gitee.com/johng/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://gitee.com/johng/gf. + +package ghttp + +import "gitee.com/johng/gf/g/encoding/gurl" + +// 构建请求参数,将参数进行urlencode编码 +func BuildParams(params map[string]string) string { + var s string + for k, v := range params { + s += k + "=" + gurl.Encode(v) + } + return s +} \ No newline at end of file diff --git a/g/net/ghttp/http_request.go b/g/net/ghttp/http_request.go index 7939d2ad5..98a452962 100644 --- a/g/net/ghttp/http_request.go +++ b/g/net/ghttp/http_request.go @@ -12,26 +12,41 @@ import ( "net/url" "gitee.com/johng/gf/g/util/gconv" "gitee.com/johng/gf/g/encoding/gjson" - "fmt" ) // 请求对象 type Request struct { http.Request - getvals *url.Values // GET参数 - Id int // 请求id(唯一) - Server *Server // 请求关联的服务器对象 - Cookie *Cookie // 与当前请求绑定的Cookie对象(并发安全) - Session *Session // 与当前请求绑定的Session对象(并发安全) - Response *Response // 对应请求的返回数据操作对象 + parsedPost bool // POST参数是否已经解析 + getvals *url.Values // GET参数 + Id int // 请求id(唯一) + Server *Server // 请求关联的服务器对象 + Cookie *Cookie // 与当前请求绑定的Cookie对象(并发安全) + Session *Session // 与当前请求绑定的Session对象(并发安全) + Response *Response // 对应请求的返回数据操作对象 } -// 获得指定名称的get参数列表 -func (r *Request) GetQuery(k string) []string { +// 初始化GET请求参数 +func (r *Request) initGet() { if r.getvals == nil { values := r.URL.Query() r.getvals = &values } +} + +// 初始化POST请求参数 +func (r *Request) initPost() { + if !r.parsedPost { + // 快速保存,尽量避免并发问题 + r.parsedPost = true + // MultiMedia表单请求解析允许最大使用内存:1GB + r.ParseMultipartForm(1024*1024*1024) + } +} + +// 获得指定名称的get参数列表 +func (r *Request) GetQuery(k string) []string { + r.initGet() if v, ok := (*r.getvals)[k]; ok { return v } @@ -72,14 +87,21 @@ func (r *Request) GetQueryArray(k string) []string { } // 获取指定键名的关联数组,并且给定当指定键名不存在时的默认值 -func (r *Request) GetQueryMap(defaultMap map[string]string) map[string]string { +func (r *Request) GetQueryMap(defaultMap...map[string]string) map[string]string { + r.initGet() m := make(map[string]string) - for k, v := range defaultMap { - v2 := r.GetQueryArray(k) - if v2 == nil { - m[k] = v - } else { - m[k] = v2[0] + if len(defaultMap) == 0 { + for k, v := range *r.getvals { + m[k] = v[0] + } + } else { + for k, v := range defaultMap[0] { + v2 := r.GetQueryArray(k) + if v2 == nil { + m[k] = v + } else { + m[k] = v2[0] + } } } return m @@ -87,10 +109,7 @@ func (r *Request) GetQueryMap(defaultMap map[string]string) map[string]string { // 获得post参数 func (r *Request) GetPost(k string) []string { - if len(r.PostForm) == 0 { - r.ParseForm() - fmt.Println(r) - } + r.initPost() if v, ok := r.PostForm[k]; ok { return v } @@ -132,13 +151,20 @@ func (r *Request) GetPostArray(k string) []string { // 获取指定键名的关联数组,并且给定当指定键名不存在时的默认值 // 需要注意的是,如果其中一个字段为数组形式,那么只会返回第一个元素,如果需要获取全部的元素,请使用GetPostArray获取特定字段内容 -func (r *Request) GetPostMap(defaultMap map[string]string) map[string]string { +func (r *Request) GetPostMap(defaultMap...map[string]string) map[string]string { + r.initPost() m := make(map[string]string) - for k, v := range defaultMap { - if v2, ok := r.PostForm[k]; ok { - m[k] = v2[0] - } else { - m[k] = v + if len(defaultMap) == 0 { + for k, v := range r.PostForm { + m[k] = v[0] + } + } else { + for k, v := range defaultMap[0] { + if v2, ok := r.PostForm[k]; ok { + m[k] = v2[0] + } else { + m[k] = v + } } } return m @@ -188,20 +214,28 @@ func (r *Request) GetRequestArray(k string) []string { // 获取指定键名的关联数组,并且给定当指定键名不存在时的默认值 // 需要注意的是,如果其中一个字段为数组形式,那么只会返回第一个元素,如果需要获取全部的元素,请使用GetRequestArray获取特定字段内容 -func (r *Request) GetRequestMap(defaultMap map[string]string) map[string]string { - m := make(map[string]string) - for k, v := range defaultMap { - v2 := r.GetRequest(k) - if v2 != nil { - m[k] = v2[0] - } else { - m[k] = v +func (r *Request) GetRequestMap(defaultMap...map[string]string) map[string]string { + m := r.GetQueryMap() + if len(defaultMap) == 0 { + for k, v := range r.GetPostMap() { + if _, ok := m[k]; !ok { + m[k] = v + } + } + } else { + for k, v := range defaultMap[0] { + v2 := r.GetRequest(k) + if v2 != nil { + m[k] = v2[0] + } else { + m[k] = v + } } } return m } -// 获取原始请求输入字符串 +// 获取原始请求输入字符串,注意:只能获取一次,读完就没了 func (r *Request) GetRaw() []byte { result, _ := ioutil.ReadAll(r.Body) return result diff --git a/g/os/gfile/gfile.go b/g/os/gfile/gfile.go index 179bdae0d..aaf1a2c91 100644 --- a/g/os/gfile/gfile.go +++ b/g/os/gfile/gfile.go @@ -49,7 +49,7 @@ func Create(path string) error { // 打开文件 func Open(path string) (*os.File, error) { - f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE, 0755) + f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE, 0666) if err != nil { return nil, err } @@ -58,7 +58,7 @@ func Open(path string) (*os.File, error) { // 打开文件 func OpenWithFlag(path string, flag int) (*os.File, error) { - f, err := os.OpenFile(path, flag, 0755) + f, err := os.OpenFile(path, flag, 0666) if err != nil { return nil, err } @@ -315,22 +315,22 @@ func putContents(path string, data []byte, flag int, perm os.FileMode) error { // (文本)写入文件内容 func PutContents(path string, content string) error { - return putContents(path, []byte(content), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0755) + return putContents(path, []byte(content), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) } // (文本)追加内容到文件末尾 func PutContentsAppend(path string, content string) error { - return putContents(path, []byte(content), os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0755) + return putContents(path, []byte(content), os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666) } // (二进制)写入文件内容 func PutBinContents(path string, content []byte) error { - return putContents(path, content, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0755) + return putContents(path, content, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) } // (二进制)追加内容到文件末尾 func PutBinContentsAppend(path string, content []byte) error { - return putContents(path, content, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0755) + return putContents(path, content, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666) } diff --git a/g/os/gfilepool/gfilepool.go b/g/os/gfilepool/gfilepool.go index 497d9d020..a0ceec6ba 100644 --- a/g/os/gfilepool/gfilepool.go +++ b/g/os/gfilepool/gfilepool.go @@ -99,7 +99,7 @@ func (p *Pool) File() (*File, error) { } } } - file, err := os.OpenFile(p.path, p.flag, 0755) + file, err := os.OpenFile(p.path, p.flag, 0666) if err != nil { return nil, err } diff --git a/g/os/glog/glog.go b/g/os/glog/glog.go index a4ea064a2..743e283c7 100644 --- a/g/os/glog/glog.go +++ b/g/os/glog/glog.go @@ -290,15 +290,15 @@ func (l *Logger) errPrint(s string) { // 调用回溯字符串 func (l *Logger) backtrace() string { - backtraces := []string{"Trace:"} - for i := 1; i < 100; i++ { + backtrace := "Trace:\n" + for i := 1; i < 10000; i++ { if _, cfile, cline, ok := runtime.Caller(i + 3); ok { - backtraces = append(backtraces, strconv.Itoa(i) + ". " + cfile + ":" + strconv.Itoa(cline) + "\n") + backtrace += strconv.Itoa(i) + ". " + cfile + ":" + strconv.Itoa(cline) + "\n" } else { break } } - return strings.Join(backtraces[0 : len(backtraces) -2 ], "\n") + return backtrace } func (l *Logger) format(s string) string { diff --git a/geg/frame/mvc/controller/demo/form.go b/geg/frame/mvc/controller/demo/form.go new file mode 100644 index 000000000..39f0c9270 --- /dev/null +++ b/geg/frame/mvc/controller/demo/form.go @@ -0,0 +1,35 @@ +package demo + +import ( + "gitee.com/johng/gf/g/net/ghttp" + "fmt" +) + +func Form(r *ghttp.Request) { + fmt.Println(r.GetPostMap()) + fmt.Println(r.GetPostString("name")) + fmt.Println(r.GetPostString("age")) + +} + +func FormShow(r *ghttp.Request) { + r.Response.WriteString(` + +
+