mirror of
https://gitee.com/johng/gf.git
synced 2024-12-01 03:38:35 +08:00
improve ghttp.Client
This commit is contained in:
parent
8bbeb186c2
commit
2a2cfc289c
9
.example/net/ghttp/server/form/form-client.go
Normal file
9
.example/net/ghttp/server/form/form-client.go
Normal file
@ -0,0 +1,9 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/net/ghttp"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ghttp.PostContent("http://127.0.0.1:8199/", "array[]=1&array[]=2")
|
||||
}
|
@ -8,7 +8,7 @@ import (
|
||||
func main() {
|
||||
s := g.Server()
|
||||
s.BindHandler("/", func(r *ghttp.Request) {
|
||||
g.Dump(r.GetPostMap())
|
||||
g.Dump(r.GetForm("array"))
|
||||
r.Response.WriteTpl("form.html")
|
||||
})
|
||||
s.SetPort(8199)
|
||||
|
@ -4,99 +4,136 @@
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
// HTTP客户端请求.
|
||||
|
||||
package ghttp
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/text/gregex"
|
||||
)
|
||||
|
||||
// 是否模拟浏览器模式(自动保存提交COOKIE)
|
||||
func (c *Client) SetBrowserMode(enabled bool) {
|
||||
c.browserMode = enabled
|
||||
// Client is the HTTP client for HTTP request management.
|
||||
type Client struct {
|
||||
http.Client // Underlying HTTP Client.
|
||||
header map[string]string // Custom header map.
|
||||
cookies map[string]string // Custom cookie map.
|
||||
prefix string // Prefix for request.
|
||||
authUser string // HTTP basic authentication: user.
|
||||
authPass string // HTTP basic authentication: pass.
|
||||
browserMode bool // Whether auto saving and sending cookie content.
|
||||
retryCount int // Retry count when request fails.
|
||||
retryInterval int // Retry interval when request fails.
|
||||
}
|
||||
|
||||
// 设置HTTP Header
|
||||
func (c *Client) SetHeader(key, value string) {
|
||||
c.header[key] = value
|
||||
}
|
||||
|
||||
func (c *Client) SetHeaderMap(m map[string]string) {
|
||||
for k, v := range m {
|
||||
c.header[k] = v
|
||||
// NewClient creates and returns a new HTTP client object.
|
||||
func NewClient() *Client {
|
||||
return &Client{
|
||||
Client: http.Client{
|
||||
Transport: &http.Transport{
|
||||
// No validation for https certification of the server.
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
},
|
||||
DisableKeepAlives: true,
|
||||
},
|
||||
},
|
||||
header: make(map[string]string),
|
||||
cookies: make(map[string]string),
|
||||
}
|
||||
}
|
||||
|
||||
// 通过字符串设置HTTP Header
|
||||
func (c *Client) SetHeaderRaw(header string) {
|
||||
// Clone clones current client and returns a new one.
|
||||
func (c *Client) Clone() *Client {
|
||||
newClient := NewClient()
|
||||
*newClient = *c
|
||||
newClient.header = make(map[string]string)
|
||||
newClient.cookies = make(map[string]string)
|
||||
for k, v := range c.header {
|
||||
newClient.header[k] = v
|
||||
}
|
||||
for k, v := range c.cookies {
|
||||
newClient.cookies[k] = v
|
||||
}
|
||||
return newClient
|
||||
}
|
||||
|
||||
// SetBrowserMode enables browser mode of the client.
|
||||
// When browser mode is enabled, it automatically saves and sends cookie content
|
||||
// from and to server.
|
||||
func (c *Client) SetBrowserMode(enabled bool) *Client {
|
||||
c.browserMode = enabled
|
||||
return c
|
||||
}
|
||||
|
||||
// SetHeader sets a custom HTTP header pair for the client.
|
||||
func (c *Client) SetHeader(key, value string) *Client {
|
||||
c.header[key] = value
|
||||
return c
|
||||
}
|
||||
|
||||
// SetHeaderMap sets custom HTTP headers with map.
|
||||
func (c *Client) SetHeaderMap(m map[string]string) *Client {
|
||||
for k, v := range m {
|
||||
c.header[k] = v
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// SetContentType sets HTTP content type for the client.
|
||||
func (c *Client) SetContentType(contentType string) *Client {
|
||||
c.header["Content-Type"] = contentType
|
||||
return c
|
||||
}
|
||||
|
||||
// SetHeaderRaw sets custom HTTP header using raw string.
|
||||
func (c *Client) SetHeaderRaw(header string) *Client {
|
||||
for _, line := range strings.Split(strings.TrimSpace(header), "\n") {
|
||||
array, _ := gregex.MatchString(`^([\w\-]+):\s*(.+)`, line)
|
||||
if len(array) >= 3 {
|
||||
c.header[array[1]] = array[2]
|
||||
}
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// 设置COOKIE
|
||||
func (c *Client) SetCookie(key, value string) {
|
||||
// SetCookie sets a cookie pair for the client.
|
||||
func (c *Client) SetCookie(key, value string) *Client {
|
||||
c.cookies[key] = value
|
||||
return c
|
||||
}
|
||||
|
||||
// 使用Map设置COOKIE
|
||||
func (c *Client) SetCookieMap(m map[string]string) {
|
||||
// SetCookieMap sets cookie items with map.
|
||||
func (c *Client) SetCookieMap(m map[string]string) *Client {
|
||||
for k, v := range m {
|
||||
c.cookies[k] = v
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// 设置请求的URL前缀
|
||||
func (c *Client) SetPrefix(prefix string) {
|
||||
// SetPrefix sets the request server URL prefix.
|
||||
func (c *Client) SetPrefix(prefix string) *Client {
|
||||
c.prefix = prefix
|
||||
}
|
||||
|
||||
// 设置请求过期时间
|
||||
func (c *Client) SetTimeOut(t time.Duration) {
|
||||
c.Timeout = t
|
||||
}
|
||||
|
||||
// 设置HTTP访问账号密码
|
||||
func (c *Client) SetBasicAuth(user, pass string) {
|
||||
c.authUser = user
|
||||
c.authPass = pass
|
||||
}
|
||||
|
||||
// 设置失败重试次数及间隔,失败仅针对网络请求失败情况。
|
||||
// 重试间隔时间单位为秒。
|
||||
func (c *Client) SetRetry(retryCount int, retryInterval int) {
|
||||
c.retryCount = retryCount
|
||||
c.retryInterval = retryInterval
|
||||
}
|
||||
|
||||
// 链式操作, See SetBrowserMode
|
||||
func (c *Client) BrowserMode(enabled bool) *Client {
|
||||
c.browserMode = enabled
|
||||
return c
|
||||
}
|
||||
|
||||
// 链式操作, See SetTimeOut
|
||||
func (c *Client) TimeOut(t time.Duration) *Client {
|
||||
// SetTimeOut sets the request timeout for the client.
|
||||
func (c *Client) SetTimeOut(t time.Duration) *Client {
|
||||
c.Timeout = t
|
||||
return c
|
||||
}
|
||||
|
||||
// 链式操作, See SetBasicAuth
|
||||
func (c *Client) BasicAuth(user, pass string) *Client {
|
||||
// SetBasicAuth sets HTTP basic authentication information for the client.
|
||||
func (c *Client) SetBasicAuth(user, pass string) *Client {
|
||||
c.authUser = user
|
||||
c.authPass = pass
|
||||
return c
|
||||
}
|
||||
|
||||
// 链式操作, See SetRetry
|
||||
func (c *Client) Retry(retryCount int, retryInterval int) *Client {
|
||||
// SetRetry sets retry count and interval.
|
||||
func (c *Client) SetRetry(retryCount int, retryInterval int) *Client {
|
||||
c.retryCount = retryCount
|
||||
c.retryInterval = retryInterval
|
||||
return c
|
||||
|
@ -8,7 +8,6 @@ package ghttp
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
@ -22,51 +21,6 @@ import (
|
||||
"github.com/gogf/gf/os/gfile"
|
||||
)
|
||||
|
||||
// Client is the HTTP client for HTTP request management.
|
||||
type Client struct {
|
||||
http.Client // Underlying HTTP Client.
|
||||
header map[string]string // Custom header map.
|
||||
cookies map[string]string // Custom cookie map.
|
||||
prefix string // Prefix for request.
|
||||
authUser string // HTTP basic authentication: user.
|
||||
authPass string // HTTP basic authentication: pass.
|
||||
browserMode bool // Whether auto saving and sending cookie content.
|
||||
retryCount int // Retry count when request fails.
|
||||
retryInterval int // Retry interval when request fails.
|
||||
}
|
||||
|
||||
// NewClient creates and returns a new HTTP client object.
|
||||
func NewClient() *Client {
|
||||
return &Client{
|
||||
Client: http.Client{
|
||||
Transport: &http.Transport{
|
||||
// No validation for https certification of the server.
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
},
|
||||
DisableKeepAlives: true,
|
||||
},
|
||||
},
|
||||
header: make(map[string]string),
|
||||
cookies: make(map[string]string),
|
||||
}
|
||||
}
|
||||
|
||||
// Clone clones current client and returns a new one.
|
||||
func (c *Client) Clone() *Client {
|
||||
newClient := NewClient()
|
||||
*newClient = *c
|
||||
newClient.header = make(map[string]string)
|
||||
newClient.cookies = make(map[string]string)
|
||||
for k, v := range c.header {
|
||||
newClient.header[k] = v
|
||||
}
|
||||
for k, v := range c.cookies {
|
||||
newClient.cookies[k] = v
|
||||
}
|
||||
return newClient
|
||||
}
|
||||
|
||||
// Get send GET request and returns the response object.
|
||||
// Note that the response object MUST be closed if it'll be never used.
|
||||
func (c *Client) Get(url string) (*ClientResponse, error) {
|
||||
@ -259,6 +213,11 @@ func (c *Client) DoRequest(method, url string, data ...interface{}) (*ClientResp
|
||||
req.Header.Set(k, v)
|
||||
}
|
||||
}
|
||||
// Automatically set default content type to "application/x-www-form-urlencoded"
|
||||
// if there' no content type set.
|
||||
if _, ok := c.header["Content-Type"]; !ok {
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
}
|
||||
// Custom cookie.
|
||||
if len(c.cookies) > 0 {
|
||||
headerCookie := ""
|
||||
|
@ -36,13 +36,13 @@ type Request struct {
|
||||
parsedQuery bool // A bool marking whether the GET parameters parsed.
|
||||
parsedBody bool // A bool marking whether the request body parsed.
|
||||
parsedForm bool // A bool marking whether request Form parsed for HTTP method PUT, POST, PATCH.
|
||||
paramsMap map[string]interface{} // Custom parameters.
|
||||
routerMap map[string]interface{} // Router parameters map, which might be nil if there're no router parameters.
|
||||
queryMap map[string]interface{} // Query parameters map, which is nil if there's no query string.
|
||||
formMap map[string]interface{} // Form parameters map, which is nil if there's no form.
|
||||
formMap map[string]interface{} // Form parameters map, which is nil if there's no form data from client.
|
||||
bodyMap map[string]interface{} // Body parameters map, which might be nil if there're no body content.
|
||||
error error // Current executing error of the request.
|
||||
exit bool // A bool marking whether current request is exited.
|
||||
params map[string]interface{} // Custom parameters.
|
||||
parsedHost string // The parsed host name for current host used by GetHost function.
|
||||
clientIp string // The parsed client ip for current host used by GetClientIp function.
|
||||
bodyContent []byte // Request body content.
|
||||
|
@ -209,6 +209,11 @@ func (r *Request) ParseForm() {
|
||||
if r.formMap, err = gstr.Parse(params); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
} else {
|
||||
r.ParseBody()
|
||||
if len(r.bodyMap) > 0 {
|
||||
r.formMap = r.bodyMap
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,18 +10,18 @@ import "github.com/gogf/gf/container/gvar"
|
||||
|
||||
// SetParam sets custom parameter with key-value pair.
|
||||
func (r *Request) SetParam(key string, value interface{}) {
|
||||
if r.params == nil {
|
||||
r.params = make(map[string]interface{})
|
||||
if r.paramsMap == nil {
|
||||
r.paramsMap = make(map[string]interface{})
|
||||
}
|
||||
r.params[key] = value
|
||||
r.paramsMap[key] = value
|
||||
}
|
||||
|
||||
// GetParam returns custom parameter with given name <key>.
|
||||
// It returns <def> if <key> does not exist.
|
||||
// It returns nil if <def> is not passed.
|
||||
func (r *Request) GetParam(key string, def ...interface{}) interface{} {
|
||||
if r.params != nil {
|
||||
return r.params[key]
|
||||
if r.paramsMap != nil {
|
||||
return r.paramsMap[key]
|
||||
}
|
||||
if len(def) > 0 {
|
||||
return def[0]
|
||||
|
@ -106,11 +106,11 @@ func (r *Request) GetFormInterfaces(key string, def ...interface{}) []interface{
|
||||
// the associated values are the default values if the client does not pass.
|
||||
func (r *Request) GetFormMap(kvMap ...map[string]interface{}) map[string]interface{} {
|
||||
r.ParseForm()
|
||||
if len(kvMap) > 0 {
|
||||
if len(kvMap) > 0 && kvMap[0] != nil {
|
||||
if len(r.formMap) == 0 {
|
||||
return kvMap[0]
|
||||
}
|
||||
m := make(map[string]interface{})
|
||||
m := make(map[string]interface{}, len(kvMap[0]))
|
||||
for k, defValue := range kvMap[0] {
|
||||
if postValue, ok := r.formMap[k]; ok {
|
||||
m[k] = postValue
|
||||
|
@ -15,16 +15,19 @@ import (
|
||||
// GetPost retrieves and returns parameter <key> from form and body.
|
||||
// It returns <def> if <key> does not exist in neither form nor body.
|
||||
// It returns nil if <def> is not passed.
|
||||
//
|
||||
// Note that if there're multiple parameters with the same name, the parameters are retrieved and overwrote
|
||||
// in order of priority: form < body.
|
||||
func (r *Request) GetPost(key string, def ...interface{}) interface{} {
|
||||
r.ParseForm()
|
||||
r.ParseBody()
|
||||
if len(r.formMap) > 0 {
|
||||
if v, ok := r.formMap[key]; ok {
|
||||
if len(r.bodyMap) > 0 {
|
||||
if v, ok := r.bodyMap[key]; ok {
|
||||
return v
|
||||
}
|
||||
}
|
||||
if len(r.bodyMap) > 0 {
|
||||
if v, ok := r.bodyMap[key]; ok {
|
||||
if len(r.formMap) > 0 {
|
||||
if v, ok := r.formMap[key]; ok {
|
||||
return v
|
||||
}
|
||||
}
|
||||
@ -101,38 +104,39 @@ func (r *Request) GetPostInterfaces(key string, def ...interface{}) []interface{
|
||||
// GetPostMap retrieves and returns all parameters in the form and body passed from client
|
||||
// as map. The parameter <kvMap> specifies the keys retrieving from client parameters,
|
||||
// the associated values are the default values if the client does not pass.
|
||||
//
|
||||
// Note that if there're multiple parameters with the same name, the parameters are retrieved and overwrote
|
||||
// in order of priority: form < body.
|
||||
func (r *Request) GetPostMap(kvMap ...map[string]interface{}) map[string]interface{} {
|
||||
r.ParseForm()
|
||||
r.ParseBody()
|
||||
var ok, filter bool
|
||||
if len(kvMap) > 0 && kvMap[0] != nil {
|
||||
filter = true
|
||||
}
|
||||
m := make(map[string]interface{}, len(r.formMap)+len(r.bodyMap))
|
||||
if len(kvMap) > 0 {
|
||||
if len(r.formMap) == 0 && len(r.bodyMap) == 0 {
|
||||
return kvMap[0]
|
||||
}
|
||||
if len(r.formMap) > 0 {
|
||||
for k, v := range kvMap[0] {
|
||||
if postValue, ok := r.formMap[k]; ok {
|
||||
m[k] = postValue
|
||||
} else {
|
||||
m[k] = v
|
||||
}
|
||||
for k, v := range r.formMap {
|
||||
if filter {
|
||||
if _, ok = kvMap[0][k]; !ok {
|
||||
continue
|
||||
}
|
||||
}
|
||||
if len(r.bodyMap) > 0 {
|
||||
for k, v := range kvMap[0] {
|
||||
if postValue, ok := r.bodyMap[k]; ok {
|
||||
m[k] = postValue
|
||||
} else {
|
||||
m[k] = v
|
||||
}
|
||||
m[k] = v
|
||||
}
|
||||
for k, v := range r.bodyMap {
|
||||
if filter {
|
||||
if _, ok = kvMap[0][k]; !ok {
|
||||
continue
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for k, v := range r.formMap {
|
||||
m[k] = v
|
||||
}
|
||||
for k, v := range r.bodyMap {
|
||||
m[k] = v
|
||||
m[k] = v
|
||||
}
|
||||
// Check none exist parameters and assign it with default value.
|
||||
if filter {
|
||||
for k, v := range kvMap[0] {
|
||||
if _, ok = m[k]; !ok {
|
||||
m[k] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
return m
|
||||
|
@ -25,16 +25,19 @@ func (r *Request) SetQuery(key string, value interface{}) {
|
||||
// GetQuery retrieves and returns parameter with given name <key> from query string
|
||||
// and request body. It returns <def> if <key> does not exist in the query. It returns nil
|
||||
// if <def> is not passed.
|
||||
//
|
||||
// Note that if there're multiple parameters with the same name, the parameters are retrieved and overwrote
|
||||
// in order of priority: query < body.
|
||||
func (r *Request) GetQuery(key string, def ...interface{}) interface{} {
|
||||
r.ParseQuery()
|
||||
r.ParseBody()
|
||||
if len(r.queryMap) > 0 {
|
||||
if v, ok := r.queryMap[key]; ok {
|
||||
if len(r.bodyMap) > 0 {
|
||||
if v, ok := r.bodyMap[key]; ok {
|
||||
return v
|
||||
}
|
||||
}
|
||||
if len(r.bodyMap) > 0 {
|
||||
if v, ok := r.bodyMap[key]; ok {
|
||||
if len(r.queryMap) > 0 {
|
||||
if v, ok := r.queryMap[key]; ok {
|
||||
return v
|
||||
}
|
||||
}
|
||||
@ -111,14 +114,18 @@ func (r *Request) GetQueryInterfaces(key string, def ...interface{}) []interface
|
||||
// GetQueryMap retrieves and returns all parameters passed from client using HTTP GET method
|
||||
// as map. The parameter <kvMap> specifies the keys retrieving from client parameters,
|
||||
// the associated values are the default values if the client does not pass.
|
||||
//
|
||||
// Note that if there're multiple parameters with the same name, the parameters are retrieved and overwrote
|
||||
// in order of priority: query < body.
|
||||
func (r *Request) GetQueryMap(kvMap ...map[string]interface{}) map[string]interface{} {
|
||||
r.ParseQuery()
|
||||
r.ParseBody()
|
||||
m := make(map[string]interface{}, len(r.queryMap)+len(r.bodyMap))
|
||||
if len(kvMap) > 0 {
|
||||
var m map[string]interface{}
|
||||
if len(kvMap) > 0 && kvMap[0] != nil {
|
||||
if len(r.queryMap) == 0 && len(r.bodyMap) == 0 {
|
||||
return kvMap[0]
|
||||
}
|
||||
m = make(map[string]interface{}, len(kvMap[0]))
|
||||
if len(r.queryMap) > 0 {
|
||||
for k, v := range kvMap[0] {
|
||||
if postValue, ok := r.queryMap[k]; ok {
|
||||
@ -138,6 +145,7 @@ func (r *Request) GetQueryMap(kvMap ...map[string]interface{}) map[string]interf
|
||||
}
|
||||
}
|
||||
} else {
|
||||
m = make(map[string]interface{}, len(r.queryMap)+len(r.bodyMap))
|
||||
for k, v := range r.queryMap {
|
||||
m[k] = v
|
||||
}
|
||||
|
@ -12,32 +12,38 @@ import (
|
||||
"github.com/gogf/gf/util/gconv"
|
||||
)
|
||||
|
||||
// GetRequestVar retrieves and returns the parameter named <key> passed from client as interface{},
|
||||
// GetRequest retrieves and returns the parameter named <key> passed from client as interface{},
|
||||
// no matter what HTTP method the client is using. The parameter <def> specifies the default value
|
||||
// if the <key> does not exist.
|
||||
//
|
||||
// Note that the parameter is retrieved in order of: router->get/body->post/body->param.
|
||||
// GetRequest is one of the most commonly used functions for retrieving parameters.
|
||||
//
|
||||
// Note that if there're multiple parameters with the same name, the parameters are retrieved and overwrote
|
||||
// in order of priority: router < query < form < body < custom.
|
||||
func (r *Request) GetRequest(key string, def ...interface{}) interface{} {
|
||||
v := r.GetRouterValue(key)
|
||||
if v == nil {
|
||||
r.ParseQuery()
|
||||
if len(r.queryMap) > 0 {
|
||||
v, _ = r.queryMap[key]
|
||||
value := r.GetParam(key)
|
||||
if value == nil {
|
||||
r.ParseBody()
|
||||
if len(r.bodyMap) > 0 {
|
||||
value = r.bodyMap[key]
|
||||
}
|
||||
}
|
||||
if v == nil {
|
||||
v = r.GetPost(key)
|
||||
if value == nil {
|
||||
value = r.GetForm(key)
|
||||
}
|
||||
if v == nil {
|
||||
v = r.GetParam(key)
|
||||
if value == nil {
|
||||
value = r.GetQuery(key)
|
||||
}
|
||||
if v != nil {
|
||||
return v
|
||||
if value == nil {
|
||||
value = r.GetRouterValue(key)
|
||||
}
|
||||
if value != nil {
|
||||
return value
|
||||
}
|
||||
if len(def) > 0 {
|
||||
return def[0]
|
||||
}
|
||||
return v
|
||||
return value
|
||||
}
|
||||
|
||||
// GetRequestVar retrieves and returns the parameter named <key> passed from client as *gvar.Var,
|
||||
@ -155,26 +161,70 @@ func (r *Request) GetRequestInterfaces(key string, def ...interface{}) []interfa
|
||||
// GetRequestMap retrieves and returns all parameters passed from client as map,
|
||||
// no matter what HTTP method the client is using. The parameter <kvMap> specifies the keys
|
||||
// retrieving from client parameters, the associated values are the default values if the client
|
||||
// does not pass.
|
||||
// does not pass the according keys.
|
||||
//
|
||||
// GetRequestMap is one of the most commonly used functions for retrieving parameters.
|
||||
//
|
||||
// Note that if there're multiple parameters with the same name, the parameters are retrieved and overwrote
|
||||
// in order of priority: router < query < form < body < custom.
|
||||
func (r *Request) GetRequestMap(kvMap ...map[string]interface{}) map[string]interface{} {
|
||||
r.ParseQuery()
|
||||
r.ParseForm()
|
||||
r.ParseBody()
|
||||
m := make(map[string]interface{}, len(r.queryMap)+len(r.formMap)+len(r.bodyMap))
|
||||
var ok, filter bool
|
||||
var length int
|
||||
if len(kvMap) > 0 && kvMap[0] != nil {
|
||||
length = len(kvMap[0])
|
||||
filter = true
|
||||
} else {
|
||||
length = len(r.routerMap) + len(r.queryMap) + len(r.formMap) + len(r.bodyMap) + len(r.paramsMap)
|
||||
}
|
||||
m := make(map[string]interface{}, length)
|
||||
for k, v := range r.routerMap {
|
||||
if filter {
|
||||
if _, ok = kvMap[0][k]; !ok {
|
||||
continue
|
||||
}
|
||||
}
|
||||
m[k] = v
|
||||
}
|
||||
for k, v := range r.queryMap {
|
||||
if filter {
|
||||
if _, ok = kvMap[0][k]; !ok {
|
||||
continue
|
||||
}
|
||||
}
|
||||
m[k] = v
|
||||
}
|
||||
for k, v := range r.formMap {
|
||||
if filter {
|
||||
if _, ok = kvMap[0][k]; !ok {
|
||||
continue
|
||||
}
|
||||
}
|
||||
m[k] = v
|
||||
}
|
||||
for k, v := range r.bodyMap {
|
||||
if filter {
|
||||
if _, ok = kvMap[0][k]; !ok {
|
||||
continue
|
||||
}
|
||||
}
|
||||
m[k] = v
|
||||
}
|
||||
if len(kvMap) > 0 && kvMap[0] != nil {
|
||||
var ok bool
|
||||
for k, _ := range m {
|
||||
for k, v := range r.paramsMap {
|
||||
if filter {
|
||||
if _, ok = kvMap[0][k]; !ok {
|
||||
delete(m, k)
|
||||
continue
|
||||
}
|
||||
}
|
||||
m[k] = v
|
||||
}
|
||||
// Check none exist parameters and assign it with default value.
|
||||
if filter {
|
||||
for k, v := range kvMap[0] {
|
||||
if _, ok = m[k]; !ok {
|
||||
m[k] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -188,7 +238,7 @@ func (r *Request) GetRequestMap(kvMap ...map[string]interface{}) map[string]inte
|
||||
func (r *Request) GetRequestMapStrStr(kvMap ...map[string]interface{}) map[string]string {
|
||||
requestMap := r.GetRequestMap(kvMap...)
|
||||
if len(requestMap) > 0 {
|
||||
m := make(map[string]string)
|
||||
m := make(map[string]string, len(requestMap))
|
||||
for k, v := range requestMap {
|
||||
m[k] = gconv.String(v)
|
||||
}
|
||||
@ -204,7 +254,7 @@ func (r *Request) GetRequestMapStrStr(kvMap ...map[string]interface{}) map[strin
|
||||
func (r *Request) GetRequestMapStrVar(kvMap ...map[string]interface{}) map[string]*gvar.Var {
|
||||
requestMap := r.GetRequestMap(kvMap...)
|
||||
if len(requestMap) > 0 {
|
||||
m := make(map[string]*gvar.Var)
|
||||
m := make(map[string]*gvar.Var, len(requestMap))
|
||||
for k, v := range requestMap {
|
||||
m[k] = gvar.New(v)
|
||||
}
|
||||
|
@ -26,62 +26,72 @@ import (
|
||||
const (
|
||||
gDEFAULT_HTTP_ADDR = ":80" // Default listening port for HTTP.
|
||||
gDEFAULT_HTTPS_ADDR = ":443" // Default listening port for HTTPS.
|
||||
URI_TYPE_DEFAULT = 0 // Type for method name to URI converting, which converts name to its lower case and joins the words using char '-'.
|
||||
URI_TYPE_FULLNAME = 1 // Type for method name to URI converting, which does no converting to the method name.
|
||||
URI_TYPE_ALLLOWER = 2 // Type for method name to URI converting, which converts name to its lower case.
|
||||
URI_TYPE_CAMEL = 3 // Type for method name to URI converting, which converts name to its camel case.
|
||||
URI_TYPE_DEFAULT = 0 // Method name to URI converting type, which converts name to its lower case and joins the words using char '-'.
|
||||
URI_TYPE_FULLNAME = 1 // Method name to URI converting type, which does no converting to the method name.
|
||||
URI_TYPE_ALLLOWER = 2 // Method name to URI converting type, which converts name to its lower case.
|
||||
URI_TYPE_CAMEL = 3 // Method name to URI converting type, which converts name to its camel case.
|
||||
)
|
||||
|
||||
// HTTP Server configuration.
|
||||
type ServerConfig struct {
|
||||
Address string // Server listening address like ":port", multiple addresses joining using ','
|
||||
HTTPSAddr string // HTTPS addresses, multiple addresses joining using char ','.
|
||||
HTTPSCertPath string // HTTPS certification file path.
|
||||
HTTPSKeyPath string // HTTPS key file path.
|
||||
Handler http.Handler // Default request handler function.
|
||||
ReadTimeout time.Duration // Maximum duration for reading the entire request, including the body.
|
||||
WriteTimeout time.Duration // Maximum duration before timing out writes of the response.
|
||||
IdleTimeout time.Duration // Maximum amount of time to wait for the next request when keep-alives are enabled.
|
||||
MaxHeaderBytes int // Maximum number of bytes the server will read parsing the request header's keys and values, including the request line.
|
||||
TLSConfig *tls.Config // TLS configuration for use by ServeTLS and ListenAndServeTLS.
|
||||
KeepAlive bool // HTTP keep-alive are enabled or not.
|
||||
ServerAgent string // Server Agent.
|
||||
View *gview.View // View engine for the server.
|
||||
Rewrites map[string]string // URI rewrite rules.
|
||||
IndexFiles []string // Static: 默认访问的文件列表
|
||||
IndexFolder bool // Static: 如果访问目录是否显示目录列表
|
||||
ServerRoot string // Static: 服务器服务的本地目录根路径(检索优先级比StaticPaths低)
|
||||
SearchPaths []string // Static: 静态文件搜索目录(包含ServerRoot,按照优先级进行排序)
|
||||
StaticPaths []staticPathItem // Static: 静态文件目录映射(按照优先级进行排序)
|
||||
FileServerEnabled bool // Static: 是否允许静态文件服务(通过静态文件服务方法调用自动识别)
|
||||
CookieMaxAge time.Duration // Cookie: 有效期
|
||||
CookiePath string // Cookie: 有效Path(注意同时也会影响SessionID)
|
||||
CookieDomain string // Cookie: 有效Domain(注意同时也会影响SessionID)
|
||||
SessionMaxAge time.Duration // Session: 有效期
|
||||
SessionIdName string // Session: SessionId.
|
||||
SessionPath string // Session: Session Storage path for storing session files.
|
||||
SessionStorage gsession.Storage // Session: Session Storage implementer.
|
||||
DenyIps []string // Security: 不允许访问的ip列表,支持ip前缀过滤,如: 10 将不允许10开头的ip访问
|
||||
AllowIps []string // Security: 仅允许访问的ip列表,支持ip前缀过滤,如: 10 将仅允许10开头的ip访问
|
||||
DenyRoutes []string // Security: 不允许访问的路由规则列表
|
||||
Logger *glog.Logger // Logging: Custom logger for server.
|
||||
LogPath string // Logging: 存放日志的目录路径(默认为空,表示不写文件)
|
||||
LogStdout bool // Logging: 是否打印日志到终端(默认开启)
|
||||
ErrorStack bool // Logging: 当产生错误时打印调用链详细堆栈
|
||||
ErrorLogEnabled bool // Logging: 是否开启error log(默认开启)
|
||||
ErrorLogPattern string // Logging: Error log file pattern like: error-{Ymd}.log
|
||||
AccessLogEnabled bool // Logging: 是否开启access log(默认关闭)
|
||||
AccessLogPattern string // Logging: Error log file pattern like: access-{Ymd}.log
|
||||
PProfEnabled bool // PProf: Enable PProf feature or not.
|
||||
PProfPattern string // PProf: PProf pattern for router, it enables PProf feature if it's not empty.
|
||||
FormParsingMemory int64 // Mess: 表单解析内存限制(byte)
|
||||
NameToUriType int // Mess: 服务注册时对象和方法名称转换为URI时的规则
|
||||
GzipContentTypes []string // Mess: 允许进行gzip压缩的文件类型
|
||||
DumpRouteMap bool // Mess: 是否在程序启动时默认打印路由表信息
|
||||
RouterCacheExpire int // Mess: 路由检索缓存过期时间(秒)
|
||||
// Basic
|
||||
Address string // Server listening address like ":port", multiple addresses joined using ','.
|
||||
HTTPSAddr string // HTTPS addresses, multiple addresses joined using char ','.
|
||||
HTTPSCertPath string // HTTPS certification file path.
|
||||
HTTPSKeyPath string // HTTPS key file path.
|
||||
TLSConfig *tls.Config // TLS configuration for use by ServeTLS and ListenAndServeTLS.
|
||||
Handler http.Handler // Request handler.
|
||||
ReadTimeout time.Duration // Maximum duration for reading the entire request, including the body.
|
||||
WriteTimeout time.Duration // Maximum duration before timing out writes of the response.
|
||||
IdleTimeout time.Duration // Maximum amount of time to wait for the next request when keep-alive is enabled.
|
||||
MaxHeaderBytes int // Maximum number of bytes the server will read parsing the request header's keys and values, including the request line.
|
||||
KeepAlive bool // Enable HTTP keep-alive.
|
||||
ServerAgent string // Server Agent.
|
||||
View *gview.View // View object for the server.
|
||||
|
||||
// Static
|
||||
Rewrites map[string]string // URI rewrite rules map.
|
||||
IndexFiles []string // The index files for static folder.
|
||||
IndexFolder bool // Whether list sub-files when requesting folder; server responses HTTP status code 403 if it's false.
|
||||
ServerRoot string // The root directory for static service.
|
||||
SearchPaths []string // Additional searching directories for static service.
|
||||
StaticPaths []staticPathItem // URI to directory mapping array.
|
||||
FileServerEnabled bool // Switch for static service.
|
||||
|
||||
// Cookie
|
||||
CookieMaxAge time.Duration // Max TTL for cookie items.
|
||||
CookiePath string // Cookie Path(also affects the default storage for session id).
|
||||
CookieDomain string // Cookie Domain(also affects the default storage for session id).
|
||||
|
||||
// Session
|
||||
SessionMaxAge time.Duration // Max TTL for session items.
|
||||
SessionIdName string // Session id name.
|
||||
SessionPath string // Session Storage directory path for storing session files.
|
||||
SessionStorage gsession.Storage // Session Storage implementer.
|
||||
|
||||
// Logging
|
||||
Logger *glog.Logger // Logger for server.
|
||||
LogPath string // Directory for storing logging files.
|
||||
LogStdout bool // Printing logging content to stdout.
|
||||
ErrorStack bool // Logging stack information when error.
|
||||
ErrorLogEnabled bool // Enable error logging files.
|
||||
ErrorLogPattern string // Error log file pattern like: error-{Ymd}.log
|
||||
AccessLogEnabled bool // Enable access logging files.
|
||||
AccessLogPattern string // Error log file pattern like: access-{Ymd}.log
|
||||
|
||||
// PProf
|
||||
PProfEnabled bool // Enable PProf feature.
|
||||
PProfPattern string // PProf service pattern for router, it automatically enables PProf feature if called.
|
||||
|
||||
// Other
|
||||
FormParsingMemory int64 // 表单解析内存限制(byte)
|
||||
NameToUriType int // 服务注册时对象和方法名称转换为URI时的规则
|
||||
GzipContentTypes []string // 允许进行gzip压缩的文件类型
|
||||
DumpRouteMap bool // 是否在程序启动时默认打印路由表信息
|
||||
RouterCacheExpire int // 路由检索缓存过期时间(秒)
|
||||
}
|
||||
|
||||
// 默认HTTP Server配置
|
||||
// defaultServerConfig is the default configuration object for server.
|
||||
var defaultServerConfig = ServerConfig{
|
||||
Address: "",
|
||||
HTTPSAddr: "",
|
||||
|
@ -6,18 +6,6 @@
|
||||
|
||||
package ghttp
|
||||
|
||||
func (s *Server) SetDenyIps(ips []string) {
|
||||
s.config.DenyIps = ips
|
||||
}
|
||||
|
||||
func (s *Server) SetAllowIps(ips []string) {
|
||||
s.config.AllowIps = ips
|
||||
}
|
||||
|
||||
func (s *Server) SetDenyRoutes(routes []string) {
|
||||
s.config.DenyRoutes = routes
|
||||
}
|
||||
|
||||
// 设置URI重写规则
|
||||
func (s *Server) SetRewrite(uri string, rewrite string) {
|
||||
s.config.Rewrites[uri] = rewrite
|
||||
|
@ -403,3 +403,44 @@ func Test_Params_Basic(t *testing.T) {
|
||||
gtest.Assert(client.PostContent("/struct-with-base", `id=1&name=john&password1=123&password2=456`), "1john1234561john123456")
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Params_Priority(t *testing.T) {
|
||||
p := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
s.BindHandler("/query", func(r *ghttp.Request) {
|
||||
r.Response.Write(r.GetQuery("a"))
|
||||
})
|
||||
s.BindHandler("/post", func(r *ghttp.Request) {
|
||||
r.Response.Write(r.GetPost("a"))
|
||||
})
|
||||
s.BindHandler("/form", func(r *ghttp.Request) {
|
||||
r.Response.Write(r.GetForm("a"))
|
||||
})
|
||||
s.BindHandler("/request", func(r *ghttp.Request) {
|
||||
r.Response.Write(r.Get("a"))
|
||||
})
|
||||
s.BindHandler("/request-map", func(r *ghttp.Request) {
|
||||
r.Response.Write(r.GetMap(g.Map{
|
||||
"a": 1,
|
||||
"b": 2,
|
||||
}))
|
||||
})
|
||||
s.SetPort(p)
|
||||
s.SetDumpRouteMap(false)
|
||||
s.Start()
|
||||
defer s.Shutdown()
|
||||
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
gtest.Case(t, func() {
|
||||
prefix := fmt.Sprintf("http://127.0.0.1:%d", p)
|
||||
client := ghttp.NewClient()
|
||||
client.SetPrefix(prefix)
|
||||
|
||||
gtest.Assert(client.GetContent("/query?a=1", "a=100"), "100")
|
||||
gtest.Assert(client.PostContent("/post?a=1", "a=100"), "100")
|
||||
gtest.Assert(client.PostContent("/form?a=1", "a=100"), "100")
|
||||
gtest.Assert(client.PutContent("/form?a=1", "a=100"), "100")
|
||||
gtest.Assert(client.GetContent("/request?a=1", "a=100"), "100")
|
||||
gtest.Assert(client.GetContent("/request-map?a=1&b=2&c=3", "a=100&b=200&c=300"), `{"a":"100","b":"200"}`)
|
||||
})
|
||||
}
|
||||
|
@ -16,7 +16,6 @@ import (
|
||||
"github.com/gogf/gf/test/gtest"
|
||||
)
|
||||
|
||||
// 基本路由功能测试
|
||||
func Test_Router_Basic(t *testing.T) {
|
||||
p := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
|
Loading…
Reference in New Issue
Block a user