Files
gf/g/net/ghttp/http_server_handler.go

147 lines
4.4 KiB
Go
Raw Normal View History

2017-12-29 16:03:30 +08:00
// 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.
2018-04-13 15:19:31 +08:00
// 请求处理.
2017-12-31 18:19:58 +08:00
2017-11-23 10:21:28 +08:00
package ghttp
import (
"os"
"fmt"
"sort"
"reflect"
"strings"
2017-11-23 10:21:28 +08:00
"net/url"
"net/http"
"path/filepath"
"gitee.com/johng/gf/g/os/gfile"
2018-04-11 16:06:45 +08:00
"gitee.com/johng/gf/g/encoding/ghtml"
2017-11-23 10:21:28 +08:00
)
2017-12-08 12:03:21 +08:00
// 默认HTTP Server处理入口http包底层默认使用了gorutine异步处理请求所以这里不再异步执行
2017-11-23 10:21:28 +08:00
func (s *Server)defaultHttpHandle(w http.ResponseWriter, r *http.Request) {
2017-12-08 12:03:21 +08:00
s.handleRequest(w, r)
}
// 执行处理HTTP请求
// 首先,查找是否有对应域名的处理接口配置;
// 其次,如果没有对应的自定义处理接口配置,那么走默认的域名处理接口配置;
// 最后,如果以上都没有找到处理接口,那么进行文件处理;
2017-12-08 12:03:21 +08:00
func (s *Server)handleRequest(w http.ResponseWriter, r *http.Request) {
2018-04-16 16:23:34 +08:00
// 去掉末尾的"/"号
if r.URL.Path != "/" {
r.URL.Path = strings.TrimRight(r.URL.Path, "/")
}
// 创建请求处理对象
2018-04-11 16:06:45 +08:00
request := newRequest(s, r, w)
// 事件 - BeforeServe
s.callHookHandler(request, "BeforeServe")
2018-04-11 12:05:25 +08:00
if h := s.getHandler(request); h != nil {
s.callHandler(h, request)
2017-11-23 10:21:28 +08:00
} else {
s.serveFile(request)
2018-04-11 12:05:25 +08:00
}
// 事件 - AfterServe
s.callHookHandler(request, "AfterServe")
// 事件 - BeforeOutput
s.callHookHandler(request, "BeforeOutput")
// 输出Cookie
request.Cookie.Output()
// 输出缓冲区
request.Response.OutputBuffer()
// 事件 - AfterOutput
s.callHookHandler(request, "AfterOutput")
// 将Request对象指针丢到队列中异步处理
s.closeQueue.PushBack(request)
2018-04-11 12:05:25 +08:00
}
// 初始化控制器
func (s *Server)callHandler(h *HandlerItem, r *Request) {
2017-12-26 10:13:49 +08:00
if h.faddr == nil {
// 新建一个控制器对象处理请求
2017-12-26 10:13:49 +08:00
c := reflect.New(h.ctype)
c.MethodByName("Init").Call([]reflect.Value{reflect.ValueOf(r)})
2018-04-16 16:50:26 +08:00
if !r.IsExited() {
2018-04-16 16:50:24 +08:00
c.MethodByName(h.fname).Call(nil)
}
c.MethodByName("Shut").Call([]reflect.Value{reflect.ValueOf(r)})
2017-12-26 10:13:49 +08:00
} else {
2018-04-16 16:50:26 +08:00
if !r.IsExited() {
2018-04-16 16:50:24 +08:00
h.faddr(r)
}
2017-12-26 10:13:49 +08:00
}
}
2017-11-23 10:21:28 +08:00
// 处理静态文件请求
func (s *Server)serveFile(r *Request) {
2017-11-23 10:21:28 +08:00
uri := r.URL.String()
if s.config.ServerRoot != "" {
// 获取文件的绝对路径
path := strings.TrimRight(s.config.ServerRoot, string(filepath.Separator))
path = path + uri
path = gfile.RealPath(path)
2017-12-28 15:21:25 +08:00
if path != "" {
s.doServeFile(r, path)
2017-11-23 10:21:28 +08:00
} else {
r.Response.WriteStatus(http.StatusNotFound)
2017-11-23 10:21:28 +08:00
}
} else {
r.Response.WriteStatus(http.StatusNotFound)
2017-11-23 10:21:28 +08:00
}
}
// http server静态文件处理
func (s *Server)doServeFile(r *Request, path string) {
2017-11-23 10:21:28 +08:00
f, err := os.Open(path)
if err != nil {
return
}
info, _ := f.Stat()
if info.IsDir() {
if len(s.config.IndexFiles) > 0 {
for _, file := range s.config.IndexFiles {
fpath := path + "/" + file
if gfile.Exists(fpath) {
f.Close()
s.doServeFile(r, fpath)
2017-11-23 10:21:28 +08:00
return
}
}
}
if s.config.IndexFolder {
s.listDir(r, f)
2017-11-23 10:21:28 +08:00
} else {
r.Response.WriteStatus(http.StatusForbidden)
2017-11-23 10:21:28 +08:00
}
} else {
// 读取文件内容返回
http.ServeContent(r.Response.ResponseWriter, &r.Request, info.Name(), info.ModTime(), f)
2017-11-23 10:21:28 +08:00
}
f.Close()
}
// 目录列表
func (s *Server)listDir(r *Request, f http.File) {
2017-11-23 10:21:28 +08:00
dirs, err := f.Readdir(-1)
if err != nil {
r.Response.WriteStatus(http.StatusInternalServerError, "Error reading directory")
2017-11-23 10:21:28 +08:00
return
}
sort.Slice(dirs, func(i, j int) bool { return dirs[i].Name() < dirs[j].Name() })
r.Response.Header().Set("Content-Type", "text/html; charset=utf-8")
r.Response.Write("<pre>\n")
2017-11-23 10:21:28 +08:00
for _, d := range dirs {
name := d.Name()
if d.IsDir() {
name += "/"
}
2017-12-07 17:34:51 +08:00
u := url.URL{Path: name}
r.Response.Write(fmt.Sprintf("<a href=\"%s\">%s</a>\n", u.String(), ghtml.SpecialChars(name)))
2017-11-23 10:21:28 +08:00
}
r.Response.Write("</pre>\n")
2017-11-23 10:21:28 +08:00
}