mirror of
https://gitee.com/johng/gf
synced 2026-06-07 02:12:11 +08:00
ghttp cookie开发,控制器增加反射,正在调试控制器指针对象反射功能
This commit is contained in:
@ -4,5 +4,5 @@ import "gitee.com/johng/gf/g/net/ghttp"
|
||||
|
||||
// 控制器基类
|
||||
type Controller struct {
|
||||
ghttp.Controller
|
||||
ghttp.ControllerBase
|
||||
}
|
||||
|
||||
@ -1,8 +0,0 @@
|
||||
package gmvc
|
||||
|
||||
import "gitee.com/johng/gf/g/net/ghttp"
|
||||
|
||||
// 基于RESTful格式的控制器
|
||||
type Controller_Rest struct {
|
||||
ghttp.ControllerRest
|
||||
}
|
||||
@ -1,39 +1,8 @@
|
||||
package ghttp
|
||||
|
||||
import "gitee.com/johng/gf/g/net/gsession"
|
||||
|
||||
// 控制器基类
|
||||
type Controller struct {
|
||||
|
||||
// 控制器接口
|
||||
type Controller interface {
|
||||
Init()
|
||||
Shut()
|
||||
}
|
||||
|
||||
func (c *Controller) Get(*ClientRequest, *ServerResponse) {}
|
||||
func (c *Controller) Put(*ClientRequest, *ServerResponse) {}
|
||||
func (c *Controller) Post(*ClientRequest, *ServerResponse) {}
|
||||
func (c *Controller) Delete(*ClientRequest, *ServerResponse) {}
|
||||
func (c *Controller) Head(*ClientRequest, *ServerResponse) {}
|
||||
func (c *Controller) Patch(*ClientRequest, *ServerResponse) {}
|
||||
func (c *Controller) Connect(*ClientRequest, *ServerResponse) {}
|
||||
func (c *Controller) Options(*ClientRequest, *ServerResponse) {}
|
||||
func (c *Controller) Trace(*ClientRequest, *ServerResponse) {}
|
||||
|
||||
// 获取当前请求的session对象
|
||||
func (c *Controller) Session(r *ClientRequest, w *ServerResponse) *gsession.Session {
|
||||
sessionid := ""
|
||||
if r, err := r.Cookie("gfsessionid"); err == nil {
|
||||
sessionid = r.Value
|
||||
} else {
|
||||
sessionid = gsession.Id()
|
||||
}
|
||||
return gsession.Get(sessionid)
|
||||
}
|
||||
|
||||
// 请求初始化时的回调函数
|
||||
func (c *Controller) __init(r *ClientRequest, w *ServerResponse) {
|
||||
|
||||
}
|
||||
|
||||
// 请求结束时的回调函数
|
||||
func (c *Controller) __shut(r *ClientRequest, w *ServerResponse) {
|
||||
|
||||
}
|
||||
30
g/net/ghttp/http_controller_base.go
Normal file
30
g/net/ghttp/http_controller_base.go
Normal file
@ -0,0 +1,30 @@
|
||||
package ghttp
|
||||
|
||||
import (
|
||||
"gitee.com/johng/gf/g/net/gsession"
|
||||
)
|
||||
|
||||
// 控制器基类
|
||||
type ControllerBase struct {
|
||||
Request *ClientRequest
|
||||
Response *ServerResponse
|
||||
Cookie *Cookie
|
||||
Session *gsession.Session
|
||||
}
|
||||
|
||||
// 控制器初始化
|
||||
func (c *ControllerBase) Init() {
|
||||
c.Cookie = NewCookie(c.Request, c.Response)
|
||||
if r := c.Cookie.Get("gfsessionid"); r != "" {
|
||||
c.Session = gsession.Get(r)
|
||||
} else {
|
||||
c.Session = gsession.Get(gsession.Id())
|
||||
}
|
||||
}
|
||||
|
||||
// 控制器结束请求
|
||||
func (c *ControllerBase) Shut() {
|
||||
c.Cookie.Output()
|
||||
}
|
||||
|
||||
|
||||
@ -1,14 +0,0 @@
|
||||
package ghttp
|
||||
|
||||
// RESTful控制器接口
|
||||
type ControllerRest interface {
|
||||
Get(*ClientRequest, *ServerResponse)
|
||||
Put(*ClientRequest, *ServerResponse)
|
||||
Post(*ClientRequest, *ServerResponse)
|
||||
Delete(*ClientRequest, *ServerResponse)
|
||||
Head(*ClientRequest, *ServerResponse)
|
||||
Patch(*ClientRequest, *ServerResponse)
|
||||
Connect(*ClientRequest, *ServerResponse)
|
||||
Options(*ClientRequest, *ServerResponse)
|
||||
Trace(*ClientRequest, *ServerResponse)
|
||||
}
|
||||
@ -9,6 +9,8 @@ import (
|
||||
"log"
|
||||
"sync"
|
||||
"errors"
|
||||
"reflect"
|
||||
"gitee.com/johng/gf/g/util/gutil"
|
||||
"gitee.com/johng/gf/g/container/gmap"
|
||||
)
|
||||
|
||||
@ -30,8 +32,11 @@ type Server struct {
|
||||
// 域名、URI与回调函数的绑定记录表
|
||||
type HandlerMap map[string]HandlerFunc
|
||||
|
||||
// http回调函数
|
||||
type HandlerFunc func(*ClientRequest, *ServerResponse)
|
||||
// http回调函数信息
|
||||
type HandlerFunc struct {
|
||||
ctype reflect.Type // 控制器类型
|
||||
fname string // 回调方法名称
|
||||
}
|
||||
|
||||
// Server表,用以存储和检索名称与Server对象之间的关联关系
|
||||
var serverMapping *gmap.StringInterfaceMap = gmap.NewStringInterfaceMap()
|
||||
@ -224,12 +229,12 @@ func (s *Server) setHandler(domain, method, pattern string, handler HandlerFunc)
|
||||
}
|
||||
|
||||
// 查询请求处理方法
|
||||
func (s *Server) getHandler(domain, method, pattern string) HandlerFunc {
|
||||
func (s *Server) getHandler(domain, method, pattern string) *HandlerFunc {
|
||||
s.hmu.RLock()
|
||||
defer s.hmu.RUnlock()
|
||||
key := s.handlerKey(domain, method, pattern)
|
||||
if f, ok := s.handlerMap[key]; ok {
|
||||
return f
|
||||
return &f
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -237,14 +242,10 @@ func (s *Server) getHandler(domain, method, pattern string) HandlerFunc {
|
||||
// 绑定URI到操作函数/方法
|
||||
// pattern的格式形如:/user/list, put:/user, delete:/user, post:/user@johng.cn
|
||||
// 支持RESTful的请求格式,具体业务逻辑由绑定的处理方法来执行
|
||||
func (s *Server)BindHandler(pattern string, handler HandlerFunc) error {
|
||||
func (s *Server)bindHandler(pattern string, handler HandlerFunc) error {
|
||||
if s.status == 1 {
|
||||
return errors.New("server handlers cannot be changed while running")
|
||||
}
|
||||
|
||||
s.hmu.Lock()
|
||||
defer s.hmu.Unlock()
|
||||
|
||||
uri := ""
|
||||
domain := gDEFAULT_DOMAIN
|
||||
method := "all"
|
||||
@ -267,28 +268,41 @@ func (s *Server)BindHandler(pattern string, handler HandlerFunc) error {
|
||||
}
|
||||
|
||||
// 通过映射数组绑定URI到操作函数/方法
|
||||
func (s *Server)BindHandlerByMap(m HandlerMap) error {
|
||||
for p, f := range m {
|
||||
if err := s.BindHandler(p, f); err != nil {
|
||||
func (s *Server)bindHandlerByMap(m HandlerMap) error {
|
||||
for p, h := range m {
|
||||
if err := s.bindHandler(p, h); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 绑定控制器,控制器需要继承gmvc.Controller对象并实现需要的REST方法
|
||||
func (s *Server)BindControllerRest(uri string, c ControllerRest) error {
|
||||
return s.BindHandlerByMap(HandlerMap{
|
||||
"GET:" + uri : c.Get,
|
||||
"PUT:" + uri : c.Put,
|
||||
"POST:" + uri : c.Post,
|
||||
"DELETE:" + uri : c.Delete,
|
||||
"PATCH:" + uri : c.Patch,
|
||||
"HEAD:" + uri : c.Head,
|
||||
"CONNECT:" + uri : c.Connect,
|
||||
"OPTIONS:" + uri : c.Options,
|
||||
"TRACE:" + uri : c.Trace,
|
||||
})
|
||||
// 绑定方法,pattern支持http method
|
||||
// pattern的格式形如:/user/list, put:/user, delete:/user
|
||||
func (s *Server)BindMethod(pattern string, c Controller, method string) error {
|
||||
return s.bindHandler(pattern, HandlerFunc{reflect.ValueOf(c).Type(), method})
|
||||
}
|
||||
|
||||
|
||||
// 绑定控制器,控制器需要实现gmvc.Controller接口
|
||||
func (s *Server)BindController(uri string, c Controller) error {
|
||||
// 遍历控制器,获取方法列表,并构造成uri
|
||||
m := make(HandlerMap)
|
||||
v := reflect.ValueOf(c)
|
||||
t := v.Type()
|
||||
for i := 0; i < v.NumMethod(); i++ {
|
||||
key := strings.TrimRight(uri, "/") + "/"
|
||||
name := t.Method(i).Name
|
||||
if name == "Init" || name == "Shut" {
|
||||
continue
|
||||
}
|
||||
for i := 0; i < len(name); i++ {
|
||||
if i > 0 && gutil.IsLetterUpper(name[i]) {
|
||||
key += "-"
|
||||
}
|
||||
key += strings.ToLower(string(name[i]))
|
||||
}
|
||||
m[key] = HandlerFunc{t, name}
|
||||
}
|
||||
//fmt.Println(m)
|
||||
return s.bindHandlerByMap(m)
|
||||
}
|
||||
|
||||
75
g/net/ghttp/http_server_cookie.go
Normal file
75
g/net/ghttp/http_server_cookie.go
Normal file
@ -0,0 +1,75 @@
|
||||
package ghttp
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// cookie对象
|
||||
type Cookie struct {
|
||||
mu sync.RWMutex // 并发安全互斥锁
|
||||
data map[string]CookieItem // 数据项
|
||||
request *ClientRequest // 所属HTTP请求对象
|
||||
response *ServerResponse // 所属HTTP返回对象
|
||||
}
|
||||
|
||||
// cookie项
|
||||
type CookieItem struct {
|
||||
value string
|
||||
domain string
|
||||
path string
|
||||
maxage int
|
||||
}
|
||||
|
||||
// 初始化cookie对象
|
||||
func NewCookie(r *ClientRequest, w *ServerResponse) *Cookie {
|
||||
return &Cookie{
|
||||
data : make(map[string]CookieItem),
|
||||
request : r,
|
||||
response : w,
|
||||
}
|
||||
}
|
||||
|
||||
// 从请求流中初始化
|
||||
func (c *Cookie) init() {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
for _, v := range c.request.Cookies() {
|
||||
c.data[v.Name] = CookieItem {
|
||||
v.Value, v.Domain, v.Path, v.MaxAge,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 设置cookie
|
||||
func (c *Cookie) Set(key, value, domain, path string, maxage int) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
c.data[key] = CookieItem {
|
||||
value, domain, path, maxage,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Cookie) Get(key string) string {
|
||||
c.mu.RLock()
|
||||
defer c.mu.RUnlock()
|
||||
if r, ok := c.data[key]; ok {
|
||||
return r.value
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (c *Cookie) Remove(key string) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
delete(c.data, key)
|
||||
}
|
||||
|
||||
// 输出到客户端
|
||||
func (c *Cookie) Output() {
|
||||
c.mu.RLock()
|
||||
defer c.mu.RUnlock()
|
||||
for k, v := range c.data {
|
||||
http.SetCookie(c.response.ResponseWriter, &http.Cookie{Name: k, Value: v.value, Domain: v.domain, Path: v.path, MaxAge: v.maxage})
|
||||
}
|
||||
}
|
||||
@ -31,30 +31,15 @@ func (s *Server) Domain(domain string) *Domain {
|
||||
return d
|
||||
}
|
||||
|
||||
// 在当前域名中绑定回调函数
|
||||
func (d *Domain) BindHandler(pattern string, handler HandlerFunc) error {
|
||||
for domain, _ := range d.m {
|
||||
if err := d.s.BindHandler(pattern + "@" + domain, handler); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
// 绑定方法
|
||||
func (d *Domain) BindMethod(pattern string, c Controller, method string) error {
|
||||
return d.s.BindMethod(pattern, c, method)
|
||||
}
|
||||
|
||||
// 批量绑定
|
||||
func (d *Domain) BindHandlerByMap(m HandlerMap) error {
|
||||
for p, f := range m {
|
||||
if err := d.s.BindHandler(p, f); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 绑定REST控制器
|
||||
func (d *Domain) BindControllerRest(uri string, c ControllerRest) error {
|
||||
// 绑定控制器
|
||||
func (d *Domain) BindController(uri string, c Controller) error {
|
||||
for domain, _ := range d.m {
|
||||
if err := d.s.BindControllerRest(uri + "@" + domain, c); err != nil {
|
||||
if err := d.s.BindController(uri + "@" + domain, c); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,6 +10,7 @@ import (
|
||||
"path/filepath"
|
||||
"gitee.com/johng/gf/g/os/gfile"
|
||||
"gitee.com/johng/gf/g/encoding/ghtml"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// 默认HTTP Server处理入口,http包底层默认使用了gorutine异步处理请求,所以这里不再异步执行
|
||||
@ -19,21 +20,32 @@ func (s *Server)defaultHttpHandle(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// 执行处理HTTP请求
|
||||
func (s *Server)handleRequest(w http.ResponseWriter, r *http.Request) {
|
||||
request := ClientRequest{}
|
||||
response := ServerResponse {server : s}
|
||||
request := &ClientRequest{}
|
||||
response := &ServerResponse {server : s}
|
||||
request.Request = *r
|
||||
response.ResponseWriter = w
|
||||
if f := s.getHandler(gDEFAULT_DOMAIN, r.Method, r.URL.Path); f != nil {
|
||||
f(&request, &response)
|
||||
if h := s.getHandler(gDEFAULT_DOMAIN, r.Method, r.URL.Path); h != nil {
|
||||
s.initController(h, request, response)
|
||||
} else {
|
||||
if f := s.getHandler(strings.Split(r.Host, ":")[0], r.Method, r.URL.Path); f != nil {
|
||||
f(&request, &response)
|
||||
if h := s.getHandler(strings.Split(r.Host, ":")[0], r.Method, r.URL.Path); h != nil {
|
||||
s.initController(h, request, response)
|
||||
} else {
|
||||
s.serveFile(w, r)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化控制器
|
||||
func (s *Server)initController(h *HandlerFunc, r *ClientRequest, w *ServerResponse) {
|
||||
c := reflect.Indirect(reflect.New(h.ctype)).Elem()
|
||||
fmt.Println(c.String())
|
||||
c.FieldByName("Request").Set(reflect.ValueOf(r))
|
||||
c.FieldByName("Response").Set(reflect.ValueOf(w))
|
||||
c.MethodByName("Init").Call(nil)
|
||||
c.MethodByName(h.fname).Call(nil)
|
||||
c.MethodByName("Shut").Call(nil)
|
||||
}
|
||||
|
||||
// 处理静态文件请求
|
||||
func (s *Server)serveFile(w http.ResponseWriter, r *http.Request) {
|
||||
uri := r.URL.String()
|
||||
|
||||
@ -47,45 +47,40 @@ func cacheKey(sessionid string) string {
|
||||
|
||||
// 获取sessionid
|
||||
func (s *Session) Id () string {
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
id := s.id
|
||||
s.updateExpire()
|
||||
return id
|
||||
go s.updateExpire()
|
||||
return s.id
|
||||
}
|
||||
|
||||
// 获取当前session所有数据
|
||||
func (s *Session) Data () map[string]interface{} {
|
||||
m := *s.data.Clone()
|
||||
s.updateExpire()
|
||||
return m
|
||||
go s.updateExpire()
|
||||
return *s.data.Clone()
|
||||
}
|
||||
|
||||
// 设置session过期间隔
|
||||
// 设置session过期间隔(秒)
|
||||
func (s *Session) SetExpire (expire int) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
go s.updateExpire()
|
||||
s.expire = expire
|
||||
s.updateExpire()
|
||||
}
|
||||
|
||||
// 设置session
|
||||
func (s *Session) Set (k string, v interface{}) {
|
||||
go s.updateExpire()
|
||||
s.data.Set(k, v)
|
||||
s.updateExpire()
|
||||
}
|
||||
|
||||
// 获取session
|
||||
func (s *Session) Get (k string) interface{} {
|
||||
r := s.data.Get(k)
|
||||
s.updateExpire()
|
||||
return r
|
||||
go s.updateExpire()
|
||||
return s.data.Get(k)
|
||||
}
|
||||
|
||||
// 删除session
|
||||
func (s *Session) Remove (k string) {
|
||||
go s.updateExpire()
|
||||
s.data.Remove(k)
|
||||
s.updateExpire()
|
||||
}
|
||||
|
||||
// 更新过期时间
|
||||
|
||||
@ -15,5 +15,19 @@ func StringInArray (a []string, s string) bool {
|
||||
return StringSearch(a, s) != -1
|
||||
}
|
||||
|
||||
// 判断给定字符是否小写
|
||||
func IsLetterLower(b byte) bool {
|
||||
if b >= byte('a') && b <= byte('z') {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// 判断给定字符是否大写
|
||||
func IsLetterUpper(b byte) bool {
|
||||
if b >= byte('A') && b <= byte('Z') {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
@ -2,14 +2,11 @@ package user
|
||||
|
||||
import (
|
||||
"gitee.com/johng/gf/g/net/ghttp"
|
||||
"html/template"
|
||||
"fmt"
|
||||
"gitee.com/johng/gf/g/os/gfile"
|
||||
"gitee.com/johng/gf/g/frame/gmvc"
|
||||
)
|
||||
|
||||
// 定义业务相关的控制器对象
|
||||
type Controller_User struct {
|
||||
type ControllerUser struct {
|
||||
gmvc.Controller
|
||||
}
|
||||
|
||||
@ -19,22 +16,21 @@ func Add(i1, i2 int) int {
|
||||
|
||||
// 初始化控制器对象,并绑定操作到Web Server
|
||||
func init() {
|
||||
u := &Controller_User{}
|
||||
ghttp.GetServer("johng").Domain("localhost").BindHandler("/user/info", u.Info)
|
||||
//ghttp.GetServer("johng").Domain("localhost").BindHandler("/user", u.Info)
|
||||
ghttp.GetServer("johng").BindController("/user", &ControllerUser{})
|
||||
}
|
||||
|
||||
// 定义操作逻辑
|
||||
func (cu *Controller_User) Info(r *ghttp.ClientRequest, w *ghttp.ServerResponse) {
|
||||
r.c
|
||||
//w.Write([]byte("user information page"))
|
||||
t, err := template.New("test").Funcs(template.FuncMap{"add": Add}).Parse(gfile.GetContents("/home/john/Workspace/Go/GOPATH/src/gitee.com/johng/gf/geg/frame/mvc/view/user/info.tpl"))
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
t.Execute(w.ResponseWriter, map[string]string{
|
||||
"name" : "john",
|
||||
})
|
||||
func (cu *ControllerUser) Info() {
|
||||
cu.Response.Write([]byte("user information page"))
|
||||
//t, err := template.New("test").Funcs(template.FuncMap{"add": Add}).Parse(gfile.GetContents("/home/john/Workspace/Go/GOPATH/src/gitee.com/johng/gf/geg/frame/mvc/view/user/info.tpl"))
|
||||
//if err != nil {
|
||||
// fmt.Println(err)
|
||||
//}
|
||||
//
|
||||
//t.Execute(w.ResponseWriter, map[string]string{
|
||||
// "name" : "john",
|
||||
//})
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1,26 +1,28 @@
|
||||
package main
|
||||
import (
|
||||
"time"
|
||||
"fmt"
|
||||
"gitee.com/johng/gf/g/frame/gmvc"
|
||||
"gitee.com/johng/gf/g/net/gsession"
|
||||
)
|
||||
type User struct {
|
||||
Username, Password string
|
||||
RegTime time.Time
|
||||
|
||||
type B struct {
|
||||
Name string
|
||||
}
|
||||
func add(i1, i2 int) int {
|
||||
return i1 + i2 + 1
|
||||
|
||||
func (b B) Get() {
|
||||
fmt.Printf("b addr:%p\n", &b)
|
||||
}
|
||||
func main() {
|
||||
fmt.Println(gsession.Id())
|
||||
view := gmvc.NewView("/home/john/Workspace/Go/GOPATH/src/gitee.com/johng/gf/geg/frame/mvc/view/user/")
|
||||
tpl, _ := view.Template("info")
|
||||
tpl.BindFunc("add", add)
|
||||
fmt.Println(tpl.Parse(nil))
|
||||
//t, err := template.New("text").Funcs(template.FuncMap{"add":add}).Parse(`{{add 1 2}}`)
|
||||
//if err != nil {
|
||||
// panic(err)
|
||||
//}
|
||||
//t.Execute(os.Stdout, u)
|
||||
b := B{}
|
||||
b.Get()
|
||||
b.Get()
|
||||
|
||||
return
|
||||
//view := gmvc.NewView("/home/john/Workspace/Go/GOPATH/src/gitee.com/johng/gf/geg/frame/mvc/view/user/")
|
||||
//tpl, _ := view.Template("info")
|
||||
//tpl.BindFunc("add", add)
|
||||
//fmt.Println(tpl.Parse(nil))
|
||||
////t, err := template.New("text").Funcs(template.FuncMap{"add":add}).Parse(`{{add 1 2}}`)
|
||||
////if err != nil {
|
||||
//// panic(err)
|
||||
////}
|
||||
////t.Execute(os.Stdout, u)
|
||||
}
|
||||
Reference in New Issue
Block a user