mirror of
https://gitee.com/johng/gf
synced 2026-06-18 22:35:54 +08:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8021f39710 | |||
| f2af08270b | |||
| c2f028848c | |||
| d9c7224861 | |||
| f59a1ada88 | |||
| 705ab1d33f |
@ -1,11 +1,10 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/frame/g"
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(g.Cfg().FilePath())
|
||||
g.Cfg().Dump()
|
||||
g.Dump(os.Args)
|
||||
}
|
||||
|
||||
@ -46,6 +46,10 @@ golang version >= 1.10
|
||||
|
||||
`GF` is licensed under the [MIT License](LICENSE), 100% free and open-source, forever.
|
||||
|
||||
# Contributors
|
||||
This project exists thanks to all the people who contribute. [[Contributors](https://github.com/gogf/gf/graphs/contributors)].
|
||||
<a href="https://github.com/gogf/gf/graphs/contributors"><img src="https://opencollective.com/goframe/contributors.svg?width=890&button=false" /></a>
|
||||
|
||||
# Donators
|
||||
|
||||
We currently accept donation by Alipay/WechatPay, please note your github/gitee account in your payment bill. If you like `GF`, why not [buy developer a cup of coffee](DONATOR.MD)?
|
||||
|
||||
@ -55,6 +55,12 @@ golang版本 >= 1.11
|
||||
|
||||
`GF` 使用非常友好的 [MIT](LICENSE) 开源协议进行发布,永久`100%`开源免费。
|
||||
|
||||
# 贡献
|
||||
|
||||
感谢所有参与`GoFrame`开发的贡献者。 [[贡献者列表](https://github.com/gogf/gf/graphs/contributors)].
|
||||
<a href="https://github.com/gogf/gf/graphs/contributors"><img src="https://opencollective.com/goframe/contributors.svg?width=890&button=false" /></a>
|
||||
|
||||
|
||||
# 捐赠
|
||||
|
||||
如果您喜欢`GF`,要不[给开发者来杯咖啡吧](DONATOR.MD)!
|
||||
|
||||
@ -176,6 +176,9 @@ func (a *Array) InsertAfter(index int, value interface{}) *Array {
|
||||
func (a *Array) Remove(index int) interface{} {
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
if index < 0 || index >= len(a.array) {
|
||||
return nil
|
||||
}
|
||||
// Determine array boundaries when deleting to improve deletion efficiency。
|
||||
if index == 0 {
|
||||
value := a.array[0]
|
||||
@ -194,6 +197,16 @@ func (a *Array) Remove(index int) interface{} {
|
||||
return value
|
||||
}
|
||||
|
||||
// RemoveValue removes an item by value.
|
||||
// It returns true if value is found in the array, or else false if not found.
|
||||
func (a *Array) RemoveValue(value interface{}) bool {
|
||||
if i := a.Search(value); i != -1 {
|
||||
a.Remove(i)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// PushLeft pushes one or multiple items to the beginning of array.
|
||||
func (a *Array) PushLeft(value ...interface{}) *Array {
|
||||
a.mu.Lock()
|
||||
@ -418,9 +431,6 @@ func (a *Array) Contains(value interface{}) bool {
|
||||
// Search searches array by <value>, returns the index of <value>,
|
||||
// or returns -1 if not exists.
|
||||
func (a *Array) Search(value interface{}) int {
|
||||
if len(a.array) == 0 {
|
||||
return -1
|
||||
}
|
||||
a.mu.RLock()
|
||||
result := -1
|
||||
for index, v := range a.array {
|
||||
@ -430,7 +440,20 @@ func (a *Array) Search(value interface{}) int {
|
||||
}
|
||||
}
|
||||
a.mu.RUnlock()
|
||||
return result
|
||||
}
|
||||
|
||||
func (a *Array) doSearch(value interface{}) int {
|
||||
if len(a.array) == 0 {
|
||||
return -1
|
||||
}
|
||||
result := -1
|
||||
for index, v := range a.array {
|
||||
if v == value {
|
||||
result = index
|
||||
break
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
@ -179,6 +179,9 @@ func (a *IntArray) InsertAfter(index int, value int) *IntArray {
|
||||
func (a *IntArray) Remove(index int) int {
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
if index < 0 || index >= len(a.array) {
|
||||
return 0
|
||||
}
|
||||
// Determine array boundaries when deleting to improve deletion efficiency.
|
||||
if index == 0 {
|
||||
value := a.array[0]
|
||||
@ -197,6 +200,16 @@ func (a *IntArray) Remove(index int) int {
|
||||
return value
|
||||
}
|
||||
|
||||
// RemoveValue removes an item by value.
|
||||
// It returns true if value is found in the array, or else false if not found.
|
||||
func (a *IntArray) RemoveValue(value int) bool {
|
||||
if i := a.Search(value); i != -1 {
|
||||
a.Remove(i)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// PushLeft pushes one or multiple items to the beginning of array.
|
||||
func (a *IntArray) PushLeft(value ...int) *IntArray {
|
||||
a.mu.Lock()
|
||||
@ -430,9 +443,6 @@ func (a *IntArray) Contains(value int) bool {
|
||||
// Search searches array by <value>, returns the index of <value>,
|
||||
// or returns -1 if not exists.
|
||||
func (a *IntArray) Search(value int) int {
|
||||
if len(a.array) == 0 {
|
||||
return -1
|
||||
}
|
||||
a.mu.RLock()
|
||||
result := -1
|
||||
for index, v := range a.array {
|
||||
@ -442,7 +452,6 @@ func (a *IntArray) Search(value int) int {
|
||||
}
|
||||
}
|
||||
a.mu.RUnlock()
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
@ -165,6 +165,9 @@ func (a *StrArray) InsertAfter(index int, value string) *StrArray {
|
||||
func (a *StrArray) Remove(index int) string {
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
if index < 0 || index >= len(a.array) {
|
||||
return ""
|
||||
}
|
||||
// Determine array boundaries when deleting to improve deletion efficiency。
|
||||
if index == 0 {
|
||||
value := a.array[0]
|
||||
@ -183,6 +186,16 @@ func (a *StrArray) Remove(index int) string {
|
||||
return value
|
||||
}
|
||||
|
||||
// RemoveValue removes an item by value.
|
||||
// It returns true if value is found in the array, or else false if not found.
|
||||
func (a *StrArray) RemoveValue(value string) bool {
|
||||
if i := a.Search(value); i != -1 {
|
||||
a.Remove(i)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// PushLeft pushes one or multiple items to the beginning of array.
|
||||
func (a *StrArray) PushLeft(value ...string) *StrArray {
|
||||
a.mu.Lock()
|
||||
|
||||
@ -160,6 +160,9 @@ func (a *SortedArray) Get(index int) interface{} {
|
||||
func (a *SortedArray) Remove(index int) interface{} {
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
if index < 0 || index >= len(a.array) {
|
||||
return nil
|
||||
}
|
||||
// Determine array boundaries when deleting to improve deletion efficiency.
|
||||
if index == 0 {
|
||||
value := a.array[0]
|
||||
@ -178,6 +181,16 @@ func (a *SortedArray) Remove(index int) interface{} {
|
||||
return value
|
||||
}
|
||||
|
||||
// RemoveValue removes an item by value.
|
||||
// It returns true if value is found in the array, or else false if not found.
|
||||
func (a *SortedArray) RemoveValue(value interface{}) bool {
|
||||
if i := a.Search(value); i != -1 {
|
||||
a.Remove(i)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// PopLeft pops and returns an item from the beginning of array.
|
||||
func (a *SortedArray) PopLeft() interface{} {
|
||||
a.mu.Lock()
|
||||
|
||||
@ -146,6 +146,9 @@ func (a *SortedIntArray) Get(index int) int {
|
||||
func (a *SortedIntArray) Remove(index int) int {
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
if index < 0 || index >= len(a.array) {
|
||||
return 0
|
||||
}
|
||||
// Determine array boundaries when deleting to improve deletion efficiency.
|
||||
if index == 0 {
|
||||
value := a.array[0]
|
||||
@ -164,6 +167,16 @@ func (a *SortedIntArray) Remove(index int) int {
|
||||
return value
|
||||
}
|
||||
|
||||
// RemoveValue removes an item by value.
|
||||
// It returns true if value is found in the array, or else false if not found.
|
||||
func (a *SortedIntArray) RemoveValue(value int) bool {
|
||||
if i := a.Search(value); i != -1 {
|
||||
a.Remove(i)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// PopLeft pops and returns an item from the beginning of array.
|
||||
func (a *SortedIntArray) PopLeft() int {
|
||||
a.mu.Lock()
|
||||
|
||||
@ -131,6 +131,9 @@ func (a *SortedStrArray) Get(index int) string {
|
||||
func (a *SortedStrArray) Remove(index int) string {
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
if index < 0 || index >= len(a.array) {
|
||||
return ""
|
||||
}
|
||||
// Determine array boundaries when deleting to improve deletion efficiency.
|
||||
if index == 0 {
|
||||
value := a.array[0]
|
||||
@ -149,6 +152,16 @@ func (a *SortedStrArray) Remove(index int) string {
|
||||
return value
|
||||
}
|
||||
|
||||
// RemoveValue removes an item by value.
|
||||
// It returns true if value is found in the array, or else false if not found.
|
||||
func (a *SortedStrArray) RemoveValue(value string) bool {
|
||||
if i := a.Search(value); i != -1 {
|
||||
a.Remove(i)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// PopLeft pops and returns an item from the beginning of array.
|
||||
func (a *SortedStrArray) PopLeft() string {
|
||||
a.mu.Lock()
|
||||
|
||||
@ -34,6 +34,8 @@ func Test_Array_Basic(t *testing.T) {
|
||||
gtest.Assert(array3.Search(100), -1)
|
||||
gtest.Assert(array.Contains(100), true)
|
||||
gtest.Assert(array.Remove(0), 100)
|
||||
gtest.Assert(array.Remove(-1), nil)
|
||||
gtest.Assert(array.Remove(100000), nil)
|
||||
|
||||
gtest.Assert(array2.Remove(3), 3)
|
||||
gtest.Assert(array2.Remove(1), 1)
|
||||
@ -497,3 +499,15 @@ func TestArray_Iterator(t *testing.T) {
|
||||
gtest.Assert(index, 1)
|
||||
})
|
||||
}
|
||||
|
||||
func TestArray_RemoveValue(t *testing.T) {
|
||||
slice := g.Slice{"a", "b", "d", "c"}
|
||||
array := garray.NewArrayFrom(slice)
|
||||
gtest.Case(t, func() {
|
||||
gtest.Assert(array.RemoveValue("e"), false)
|
||||
gtest.Assert(array.RemoveValue("b"), true)
|
||||
gtest.Assert(array.RemoveValue("a"), true)
|
||||
gtest.Assert(array.RemoveValue("c"), true)
|
||||
gtest.Assert(array.RemoveValue("f"), false)
|
||||
})
|
||||
}
|
||||
|
||||
@ -35,6 +35,8 @@ func Test_IntArray_Basic(t *testing.T) {
|
||||
gtest.Assert(array2.Search(100), -1)
|
||||
gtest.Assert(array.Contains(100), true)
|
||||
gtest.Assert(array.Remove(0), 100)
|
||||
gtest.Assert(array.Remove(-1), 0)
|
||||
gtest.Assert(array.Remove(100000), 0)
|
||||
gtest.Assert(array.Contains(100), false)
|
||||
array.Append(4)
|
||||
gtest.Assert(array.Len(), 4)
|
||||
@ -531,3 +533,16 @@ func TestIntArray_Iterator(t *testing.T) {
|
||||
gtest.Assert(index, 1)
|
||||
})
|
||||
}
|
||||
|
||||
func TestIntArray_RemoveValue(t *testing.T) {
|
||||
slice := g.SliceInt{10, 20, 30, 40}
|
||||
array := garray.NewIntArrayFrom(slice)
|
||||
gtest.Case(t, func() {
|
||||
gtest.Assert(array.RemoveValue(99), false)
|
||||
gtest.Assert(array.RemoveValue(20), true)
|
||||
gtest.Assert(array.RemoveValue(10), true)
|
||||
gtest.Assert(array.RemoveValue(20), false)
|
||||
gtest.Assert(array.RemoveValue(88), false)
|
||||
gtest.Assert(array.Len(), 2)
|
||||
})
|
||||
}
|
||||
|
||||
@ -34,6 +34,8 @@ func Test_StrArray_Basic(t *testing.T) {
|
||||
gtest.Assert(array.Search("100"), 0)
|
||||
gtest.Assert(array.Contains("100"), true)
|
||||
gtest.Assert(array.Remove(0), 100)
|
||||
gtest.Assert(array.Remove(-1), "")
|
||||
gtest.Assert(array.Remove(100000), "")
|
||||
gtest.Assert(array.Contains("100"), false)
|
||||
array.Append("4")
|
||||
gtest.Assert(array.Len(), 4)
|
||||
@ -535,3 +537,15 @@ func TestStrArray_Iterator(t *testing.T) {
|
||||
gtest.Assert(index, 1)
|
||||
})
|
||||
}
|
||||
|
||||
func TestStrArray_RemoveValue(t *testing.T) {
|
||||
slice := g.SliceStr{"a", "b", "d", "c"}
|
||||
array := garray.NewStrArrayFrom(slice)
|
||||
gtest.Case(t, func() {
|
||||
gtest.Assert(array.RemoveValue("e"), false)
|
||||
gtest.Assert(array.RemoveValue("b"), true)
|
||||
gtest.Assert(array.RemoveValue("a"), true)
|
||||
gtest.Assert(array.RemoveValue("c"), true)
|
||||
gtest.Assert(array.RemoveValue("f"), false)
|
||||
})
|
||||
}
|
||||
|
||||
@ -117,6 +117,9 @@ func TestSortedArray_Remove(t *testing.T) {
|
||||
gtest.Assert(array1.Len(), 3)
|
||||
gtest.Assert(array1.Contains("b"), false)
|
||||
|
||||
gtest.Assert(array1.Remove(-1), nil)
|
||||
gtest.Assert(array1.Remove(100000), nil)
|
||||
|
||||
i2 := array1.Remove(0)
|
||||
gtest.Assert(gconv.String(i2), "a")
|
||||
gtest.Assert(array1.Len(), 2)
|
||||
@ -634,3 +637,15 @@ func TestSortedArray_Iterator(t *testing.T) {
|
||||
gtest.Assert(index, 1)
|
||||
})
|
||||
}
|
||||
|
||||
func TestSortedArray_RemoveValue(t *testing.T) {
|
||||
slice := g.Slice{"a", "b", "d", "c"}
|
||||
array := garray.NewSortedArrayFrom(slice, gutil.ComparatorString)
|
||||
gtest.Case(t, func() {
|
||||
gtest.Assert(array.RemoveValue("e"), false)
|
||||
gtest.Assert(array.RemoveValue("b"), true)
|
||||
gtest.Assert(array.RemoveValue("a"), true)
|
||||
gtest.Assert(array.RemoveValue("c"), true)
|
||||
gtest.Assert(array.RemoveValue("f"), false)
|
||||
})
|
||||
}
|
||||
|
||||
@ -78,6 +78,10 @@ func TestSortedIntArray_Remove(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
a1 := []int{1, 3, 5, 0}
|
||||
array1 := garray.NewSortedIntArrayFrom(a1)
|
||||
|
||||
gtest.Assert(array1.Remove(-1), 0)
|
||||
gtest.Assert(array1.Remove(100000), 0)
|
||||
|
||||
i1 := array1.Remove(2)
|
||||
gtest.Assert(i1, 3)
|
||||
gtest.Assert(array1.Search(5), 2)
|
||||
@ -513,3 +517,16 @@ func TestSortedIntArray_Iterator(t *testing.T) {
|
||||
gtest.Assert(index, 1)
|
||||
})
|
||||
}
|
||||
|
||||
func TestSortedIntArray_RemoveValue(t *testing.T) {
|
||||
slice := g.SliceInt{10, 20, 30, 40}
|
||||
array := garray.NewSortedIntArrayFrom(slice)
|
||||
gtest.Case(t, func() {
|
||||
gtest.Assert(array.RemoveValue(99), false)
|
||||
gtest.Assert(array.RemoveValue(20), true)
|
||||
gtest.Assert(array.RemoveValue(10), true)
|
||||
gtest.Assert(array.RemoveValue(20), false)
|
||||
gtest.Assert(array.RemoveValue(88), false)
|
||||
gtest.Assert(array.Len(), 2)
|
||||
})
|
||||
}
|
||||
|
||||
@ -77,6 +77,10 @@ func TestSortedStrArray_Remove(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
a1 := []string{"a", "d", "c", "b"}
|
||||
array1 := garray.NewSortedStrArrayFrom(a1)
|
||||
|
||||
gtest.Assert(array1.Remove(-1), "")
|
||||
gtest.Assert(array1.Remove(100000), "")
|
||||
|
||||
gtest.Assert(array1.Remove(2), "c")
|
||||
gtest.Assert(array1.Get(2), "d")
|
||||
gtest.Assert(array1.Len(), 3)
|
||||
@ -523,3 +527,15 @@ func TestSortedStrArray_Iterator(t *testing.T) {
|
||||
gtest.Assert(index, 1)
|
||||
})
|
||||
}
|
||||
|
||||
func TestSortedStrArray_RemoveValue(t *testing.T) {
|
||||
slice := g.SliceStr{"a", "b", "d", "c"}
|
||||
array := garray.NewSortedStrArrayFrom(slice)
|
||||
gtest.Case(t, func() {
|
||||
gtest.Assert(array.RemoveValue("e"), false)
|
||||
gtest.Assert(array.RemoveValue("b"), true)
|
||||
gtest.Assert(array.RemoveValue("a"), true)
|
||||
gtest.Assert(array.RemoveValue("c"), true)
|
||||
gtest.Assert(array.RemoveValue("f"), false)
|
||||
})
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@ package ghttp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/os/gres"
|
||||
"github.com/gogf/gf/os/gview"
|
||||
"net/http"
|
||||
"strings"
|
||||
@ -29,6 +30,7 @@ type Request struct {
|
||||
EnterTime int64 // Request starting time in microseconds.
|
||||
LeaveTime int64 // Request ending time in microseconds.
|
||||
Middleware *Middleware // The middleware manager.
|
||||
StaticFile *StaticFile // Static file object when static file serving.
|
||||
handlers []*handlerParsedItem // All matched handlers containing handler, hook and middleware for this request .
|
||||
hasHookHandler bool // A bool marking whether there's hook handler in the handlers for performance purpose.
|
||||
hasServeHandler bool // A bool marking whether there's serving handler in the handlers for performance purpose.
|
||||
@ -50,13 +52,20 @@ type Request struct {
|
||||
viewParams gview.Params // Custom template view variables for this response.
|
||||
}
|
||||
|
||||
// StaticFile is the file struct for static file service.
|
||||
type StaticFile struct {
|
||||
File *gres.File // Resource file object.
|
||||
Path string // File path.
|
||||
IsDir bool // Is directory.
|
||||
}
|
||||
|
||||
// newRequest creates and returns a new request object.
|
||||
func newRequest(s *Server, r *http.Request, w http.ResponseWriter) *Request {
|
||||
request := &Request{
|
||||
Server: s,
|
||||
Request: r,
|
||||
Response: newResponse(s, w),
|
||||
EnterTime: gtime.Microsecond(),
|
||||
EnterTime: gtime.TimestampMicro(),
|
||||
}
|
||||
request.Cookie = GetCookie(request)
|
||||
request.Session = s.sessionManager.New(request.GetSessionId())
|
||||
|
||||
@ -41,11 +41,11 @@ func newResponse(s *Server, w http.ResponseWriter) *Response {
|
||||
|
||||
// ServeFile serves the file to the response.
|
||||
func (r *Response) ServeFile(path string, allowIndex ...bool) {
|
||||
serveFile := (*staticServeFile)(nil)
|
||||
serveFile := (*StaticFile)(nil)
|
||||
if file := gres.Get(path); file != nil {
|
||||
serveFile = &staticServeFile{
|
||||
file: file,
|
||||
dir: file.FileInfo().IsDir(),
|
||||
serveFile = &StaticFile{
|
||||
File: file,
|
||||
IsDir: file.FileInfo().IsDir(),
|
||||
}
|
||||
} else {
|
||||
path = gfile.RealPath(path)
|
||||
@ -53,22 +53,22 @@ func (r *Response) ServeFile(path string, allowIndex ...bool) {
|
||||
r.WriteStatus(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
serveFile = &staticServeFile{path: path}
|
||||
serveFile = &StaticFile{Path: path}
|
||||
}
|
||||
r.Server.serveFile(r.Request, serveFile, allowIndex...)
|
||||
}
|
||||
|
||||
// ServeFileDownload serves file downloading to the response.
|
||||
func (r *Response) ServeFileDownload(path string, name ...string) {
|
||||
serveFile := (*staticServeFile)(nil)
|
||||
serveFile := (*StaticFile)(nil)
|
||||
downloadName := ""
|
||||
if len(name) > 0 {
|
||||
downloadName = name[0]
|
||||
}
|
||||
if file := gres.Get(path); file != nil {
|
||||
serveFile = &staticServeFile{
|
||||
file: file,
|
||||
dir: file.FileInfo().IsDir(),
|
||||
serveFile = &StaticFile{
|
||||
File: file,
|
||||
IsDir: file.FileInfo().IsDir(),
|
||||
}
|
||||
if downloadName == "" {
|
||||
downloadName = gfile.Basename(file.Name())
|
||||
@ -79,7 +79,7 @@ func (r *Response) ServeFileDownload(path string, name ...string) {
|
||||
r.WriteStatus(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
serveFile = &staticServeFile{path: path}
|
||||
serveFile = &StaticFile{Path: path}
|
||||
if downloadName == "" {
|
||||
downloadName = gfile.Basename(path)
|
||||
}
|
||||
|
||||
@ -24,13 +24,6 @@ import (
|
||||
"github.com/gogf/gf/os/gtime"
|
||||
)
|
||||
|
||||
// staticServeFile is the file struct for static service.
|
||||
type staticServeFile struct {
|
||||
file *gres.File // Resource file object.
|
||||
path string // File path.
|
||||
dir bool // Is directory.
|
||||
}
|
||||
|
||||
// 默认HTTP Server处理入口,http包底层默认使用了gorutine异步处理请求,所以这里不再异步执行
|
||||
func (s *Server) defaultHandler(w http.ResponseWriter, r *http.Request) {
|
||||
s.handleRequest(w, r)
|
||||
@ -65,7 +58,7 @@ func (s *Server) handleRequest(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
defer func() {
|
||||
// 设置请求完成时间
|
||||
request.LeaveTime = gtime.Microsecond()
|
||||
request.LeaveTime = gtime.TimestampMicro()
|
||||
// error log
|
||||
if request.error != nil {
|
||||
s.handleErrorLog(request.error, request)
|
||||
@ -86,11 +79,10 @@ func (s *Server) handleRequest(w http.ResponseWriter, r *http.Request) {
|
||||
// 静态文件 > 动态服务 > 静态目录
|
||||
// ============================================================
|
||||
|
||||
serveFile := (*staticServeFile)(nil)
|
||||
// 优先执行静态文件检索(检测是否存在对应的静态文件,包括index files处理)
|
||||
if s.config.FileServerEnabled {
|
||||
serveFile = s.searchStaticFile(r.URL.Path)
|
||||
if serveFile != nil {
|
||||
request.StaticFile = s.searchStaticFile(r.URL.Path)
|
||||
if request.StaticFile != nil {
|
||||
request.isFileRequest = true
|
||||
}
|
||||
}
|
||||
@ -99,7 +91,7 @@ func (s *Server) handleRequest(w http.ResponseWriter, r *http.Request) {
|
||||
request.handlers, request.hasHookHandler, request.hasServeHandler = s.getHandlersWithCache(request)
|
||||
|
||||
// 判断最终对该请求提供的服务方式
|
||||
if serveFile != nil && serveFile.dir && request.hasServeHandler {
|
||||
if request.StaticFile != nil && request.StaticFile.IsDir && request.hasServeHandler {
|
||||
request.isFileRequest = false
|
||||
}
|
||||
|
||||
@ -110,15 +102,15 @@ func (s *Server) handleRequest(w http.ResponseWriter, r *http.Request) {
|
||||
if !request.IsExited() {
|
||||
if request.isFileRequest {
|
||||
// 静态服务
|
||||
s.serveFile(request, serveFile)
|
||||
s.serveFile(request, request.StaticFile)
|
||||
} else {
|
||||
if len(request.handlers) > 0 {
|
||||
// 动态服务
|
||||
request.Middleware.Next()
|
||||
} else {
|
||||
if serveFile != nil && serveFile.dir {
|
||||
if request.StaticFile != nil && request.StaticFile.IsDir {
|
||||
// 静态目录
|
||||
s.serveFile(request, serveFile)
|
||||
s.serveFile(request, request.StaticFile)
|
||||
} else {
|
||||
if len(request.Response.Header()) == 0 &&
|
||||
request.Response.Status == 0 &&
|
||||
@ -142,7 +134,7 @@ func (s *Server) handleRequest(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// HTTP status checking.
|
||||
if request.Response.Status == 0 {
|
||||
if serveFile != nil || request.Middleware.served || request.Response.buffer.Len() > 0 {
|
||||
if request.StaticFile != nil || request.Middleware.served || request.Response.buffer.Len() > 0 {
|
||||
request.Response.WriteHeader(http.StatusOK)
|
||||
} else {
|
||||
request.Response.WriteHeader(http.StatusNotFound)
|
||||
@ -174,7 +166,7 @@ func (s *Server) handleRequest(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// searchStaticFile searches the file with given URI.
|
||||
// It returns a file struct specifying the file information.
|
||||
func (s *Server) searchStaticFile(uri string) *staticServeFile {
|
||||
func (s *Server) searchStaticFile(uri string) *StaticFile {
|
||||
var file *gres.File
|
||||
var path string
|
||||
var dir bool
|
||||
@ -188,16 +180,16 @@ func (s *Server) searchStaticFile(uri string) *staticServeFile {
|
||||
}
|
||||
file = gres.GetWithIndex(item.path+uri[len(item.prefix):], s.config.IndexFiles)
|
||||
if file != nil {
|
||||
return &staticServeFile{
|
||||
file: file,
|
||||
dir: file.FileInfo().IsDir(),
|
||||
return &StaticFile{
|
||||
File: file,
|
||||
IsDir: file.FileInfo().IsDir(),
|
||||
}
|
||||
}
|
||||
path, dir = gspath.Search(item.path, uri[len(item.prefix):], s.config.IndexFiles...)
|
||||
if path != "" {
|
||||
return &staticServeFile{
|
||||
path: path,
|
||||
dir: dir,
|
||||
return &StaticFile{
|
||||
Path: path,
|
||||
IsDir: dir,
|
||||
}
|
||||
}
|
||||
|
||||
@ -209,15 +201,15 @@ func (s *Server) searchStaticFile(uri string) *staticServeFile {
|
||||
for _, p := range s.config.SearchPaths {
|
||||
file = gres.GetWithIndex(p+uri, s.config.IndexFiles)
|
||||
if file != nil {
|
||||
return &staticServeFile{
|
||||
file: file,
|
||||
dir: file.FileInfo().IsDir(),
|
||||
return &StaticFile{
|
||||
File: file,
|
||||
IsDir: file.FileInfo().IsDir(),
|
||||
}
|
||||
}
|
||||
if path, dir = gspath.Search(p, uri, s.config.IndexFiles...); path != "" {
|
||||
return &staticServeFile{
|
||||
path: path,
|
||||
dir: dir,
|
||||
return &StaticFile{
|
||||
Path: path,
|
||||
IsDir: dir,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -225,9 +217,9 @@ func (s *Server) searchStaticFile(uri string) *staticServeFile {
|
||||
// Lastly search the resource manager.
|
||||
if len(s.config.StaticPaths) == 0 && len(s.config.SearchPaths) == 0 {
|
||||
if file = gres.GetWithIndex(uri, s.config.IndexFiles); file != nil {
|
||||
return &staticServeFile{
|
||||
file: file,
|
||||
dir: file.FileInfo().IsDir(),
|
||||
return &StaticFile{
|
||||
File: file,
|
||||
IsDir: file.FileInfo().IsDir(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -235,24 +227,24 @@ func (s *Server) searchStaticFile(uri string) *staticServeFile {
|
||||
}
|
||||
|
||||
// http server静态文件处理,path可以为相对路径也可以为绝对路径
|
||||
func (s *Server) serveFile(r *Request, f *staticServeFile, allowIndex ...bool) {
|
||||
func (s *Server) serveFile(r *Request, f *StaticFile, allowIndex ...bool) {
|
||||
// 使用资源文件
|
||||
if f.file != nil {
|
||||
if f.dir {
|
||||
if f.File != nil {
|
||||
if f.IsDir {
|
||||
if s.config.IndexFolder || (len(allowIndex) > 0 && allowIndex[0]) {
|
||||
s.listDir(r, f.file)
|
||||
s.listDir(r, f.File)
|
||||
} else {
|
||||
r.Response.WriteStatus(http.StatusForbidden)
|
||||
}
|
||||
} else {
|
||||
info := f.file.FileInfo()
|
||||
info := f.File.FileInfo()
|
||||
r.Response.wroteHeader = true
|
||||
http.ServeContent(r.Response.Writer.RawWriter(), r.Request, info.Name(), info.ModTime(), f.file)
|
||||
http.ServeContent(r.Response.Writer.RawWriter(), r.Request, info.Name(), info.ModTime(), f.File)
|
||||
}
|
||||
return
|
||||
}
|
||||
// 使用磁盘文件
|
||||
file, err := os.Open(f.path)
|
||||
file, err := os.Open(f.Path)
|
||||
if err != nil {
|
||||
r.Response.WriteStatus(http.StatusForbidden)
|
||||
return
|
||||
|
||||
24
net/ghttp/ghttp_server_plugin.go
Normal file
24
net/ghttp/ghttp_server_plugin.go
Normal file
@ -0,0 +1,24 @@
|
||||
// Copyright 2019 gf Author(https://github.com/gogf/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://github.com/gogf/gf.
|
||||
|
||||
package ghttp
|
||||
|
||||
import "github.com/gogf/gf/os/glog"
|
||||
|
||||
// Plugin is the interface for server plugin.
|
||||
type Plugin interface {
|
||||
Install(s *Server) error
|
||||
Remove() error
|
||||
}
|
||||
|
||||
// Plugin adds plugin for server.
|
||||
func (s *Server) Plugin(plugin ...Plugin) {
|
||||
for _, p := range plugin {
|
||||
if err := p.Install(s); err != nil {
|
||||
glog.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -189,6 +189,11 @@ func SearchBinary(file string) string {
|
||||
if gfile.Exists(file) {
|
||||
return file
|
||||
}
|
||||
return SearchBinaryPath(file)
|
||||
}
|
||||
|
||||
// SearchBinaryPath searches the binary <file> in PATH environment.
|
||||
func SearchBinaryPath(file string) string {
|
||||
array := ([]string)(nil)
|
||||
switch runtime.GOOS {
|
||||
case "windows":
|
||||
|
||||
@ -24,12 +24,11 @@ type Process struct {
|
||||
|
||||
// NewProcess creates and returns a new Process.
|
||||
func NewProcess(path string, args []string, environment ...[]string) *Process {
|
||||
var env []string
|
||||
env := os.Environ()
|
||||
if len(environment) > 0 {
|
||||
env = make([]string, len(environment[0]))
|
||||
copy(env, environment[0])
|
||||
} else {
|
||||
env = os.Environ()
|
||||
for k, v := range environment[0] {
|
||||
env[k] = v
|
||||
}
|
||||
}
|
||||
process := &Process{
|
||||
Manager: nil,
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
package gf
|
||||
|
||||
const VERSION = "v1.11.3"
|
||||
const VERSION = "v1.11.4"
|
||||
const AUTHORS = "john<john@goframe.org>"
|
||||
|
||||
Reference in New Issue
Block a user