From c89482c3d6670a0ae10edec4f85b9bd53be1142c Mon Sep 17 00:00:00 2001 From: John Date: Sat, 17 Nov 2018 11:17:02 +0800 Subject: [PATCH] =?UTF-8?q?WebServer=E6=80=A7=E8=83=BD=E7=BB=86=E8=8A=82?= =?UTF-8?q?=E6=94=B9=E8=BF=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- g/net/ghttp/ghttp_response.go | 21 ++++++++++++--------- g/net/ghttp/ghttp_response_writer.go | 15 ++++++++------- g/net/ghttp/ghttp_server.go | 12 ++++++++---- g/net/ghttp/ghttp_server_handler.go | 20 +++++++------------- g/os/gspath/gspath.go | 15 +++++++++++++++ geg/net/ghttp/server/hello.go | 1 + geg/other/test.go | 2 +- 7 files changed, 52 insertions(+), 34 deletions(-) diff --git a/g/net/ghttp/ghttp_response.go b/g/net/ghttp/ghttp_response.go index f6a095ef6..4d675b1bd 100644 --- a/g/net/ghttp/ghttp_response.go +++ b/g/net/ghttp/ghttp_response.go @@ -8,6 +8,7 @@ package ghttp import ( + "bytes" "gitee.com/johng/gf/g/os/gfile" "net/http" "gitee.com/johng/gf/g/util/gconv" @@ -32,7 +33,7 @@ func newResponse(s *Server, w http.ResponseWriter) *Response { ResponseWriter : ResponseWriter { ResponseWriter : w, Status : http.StatusOK, - buffer : make([]byte, 0), + buffer : bytes.NewBuffer(nil), }, } r.Writer = &r.ResponseWriter @@ -48,10 +49,11 @@ func (r *Response) Write(content ... interface{}) { switch v.(type) { case []byte: // 如果是二进制数据,那么返回二进制数据 - r.buffer = append(r.buffer, gconv.Bytes(v)...) + r.buffer.Write(gconv.Bytes(v)) + default: // 否则一律按照可显示的字符串进行转换 - r.buffer = append(r.buffer, gconv.String(v)...) + r.buffer.WriteString(gconv.String(v)) } } } @@ -130,7 +132,7 @@ func (r *Response) SetAllowCrossDomainRequest(allowOrigin string, allowMethods s // 返回HTTP Code状态码 func (r *Response) WriteStatus(status int, content...string) { - if len(r.buffer) == 0 { + if r.buffer.Len() == 0 { // 状态码注册回调函数处理 if status != http.StatusOK { if f := r.request.Server.getStatusHandler(status, r.request); f != nil { @@ -181,22 +183,23 @@ func (r *Response) RedirectBack() { // 获取当前缓冲区中的数据 func (r *Response) Buffer() []byte { - return r.buffer + return r.buffer.Bytes() } // 获取当前缓冲区中的数据大小 func (r *Response) BufferLength() int { - return len(r.buffer) + return r.buffer.Len() } // 手动设置缓冲区内容 -func (r *Response) SetBuffer(buffer []byte) { - r.buffer = buffer +func (r *Response) SetBuffer(data []byte) { + r.buffer.Reset() + r.buffer.Write(data) } // 清空缓冲区内容 func (r *Response) ClearBuffer() { - r.buffer = r.buffer[:0] + r.buffer.Reset() } // 输出缓冲区数据到客户端 diff --git a/g/net/ghttp/ghttp_response_writer.go b/g/net/ghttp/ghttp_response_writer.go index 271567488..936234dbf 100644 --- a/g/net/ghttp/ghttp_response_writer.go +++ b/g/net/ghttp/ghttp_response_writer.go @@ -8,6 +8,7 @@ package ghttp import ( + "bytes" "net/http" ) @@ -15,13 +16,13 @@ import ( type ResponseWriter struct { http.ResponseWriter Status int // http status - buffer []byte // 缓冲区内容 + buffer *bytes.Buffer // 缓冲区内容 } // 覆盖父级的WriteHeader方法 -func (w *ResponseWriter) Write(buffer []byte) (int, error) { - w.buffer = append(w.buffer, buffer...) - return len(buffer), nil +func (w *ResponseWriter) Write(data []byte) (int, error) { + w.buffer.Write(data) + return len(data), nil } // 覆盖父级的WriteHeader方法 @@ -32,8 +33,8 @@ func (w *ResponseWriter) WriteHeader(code int) { // 输出buffer数据到客户端 func (w *ResponseWriter) OutputBuffer() { - if len(w.buffer) > 0 { - w.ResponseWriter.Write(w.buffer) - w.buffer = w.buffer[:0] + if w.buffer.Len() > 0 { + w.ResponseWriter.Write(w.buffer.Bytes()) + w.buffer.Reset() } } diff --git a/g/net/ghttp/ghttp_server.go b/g/net/ghttp/ghttp_server.go index 008448994..2242070e6 100644 --- a/g/net/ghttp/ghttp_server.go +++ b/g/net/ghttp/ghttp_server.go @@ -218,16 +218,20 @@ func (s *Server) Start() error { glog.Debug("ghttp.SetServerRoot:", rp) } } - s.AddSearchPath(gfile.SelfDir()) + // 添加当前可执行文件运行目录到搜索目录 + s.paths.Add(gfile.SelfDir()) + // (开发环境)添加main源码包到搜索目录 if p := gfile.MainPkgPath(); p != "" && gfile.Exists(p) { s.paths.Add(p) } + // (安全控制)不能访问当前执行文件 + s.paths.Remove(gfile.SelfPath()) // 底层http server配置 if s.config.Handler == nil { s.config.Handler = http.HandlerFunc(s.defaultHttpHandle) } - // 不允许访问的路由注册 + // 不允许访问的路由注册(通过HOOK实现) if s.config.DenyRoutes != nil { for _, v := range s.config.DenyRoutes { s.BindHookHandler(v, HOOK_BEFORE_SERVE, func(r *Request) { @@ -238,12 +242,12 @@ func (s *Server) Start() error { } // 配置相关相对路径处理 - if !gfile.Exists(s.config.HTTPSCertPath) { + if s.config.HTTPSCertPath != "" && !gfile.Exists(s.config.HTTPSCertPath) { if t, _ := s.paths.Search(s.config.HTTPSCertPath); t != "" { s.config.HTTPSCertPath = t } } - if !gfile.Exists(s.config.HTTPSKeyPath) { + if s.config.HTTPSKeyPath != "" && !gfile.Exists(s.config.HTTPSKeyPath) { if t, _ := s.paths.Search(s.config.HTTPSKeyPath); t != "" { s.config.HTTPSKeyPath = t } diff --git a/g/net/ghttp/ghttp_server_handler.go b/g/net/ghttp/ghttp_server_handler.go index 48b258c60..9ce29a2be 100644 --- a/g/net/ghttp/ghttp_server_handler.go +++ b/g/net/ghttp/ghttp_server_handler.go @@ -10,10 +10,8 @@ package ghttp import ( "fmt" "gitee.com/johng/gf/g/encoding/ghtml" - "gitee.com/johng/gf/g/os/gfile" "gitee.com/johng/gf/g/os/gtime" "net/http" - "net/url" "os" "reflect" "sort" @@ -83,7 +81,7 @@ func (s *Server)handleRequest(w http.ResponseWriter, r *http.Request) { // 执行静态文件服务/回调控制器/执行对象/方法 if !request.IsExited() { // 需要再次判断文件是否真实存在,因为文件检索可能使用了缓存,从健壮性考虑这里需要二次判断 - if request.IsFileRequest() && !isStaticDir /* && gfile.Exists(staticFile) */ && gfile.SelfPath() != staticFile { + if request.IsFileRequest() && !isStaticDir /* && gfile.Exists(staticFile) */{ // 静态文件 s.serveFile(request, staticFile) } else { @@ -167,24 +165,20 @@ func (s *Server)serveFile(r *Request, path string) { } } -// 目录列表 +// 显示目录列表 func (s *Server)listDir(r *Request, f http.File) { - dirs, err := f.Readdir(-1) + files, err := f.Readdir(-1) if err != nil { r.Response.WriteStatus(http.StatusInternalServerError, "Error reading directory") return } - sort.Slice(dirs, func(i, j int) bool { return dirs[i].Name() < dirs[j].Name() }) + sort.Slice(files, func(i, j int) bool { return files[i].Name() < files[j].Name() }) r.Response.Header().Set("Content-Type", "text/html; charset=utf-8") r.Response.Write("
\n")
-    for _, d := range dirs {
-        name := d.Name()
-        if d.IsDir() {
-            name += "/"
-        }
-        u := url.URL{Path: name}
-        r.Response.Write(fmt.Sprintf("%s\n", u.String(), ghtml.SpecialChars(name)))
+    for _, file := range files {
+        name := file.Name()
+        r.Response.Write(fmt.Sprintf("%s\n", r.URL.Path, name, ghtml.SpecialChars(name)))
     }
     r.Response.Write("
\n") } diff --git a/g/os/gspath/gspath.go b/g/os/gspath/gspath.go index e97f65459..f9c467136 100644 --- a/g/os/gspath/gspath.go +++ b/g/os/gspath/gspath.go @@ -125,6 +125,21 @@ func (sp *SPath) Search(name string, indexFiles...string) (path string, isDir bo return "", false } +// 从搜索路径中移除指定的文件,这样该文件无法给搜索。 +// path可以是绝对路径,也可以相对路径。 +func (sp *SPath) Remove(path string) { + if gfile.Exists(path) { + for _, v := range sp.paths.Slice() { + name := gstr.Replace(path, v, "") + name = sp.formatCacheName(name) + sp.cache.Remove(name) + } + } else { + name := sp.formatCacheName(path) + sp.cache.Remove(name) + } +} + // 返回当前对象缓存的所有路径列表 func (sp *SPath) AllPaths() []string { paths := sp.cache.Keys() diff --git a/geg/net/ghttp/server/hello.go b/geg/net/ghttp/server/hello.go index be6bc7c4f..596630462 100644 --- a/geg/net/ghttp/server/hello.go +++ b/geg/net/ghttp/server/hello.go @@ -7,6 +7,7 @@ import ( func main() { s := g.Server() + s.SetIndexFolder(true) s.BindHandler("/", func(r *ghttp.Request){ r.Response.Writeln("哈喽世界!") }) diff --git a/geg/other/test.go b/geg/other/test.go index f600d12cd..62db13c3c 100644 --- a/geg/other/test.go +++ b/geg/other/test.go @@ -6,5 +6,5 @@ import ( ) func main() { - fmt.Println(gfile.TempDir()) + fmt.Println(gfile.SelfPath()) }