From 51d9fe5253522df5d86fbbc2df9778d3591b8d4c Mon Sep 17 00:00:00 2001 From: John Date: Mon, 23 Sep 2019 19:25:03 +0800 Subject: [PATCH] add AllowDomain option for ghttp.CORS; add IsSubDomain function for gstr; improve grand.Intn --- .example/net/ghttp/server/admin/admin.go | 2 +- .example/net/ghttp/server/name.go | 8 ++--- .../net/ghttp/server/template/tpl2/main.go | 2 +- .gitignore | 1 + frame/g/g.go | 6 ++-- net/ghttp/ghttp_request.go | 2 +- net/ghttp/ghttp_response_cors.go | 36 +++++++++---------- net/ghttp/ghttp_server_config.go | 8 ++--- net/ghttp/ghttp_server_service_handler.go | 8 ++--- net/ghttp/ghttp_unit_router_names_test.go | 8 ++--- text/gstr/gstr_domain.go | 6 ++++ text/gstr/gstr_z_unit_domain_test.go | 14 ++++++++ util/grand/grand_intn.go | 8 +++-- 13 files changed, 66 insertions(+), 43 deletions(-) diff --git a/.example/net/ghttp/server/admin/admin.go b/.example/net/ghttp/server/admin/admin.go index c7ad4e598..5a7ffd87e 100644 --- a/.example/net/ghttp/server/admin/admin.go +++ b/.example/net/ghttp/server/admin/admin.go @@ -7,7 +7,7 @@ import ( func main() { s := g.Server() - s.SetNameToUriType(ghttp.NAME_TO_URI_TYPE_FULLNAME) + s.SetNameToUriType(ghttp.URI_TYPE_FULLNAME) s.EnableAdmin() s.BindHandler("/", func(r *ghttp.Request) { r.Response.Write("hello world") diff --git a/.example/net/ghttp/server/name.go b/.example/net/ghttp/server/name.go index 90035cca3..2e1cd60cc 100644 --- a/.example/net/ghttp/server/name.go +++ b/.example/net/ghttp/server/name.go @@ -17,10 +17,10 @@ func main() { s3 := g.Server(3) s4 := g.Server(4) - s1.SetNameToUriType(ghttp.NAME_TO_URI_TYPE_DEFAULT) - s2.SetNameToUriType(ghttp.NAME_TO_URI_TYPE_FULLNAME) - s3.SetNameToUriType(ghttp.NAME_TO_URI_TYPE_ALLLOWER) - s4.SetNameToUriType(ghttp.NAME_TO_URI_TYPE_CAMEL) + s1.SetNameToUriType(ghttp.URI_TYPE_DEFAULT) + s2.SetNameToUriType(ghttp.URI_TYPE_FULLNAME) + s3.SetNameToUriType(ghttp.URI_TYPE_ALLLOWER) + s4.SetNameToUriType(ghttp.URI_TYPE_CAMEL) s1.BindObject("/{.struct}/{.method}", new(User)) s2.BindObject("/{.struct}/{.method}", new(User)) diff --git a/.example/net/ghttp/server/template/tpl2/main.go b/.example/net/ghttp/server/template/tpl2/main.go index c46d010ec..c933cb678 100644 --- a/.example/net/ghttp/server/template/tpl2/main.go +++ b/.example/net/ghttp/server/template/tpl2/main.go @@ -9,7 +9,7 @@ import ( func main() { s := g.Server() s.SetServerRoot("public") - s.SetNameToUriType(ghttp.NAME_TO_URI_TYPE_ALLLOWER) + s.SetNameToUriType(ghttp.URI_TYPE_ALLLOWER) s.SetErrorLogEnabled(true) s.SetAccessLogEnabled(true) s.SetPort(2333) diff --git a/.gitignore b/.gitignore index ef34601f4..c3165c5e8 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ bin/ cbuild **/.DS_Store .vscode/ +go.sum diff --git a/frame/g/g.go b/frame/g/g.go index aa85b5678..5ed4481d4 100644 --- a/frame/g/g.go +++ b/frame/g/g.go @@ -6,9 +6,11 @@ package g -import "github.com/gogf/gf/container/gvar" +import ( + "github.com/gogf/gf/container/gvar" +) -// Universal variable type, like generics. +// Var is a universal variable type, like generics. type Var = gvar.Var // Frequently-used map type alias. diff --git a/net/ghttp/ghttp_request.go b/net/ghttp/ghttp_request.go index faa41623b..509593c09 100644 --- a/net/ghttp/ghttp_request.go +++ b/net/ghttp/ghttp_request.go @@ -74,7 +74,7 @@ func newRequest(s *Server, r *http.Request, w http.ResponseWriter) *Request { // 获取Web Socket连接对象(如果是非WS请求会失败,注意检查返回的error结果) func (r *Request) WebSocket() (*WebSocket, error) { - if conn, err := wsUpgrader.Upgrade(r.Response.ResponseWriter.ResponseWriter, r.Request, nil); err == nil { + if conn, err := wsUpgrader.Upgrade(r.Response.Writer, r.Request, nil); err == nil { return &WebSocket{ conn, }, nil diff --git a/net/ghttp/ghttp_response_cors.go b/net/ghttp/ghttp_response_cors.go index 65278bfd5..b3676ff21 100644 --- a/net/ghttp/ghttp_response_cors.go +++ b/net/ghttp/ghttp_response_cors.go @@ -8,6 +8,8 @@ package ghttp import ( + "net/url" + "github.com/gogf/gf/text/gstr" "github.com/gogf/gf/util/gconv" ) @@ -47,26 +49,20 @@ func (r *Response) DefaultCORSOptions() CORSOptions { // See https://www.w3.org/TR/cors/ . func (r *Response) CORS(options CORSOptions) { if options.AllowDomain != nil { - //origin := r.request.Header.Get("Origin") - //if origin == "" { - // return - //} - //parsed, err := url.Parse(origin) - //if err != nil { - // return - //} - //for k, v := range options.AllowDomain { - // if gstr.Contains(v, "*") { - // // Regular expression. - // gstr.ReplaceByArray(v, []string{ - // ".", "\\.", "*", "[^\\.]*", - // }) - // } else if len(parsed.Host) >= len(v) && parsed.Host[len(parsed.Host)-len(v):] == v { - // // Last domain. - // r.Header().Set("Access-Control-Allow-Origin", origin) - // break - // } - //} + origin := r.request.Header.Get("Origin") + if origin == "" { + return + } + parsed, err := url.Parse(origin) + if err != nil { + return + } + for _, v := range options.AllowDomain { + if gstr.IsSubDomain(parsed.Host, v) { + r.Header().Set("Access-Control-Allow-Origin", origin) + break + } + } } else if options.AllowOrigin != "" { r.Header().Set("Access-Control-Allow-Origin", options.AllowOrigin) } diff --git a/net/ghttp/ghttp_server_config.go b/net/ghttp/ghttp_server_config.go index 6331d59ac..b0b6024e4 100644 --- a/net/ghttp/ghttp_server_config.go +++ b/net/ghttp/ghttp_server_config.go @@ -26,10 +26,10 @@ import ( const ( gDEFAULT_HTTP_ADDR = ":80" // 默认HTTP监听地址 gDEFAULT_HTTPS_ADDR = ":443" // 默认HTTPS监听地址 - NAME_TO_URI_TYPE_DEFAULT = 0 // 服务注册时对象和方法名称转换为URI时,全部转为小写,单词以'-'连接符号连接 - NAME_TO_URI_TYPE_FULLNAME = 1 // 不处理名称,以原有名称构建成URI - NAME_TO_URI_TYPE_ALLLOWER = 2 // 仅转为小写,单词间不使用连接符号 - NAME_TO_URI_TYPE_CAMEL = 3 // 采用驼峰命名方式 + URI_TYPE_DEFAULT = 0 // 服务注册时对象和方法名称转换为URI时,全部转为小写,单词以'-'连接符号连接 + URI_TYPE_FULLNAME = 1 // 不处理名称,以原有名称构建成URI + URI_TYPE_ALLLOWER = 2 // 仅转为小写,单词间不使用连接符号 + URI_TYPE_CAMEL = 3 // 采用驼峰命名方式 gCHANGE_CONFIG_WHILE_RUNNING_ERROR = "server's configuration cannot be changed while running" ) diff --git a/net/ghttp/ghttp_server_service_handler.go b/net/ghttp/ghttp_server_service_handler.go index 7ff4fc21d..ce201726e 100644 --- a/net/ghttp/ghttp_server_service_handler.go +++ b/net/ghttp/ghttp_server_service_handler.go @@ -77,13 +77,13 @@ func (s *Server) mergeBuildInNameToPattern(pattern string, structName, methodNam // 规则3: 采用驼峰命名方式 func (s *Server) nameToUrlPart(name string) string { switch s.config.NameToUriType { - case NAME_TO_URI_TYPE_FULLNAME: + case URI_TYPE_FULLNAME: return name - case NAME_TO_URI_TYPE_ALLLOWER: + case URI_TYPE_ALLLOWER: return strings.ToLower(name) - case NAME_TO_URI_TYPE_CAMEL: + case URI_TYPE_CAMEL: part := bytes.NewBuffer(nil) if gstr.IsLetterUpper(name[0]) { part.WriteByte(name[0] + 32) @@ -93,7 +93,7 @@ func (s *Server) nameToUrlPart(name string) string { part.WriteString(name[1:]) return part.String() - case NAME_TO_URI_TYPE_DEFAULT: + case URI_TYPE_DEFAULT: fallthrough default: part := bytes.NewBuffer(nil) diff --git a/net/ghttp/ghttp_unit_router_names_test.go b/net/ghttp/ghttp_unit_router_names_test.go index c117c83ad..a6faea3a8 100644 --- a/net/ghttp/ghttp_unit_router_names_test.go +++ b/net/ghttp/ghttp_unit_router_names_test.go @@ -25,7 +25,7 @@ func (o *NamesObject) ShowName(r *ghttp.Request) { func Test_NameToUri_FullName(t *testing.T) { p := ports.PopRand() s := g.Server(p) - s.SetNameToUriType(ghttp.NAME_TO_URI_TYPE_FULLNAME) + s.SetNameToUriType(ghttp.URI_TYPE_FULLNAME) s.BindObject("/{.struct}/{.method}", new(NamesObject)) s.SetPort(p) s.SetDumpRouteMap(false) @@ -47,7 +47,7 @@ func Test_NameToUri_FullName(t *testing.T) { func Test_NameToUri_AllLower(t *testing.T) { p := ports.PopRand() s := g.Server(p) - s.SetNameToUriType(ghttp.NAME_TO_URI_TYPE_ALLLOWER) + s.SetNameToUriType(ghttp.URI_TYPE_ALLLOWER) s.BindObject("/{.struct}/{.method}", new(NamesObject)) s.SetPort(p) s.SetDumpRouteMap(false) @@ -69,7 +69,7 @@ func Test_NameToUri_AllLower(t *testing.T) { func Test_NameToUri_Camel(t *testing.T) { p := ports.PopRand() s := g.Server(p) - s.SetNameToUriType(ghttp.NAME_TO_URI_TYPE_CAMEL) + s.SetNameToUriType(ghttp.URI_TYPE_CAMEL) s.BindObject("/{.struct}/{.method}", new(NamesObject)) s.SetPort(p) s.SetDumpRouteMap(false) @@ -91,7 +91,7 @@ func Test_NameToUri_Camel(t *testing.T) { func Test_NameToUri_Default(t *testing.T) { p := ports.PopRand() s := g.Server(p) - s.SetNameToUriType(ghttp.NAME_TO_URI_TYPE_DEFAULT) + s.SetNameToUriType(ghttp.URI_TYPE_DEFAULT) s.BindObject("/{.struct}/{.method}", new(NamesObject)) s.SetPort(p) s.SetDumpRouteMap(false) diff --git a/text/gstr/gstr_domain.go b/text/gstr/gstr_domain.go index 6be615b4f..020ed5705 100644 --- a/text/gstr/gstr_domain.go +++ b/text/gstr/gstr_domain.go @@ -11,6 +11,12 @@ import "strings" // IsSubDomain checks whether is sub-domain of mainDomain. // It supports '*' in . func IsSubDomain(subDomain string, mainDomain string) bool { + if p := strings.IndexByte(subDomain, ':'); p != -1 { + subDomain = subDomain[0:p] + } + if p := strings.IndexByte(mainDomain, ':'); p != -1 { + mainDomain = mainDomain[0:p] + } subArray := strings.Split(subDomain, ".") mainArray := strings.Split(mainDomain, ".") subLength := len(subArray) diff --git a/text/gstr/gstr_z_unit_domain_test.go b/text/gstr/gstr_z_unit_domain_test.go index c82c75bd5..e6797be2f 100644 --- a/text/gstr/gstr_z_unit_domain_test.go +++ b/text/gstr/gstr_z_unit_domain_test.go @@ -21,6 +21,7 @@ func Test_IsSubDomain(t *testing.T) { gtest.Assert(gstr.IsSubDomain("goframe.org", main), true) gtest.Assert(gstr.IsSubDomain("s.goframe.org", main), true) gtest.Assert(gstr.IsSubDomain("s.s.goframe.org", main), true) + gtest.Assert(gstr.IsSubDomain("s.s.goframe.org:8080", main), true) gtest.Assert(gstr.IsSubDomain("johng.cn", main), false) gtest.Assert(gstr.IsSubDomain("s.johng.cn", main), false) gtest.Assert(gstr.IsSubDomain("s.s.johng.cn", main), false) @@ -29,6 +30,7 @@ func Test_IsSubDomain(t *testing.T) { main := "*.goframe.org" gtest.Assert(gstr.IsSubDomain("goframe.org", main), true) gtest.Assert(gstr.IsSubDomain("s.goframe.org", main), true) + gtest.Assert(gstr.IsSubDomain("s.goframe.org:80", main), true) gtest.Assert(gstr.IsSubDomain("s.s.goframe.org", main), false) gtest.Assert(gstr.IsSubDomain("johng.cn", main), false) gtest.Assert(gstr.IsSubDomain("s.johng.cn", main), false) @@ -39,6 +41,18 @@ func Test_IsSubDomain(t *testing.T) { gtest.Assert(gstr.IsSubDomain("goframe.org", main), true) gtest.Assert(gstr.IsSubDomain("s.goframe.org", main), true) gtest.Assert(gstr.IsSubDomain("s.s.goframe.org", main), true) + gtest.Assert(gstr.IsSubDomain("s.s.goframe.org:8000", main), true) + gtest.Assert(gstr.IsSubDomain("s.s.s.goframe.org", main), false) + gtest.Assert(gstr.IsSubDomain("johng.cn", main), false) + gtest.Assert(gstr.IsSubDomain("s.johng.cn", main), false) + gtest.Assert(gstr.IsSubDomain("s.s.johng.cn", main), false) + }) + gtest.Case(t, func() { + main := "*.*.goframe.org:8080" + gtest.Assert(gstr.IsSubDomain("goframe.org", main), true) + gtest.Assert(gstr.IsSubDomain("s.goframe.org", main), true) + gtest.Assert(gstr.IsSubDomain("s.s.goframe.org", main), true) + gtest.Assert(gstr.IsSubDomain("s.s.goframe.org:8000", main), true) gtest.Assert(gstr.IsSubDomain("s.s.s.goframe.org", main), false) gtest.Assert(gstr.IsSubDomain("johng.cn", main), false) gtest.Assert(gstr.IsSubDomain("s.johng.cn", main), false) diff --git a/util/grand/grand_intn.go b/util/grand/grand_intn.go index f362a0de5..22b312637 100644 --- a/util/grand/grand_intn.go +++ b/util/grand/grand_intn.go @@ -58,9 +58,13 @@ func init() { // Intn returns a int number which is between 0 and max - [0, max). // // Note: -// 1. The result is greater than or equal to 0, but less than ; -// 2. The result number is 32bit and less than math.MaxUint32. +// 1. The can only be geater than 0, or else it return directly; +// 2. The result is greater than or equal to 0, but less than ; +// 3. The result number is 32bit and less than math.MaxUint32. func Intn(max int) int { + if max <= 0 { + return max + } n := int(<-bufferChan) % max if (max > 0 && n < 0) || (max < 0 && n > 0) { return -n