改进ghttp传递给注册函数的参数,简化使用

This commit is contained in:
John
2018-01-02 15:52:32 +08:00
parent 762e2c8dea
commit d4f992bfc4
18 changed files with 167 additions and 123 deletions

View File

@ -15,7 +15,7 @@ import (
// 控制器基类
type Controller struct {
Server *ghttp.Server // Web Server对象
Request *ghttp.ClientRequest // 请求数据对象
Request *ghttp.Request // 请求数据对象
Response *ghttp.ServerResponse // 返回数据对象
Cookie *ghttp.Cookie // COOKIE操作对象
Session *ghttp.Session // SESSION操作对象
@ -23,11 +23,11 @@ type Controller struct {
}
// 控制器初始化接口方法
func (c *Controller) Init(s *ghttp.Server, r *ghttp.ClientRequest, w *ghttp.ServerResponse) {
c.Server = s
func (c *Controller) Init(r *ghttp.Request) {
c.Server = r.Server
c.Request = r
c.Response = w
c.View = NewView(w)
c.Response = r.Response
c.View = NewView(r.Response)
c.Cookie = r.Cookie
c.Session = r.Session
}

View File

@ -36,12 +36,12 @@ func (c *Client) SetTimeOut(t time.Duration) {
// GET请求
func (c *Client) Get(url string) (*ClientResponse, error) {
return c.Request("GET", url, []byte(""))
return c.DoRequest("GET", url, []byte(""))
}
// PUT请求
func (c *Client) Put(url, data string) (*ClientResponse, error) {
return c.Request("PUT", url, []byte(data))
return c.DoRequest("PUT", url, []byte(data))
}
// POST请求提交数据
@ -57,31 +57,31 @@ func (c *Client) Post(url, data string) (*ClientResponse, error) {
// DELETE请求
func (c *Client) Delete(url, data string) (*ClientResponse, error) {
return c.Request("DELETE", url, []byte(data))
return c.DoRequest("DELETE", url, []byte(data))
}
func (c *Client) Head(url, data string) (*ClientResponse, error) {
return c.Request("HEAD", url, []byte(data))
return c.DoRequest("HEAD", url, []byte(data))
}
func (c *Client) Patch(url, data string) (*ClientResponse, error) {
return c.Request("PATCH", url, []byte(data))
return c.DoRequest("PATCH", url, []byte(data))
}
func (c *Client) Connect(url, data string) (*ClientResponse, error) {
return c.Request("CONNECT", url, []byte(data))
return c.DoRequest("CONNECT", url, []byte(data))
}
func (c *Client) Options(url, data string) (*ClientResponse, error) {
return c.Request("OPTIONS", url, []byte(data))
return c.DoRequest("OPTIONS", url, []byte(data))
}
func (c *Client) Trace(url, data string) (*ClientResponse, error) {
return c.Request("TRACE", url, []byte(data))
return c.DoRequest("TRACE", url, []byte(data))
}
// 请求并返回response对象该方法支持二进制提交数据
func (c *Client) Request(method, url string, data []byte) (*ClientResponse, error) {
func (c *Client) DoRequest(method, url string, data []byte) (*ClientResponse, error) {
req, err := http.NewRequest(strings.ToUpper(method), url, bytes.NewReader(data))
if err != nil {
return nil, err
@ -97,42 +97,42 @@ func (c *Client) Request(method, url string, data []byte) (*ClientResponse, erro
func Get(url string) (*ClientResponse, error) {
return Request("GET", url, []byte(""))
return DoRequest("GET", url, []byte(""))
}
func Put(url, data string) (*ClientResponse, error) {
return Request("PUT", url, []byte(data))
return DoRequest("PUT", url, []byte(data))
}
func Post(url, data string) (*ClientResponse, error) {
return Request("PUT", url, []byte(data))
return DoRequest("PUT", url, []byte(data))
}
func Delete(url, data string) (*ClientResponse, error) {
return Request("DELETE", url, []byte(data))
return DoRequest("DELETE", url, []byte(data))
}
func Head(url, data string) (*ClientResponse, error) {
return Request("HEAD", url, []byte(data))
return DoRequest("HEAD", url, []byte(data))
}
func Patch(url, data string) (*ClientResponse, error) {
return Request("PATCH", url, []byte(data))
return DoRequest("PATCH", url, []byte(data))
}
func Connect(url, data string) (*ClientResponse, error) {
return Request("CONNECT", url, []byte(data))
return DoRequest("CONNECT", url, []byte(data))
}
func Options(url, data string) (*ClientResponse, error) {
return Request("OPTIONS", url, []byte(data))
return DoRequest("OPTIONS", url, []byte(data))
}
func Trace(url, data string) (*ClientResponse, error) {
return Request("TRACE", url, []byte(data))
return DoRequest("TRACE", url, []byte(data))
}
// 该方法支持二进制提交数据
func Request(method, url string, data []byte) (*ClientResponse, error) {
return NewClient().Request(method, url, data)
func DoRequest(method, url string, data []byte) (*ClientResponse, error) {
return NewClient().DoRequest(method, url, data)
}

View File

@ -10,6 +10,6 @@ package ghttp
// 控制器接口
type Controller interface {
Init(*Server, *ClientRequest, *ServerResponse)
Init(*Request)
Shut()
}

View File

@ -15,16 +15,18 @@ import (
)
// 请求对象
type ClientRequest struct {
type Request struct {
http.Request
getvals *url.Values // GET参数
Id uint64 // 请求id(唯一)
Cookie *Cookie // 与当前请求绑定的Cookie对象(并发安全)
Session *Session // 与当前请求绑定的Session对象(并发安全)
getvals *url.Values // GET参数
Id int // 请求id(唯一)
Server *Server // 请求关联的服务器对象
Cookie *Cookie // 与当前请求绑定的Cookie对象(并发安全)
Session *Session // 与当前请求绑定的Session对象(并发安全)
Response *ServerResponse // 对应请求的返回数据操作对象
}
// 获得指定名称的get参数列表
func (r *ClientRequest) GetQuery(k string) []string {
func (r *Request) GetQuery(k string) []string {
if r.getvals == nil {
values := r.URL.Query()
r.getvals = &values
@ -35,27 +37,27 @@ func (r *ClientRequest) GetQuery(k string) []string {
return nil
}
func (r *ClientRequest) GetQueryBool(k string) bool {
func (r *Request) GetQueryBool(k string) bool {
return gconv.Bool(r.GetQueryString(k))
}
func (r *ClientRequest) GetQueryInt(k string) int {
func (r *Request) GetQueryInt(k string) int {
return gconv.Int(r.GetQueryString(k))
}
func (r *ClientRequest) GetQueryUint(k string) uint {
func (r *Request) GetQueryUint(k string) uint {
return gconv.Uint(r.GetQueryString(k))
}
func (r *ClientRequest) GetQueryFloat32(k string) float32 {
func (r *Request) GetQueryFloat32(k string) float32 {
return gconv.Float32(r.GetQueryString(k))
}
func (r *ClientRequest) GetQueryFloat64(k string) float64 {
func (r *Request) GetQueryFloat64(k string) float64 {
return gconv.Float64(r.GetQueryString(k))
}
func (r *ClientRequest) GetQueryString(k string) string {
func (r *Request) GetQueryString(k string) string {
v := r.GetQuery(k)
if v == nil {
return ""
@ -64,12 +66,12 @@ func (r *ClientRequest) GetQueryString(k string) string {
}
}
func (r *ClientRequest) GetQueryArray(k string) []string {
func (r *Request) GetQueryArray(k string) []string {
return r.GetQuery(k)
}
// 获取指定键名的关联数组,并且给定当指定键名不存在时的默认值
func (r *ClientRequest) GetQueryMap(defaultMap map[string]string) map[string]string {
func (r *Request) GetQueryMap(defaultMap map[string]string) map[string]string {
m := make(map[string]string)
for k, v := range defaultMap {
v2 := r.GetQueryArray(k)
@ -83,34 +85,34 @@ func (r *ClientRequest) GetQueryMap(defaultMap map[string]string) map[string]str
}
// 获得post参数
func (r *ClientRequest) GetPost(k string) []string {
func (r *Request) GetPost(k string) []string {
if v, ok := r.PostForm[k]; ok {
return v
}
return nil
}
func (r *ClientRequest) GetPostBool(k string) bool {
func (r *Request) GetPostBool(k string) bool {
return gconv.Bool(r.GetPostString(k))
}
func (r *ClientRequest) GetPostInt(k string) int {
func (r *Request) GetPostInt(k string) int {
return gconv.Int(r.GetPostString(k))
}
func (r *ClientRequest) GetPostUint(k string) uint {
func (r *Request) GetPostUint(k string) uint {
return gconv.Uint(r.GetPostString(k))
}
func (r *ClientRequest) GetPostFloat32(k string) float32 {
func (r *Request) GetPostFloat32(k string) float32 {
return gconv.Float32(r.GetPostString(k))
}
func (r *ClientRequest) GetPostFloat64(k string) float64 {
func (r *Request) GetPostFloat64(k string) float64 {
return gconv.Float64(r.GetPostString(k))
}
func (r *ClientRequest) GetPostString(k string) string {
func (r *Request) GetPostString(k string) string {
v := r.GetPost(k)
if v == nil {
return ""
@ -119,13 +121,13 @@ func (r *ClientRequest) GetPostString(k string) string {
}
}
func (r *ClientRequest) GetPostArray(k string) []string {
func (r *Request) GetPostArray(k string) []string {
return r.GetPost(k)
}
// 获取指定键名的关联数组,并且给定当指定键名不存在时的默认值
// 需要注意的是如果其中一个字段为数组形式那么只会返回第一个元素如果需要获取全部的元素请使用GetPostArray获取特定字段内容
func (r *ClientRequest) GetPostMap(defaultMap map[string]string) map[string]string {
func (r *Request) GetPostMap(defaultMap map[string]string) map[string]string {
m := make(map[string]string)
for k, v := range defaultMap {
if v2, ok := r.PostForm[k]; ok {
@ -138,7 +140,7 @@ func (r *ClientRequest) GetPostMap(defaultMap map[string]string) map[string]stri
}
// 获得post或者get提交的参数如果有同名参数那么按照get->post优先级进行覆盖
func (r *ClientRequest) GetRequest(k string) []string {
func (r *Request) GetRequest(k string) []string {
v := r.GetQuery(k)
if v == nil {
return r.GetPost(k)
@ -146,7 +148,7 @@ func (r *ClientRequest) GetRequest(k string) []string {
return v
}
func (r *ClientRequest) GetRequestString(k string) string {
func (r *Request) GetRequestString(k string) string {
v := r.GetRequest(k)
if v == nil {
return ""
@ -155,33 +157,33 @@ func (r *ClientRequest) GetRequestString(k string) string {
}
}
func (r *ClientRequest) GetRequestBool(k string) bool {
func (r *Request) GetRequestBool(k string) bool {
return gconv.Bool(r.GetRequestString(k))
}
func (r *ClientRequest) GetRequestInt(k string) int {
func (r *Request) GetRequestInt(k string) int {
return gconv.Int(r.GetRequestString(k))
}
func (r *ClientRequest) GetRequestUint(k string) uint {
func (r *Request) GetRequestUint(k string) uint {
return gconv.Uint(r.GetRequestString(k))
}
func (r *ClientRequest) GetRequestFloat32(k string) float32 {
func (r *Request) GetRequestFloat32(k string) float32 {
return gconv.Float32(r.GetRequestString(k))
}
func (r *ClientRequest) GetRequestFloat64(k string) float64 {
func (r *Request) GetRequestFloat64(k string) float64 {
return gconv.Float64(r.GetRequestString(k))
}
func (r *ClientRequest) GetRequestArray(k string) []string {
func (r *Request) GetRequestArray(k string) []string {
return r.GetRequest(k)
}
// 获取指定键名的关联数组,并且给定当指定键名不存在时的默认值
// 需要注意的是如果其中一个字段为数组形式那么只会返回第一个元素如果需要获取全部的元素请使用GetRequestArray获取特定字段内容
func (r *ClientRequest) GetRequestMap(defaultMap map[string]string) map[string]string {
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)
@ -195,13 +197,13 @@ func (r *ClientRequest) GetRequestMap(defaultMap map[string]string) map[string]s
}
// 获取原始请求输入字符串
func (r *ClientRequest) GetRaw() []byte {
func (r *Request) GetRaw() []byte {
result, _ := ioutil.ReadAll(r.Body)
return result
}
// 获取原始json请求输入字符串并解析为json对象
func (r *ClientRequest) GetJson() *gjson.Json {
func (r *Request) GetJson() *gjson.Json {
data := r.GetRaw()
if data != nil {
if j, err := gjson.DecodeToJson(data); err == nil {

View File

@ -19,9 +19,9 @@ import (
"crypto/tls"
"path/filepath"
"gitee.com/johng/gf/g/util/gutil"
"gitee.com/johng/gf/g/container/gmap"
"gitee.com/johng/gf/g/net/grouter"
"sync/atomic"
"gitee.com/johng/gf/g/util/gidgen"
"gitee.com/johng/gf/g/container/gmap"
)
const (
@ -38,9 +38,9 @@ type Server struct {
server http.Server // 底层http server对象
config ServerConfig // 配置对象
status int8 // 当前服务器状态(0未启动1运行中)
served uint64 // 已服务的请求数(递增)
handlerMap HandlerMap // 所有注册的回调函数
methodsMap map[string]bool // 所有支持的HTTP Method
idgen *gidgen.Gen // 请求ID生成器
Router *grouter.Router // 路由管理对象
}
@ -55,7 +55,7 @@ type HandlerItem struct {
}
// http注册函数
type HandlerFunc func(*Server, *ClientRequest, *ServerResponse)
type HandlerFunc func(*Request)
// Server表用以存储和检索名称与Server对象之间的关联关系
var serverMapping = gmap.NewStringInterfaceMap()
@ -74,6 +74,7 @@ func GetServer(names...string) (*Server) {
name : name,
handlerMap : make(HandlerMap),
methodsMap : make(map[string]bool),
idgen : gidgen.New(20000),
Router : grouter.New(),
}
for _, v := range strings.Split(gHTTP_METHODS, ",") {
@ -248,11 +249,6 @@ func (s *Server)SetServerRoot(root string) error {
return nil
}
// 服务请求数原子递增
func (s *Server) increServed() uint64 {
return atomic.AddUint64(&s.served, 1)
}
// 生成回调方法查询的Key
func (s *Server) handlerKey(domain, method, pattern string) string {
return strings.ToUpper(method) + ":" + pattern + "@" + strings.ToLower(domain)
@ -355,7 +351,7 @@ func (s *Server)BindObject(pattern string, obj interface{}) error {
for i := 0; i < v.NumMethod(); i++ {
name := t.Method(i).Name
key := s.appendMethodNameToUriWithPattern(pattern, name)
m[key] = HandlerItem{nil, "", v.Method(i).Interface().(func(*Server, *ClientRequest, *ServerResponse))}
m[key] = HandlerItem{nil, "", v.Method(i).Interface().(func(*Request))}
}
return s.bindHandlerByMap(m)
}
@ -372,7 +368,7 @@ func (s *Server)BindObjectRest(pattern string, obj interface{}) error {
continue
}
key := name + ":" + pattern
m[key] = HandlerItem{nil, "", v.Method(i).Interface().(func(*Server, *ClientRequest, *ServerResponse))}
m[key] = HandlerItem{nil, "", v.Method(i).Interface().(func(*Request))}
}
return s.bindHandlerByMap(m)
}

View File

@ -29,7 +29,7 @@ type Cookie struct {
mu sync.RWMutex // 并发安全互斥锁
data map[string]CookieItem // 数据项
domain string // 默认的cookie域名
request *ClientRequest // 所属HTTP请求对象
request *Request // 所属HTTP请求对象
response *ServerResponse // 所属HTTP返回对象
}
@ -45,7 +45,7 @@ type CookieItem struct {
var cookies = gmap.NewUintInterfaceMap()
// 创建一个cookie对象与传入的请求对应
func NewCookie(r *ClientRequest, w *ServerResponse) *Cookie {
func NewCookie(r *Request) *Cookie {
if r := GetCookie(r.Id); r != nil {
return r
}
@ -53,7 +53,7 @@ func NewCookie(r *ClientRequest, w *ServerResponse) *Cookie {
data : make(map[string]CookieItem),
domain : defaultDomain(r),
request : r,
response : w,
response : r.Response,
}
c.init()
cookies.Set(uint(r.Id), c)
@ -61,7 +61,7 @@ func NewCookie(r *ClientRequest, w *ServerResponse) *Cookie {
}
// 获取一个已经存在的Cookie对象
func GetCookie(requestid uint64) *Cookie {
func GetCookie(requestid int) *Cookie {
if r := cookies.Get(uint(requestid)); r != nil {
return r.(*Cookie)
}
@ -69,7 +69,7 @@ func GetCookie(requestid uint64) *Cookie {
}
// 获取默认的domain参数
func defaultDomain(r *ClientRequest) string {
func defaultDomain(r *Request) string {
return strings.Split(r.Host, ":")[0]
}

View File

@ -36,17 +36,19 @@ func (s *Server)handleRequest(w http.ResponseWriter, r *http.Request) {
if err == nil && strings.Compare(uri, result) != 0 {
r.URL, _ = r.URL.Parse(result)
}
// 构造请求/返回参数对象
request := &ClientRequest{}
response := &ServerResponse{}
request.Id = s.increServed()
request.Request = *r
response.ResponseWriter = w
// 构造请求参数对象
request := &Request{
Id : s.idgen.Int(),
Request : *r,
Response : &ServerResponse {
ResponseWriter : w,
},
}
if h := s.getHandler(gDEFAULT_DOMAIN, r.Method, r.URL.Path); h != nil {
s.callHandler(h, request, response)
s.callHandler(h, request)
} else {
if h := s.getHandler(strings.Split(r.Host, ":")[0], r.Method, r.URL.Path); h != nil {
s.callHandler(h, request, response)
s.callHandler(h, request)
} else {
s.serveFile(w, r)
}
@ -54,33 +56,33 @@ func (s *Server)handleRequest(w http.ResponseWriter, r *http.Request) {
}
// 初始化控制器
func (s *Server)callHandler(h *HandlerItem, r *ClientRequest, w *ServerResponse) {
func (s *Server)callHandler(h *HandlerItem, r *Request) {
// 会话处理
r.Cookie = NewCookie(r, w)
r.Cookie = NewCookie(r)
r.Session = GetSession(r.Cookie.SessionId())
// 请求处理
if h.faddr == nil {
// 新建一个控制器对象处理请求
c := reflect.New(h.ctype)
c.MethodByName("Init").Call([]reflect.Value{reflect.ValueOf(s), reflect.ValueOf(r), reflect.ValueOf(w)})
c.MethodByName("Init").Call([]reflect.Value{reflect.ValueOf(r)})
c.MethodByName(h.fname).Call(nil)
c.MethodByName("Shut").Call(nil)
} else {
// 直接调用注册的方法处理请求
h.faddr(s, r, w)
h.faddr(r)
}
// 路由规则打包
if buffer, err := s.Router.Patch(w.Buffer()); err == nil {
w.ClearBuffer()
w.Write(buffer)
if buffer, err := s.Router.Patch(r.Response.Buffer()); err == nil {
r.Response.ClearBuffer()
r.Response.Write(buffer)
}
// 输出Cookie
r.Cookie.Output()
// 输出缓冲区
w.OutputBuffer()
r.Response.OutputBuffer()
// 关闭当前会话的Cookie
go r.Cookie.Close()

View File

@ -3,8 +3,8 @@
// 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 gconv
import (

52
g/util/gidgen/gidgen.go Normal file
View File

@ -0,0 +1,52 @@
// 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.
// 唯一ID生成器
// 内部采用了通道+缓冲池来实现高效的ID递增生成
// 非常适合高并发下使用
package gidgen
import "math"
// ID生成器管理对象
type Gen struct {
ch chan uint
}
// 创建一个ID生成器并给定ID池大小
func New (bufsize int) *Gen {
g := &Gen {
ch : make(chan uint, bufsize),
}
go g.startLoop()
return g
}
// 内部循环当最大值使用完之后重新从1开始获取
func (g *Gen) startLoop() {
for {
// 当ch达到缓冲池大小会阻塞只要有线程取出值再立即填充
for i := uint(1); i < uint(math.MaxUint64); i++ {
g.ch <- i
}
}
}
// 从池中获取一个ID返回(uint)
func (g *Gen) Uint() uint {
return <- g.ch
}
// 从池中获取一个ID返回(int)
func (g *Gen) Int() int {
i := int(<- g.ch & 0x7FFFFFFFFFFFFFFF)
// 可能是int与uint之间的临界点
if i == 0 {
i = int(<- g.ch & 0x7FFFFFFFFFFFFFFF)
}
return i
}