diff --git a/.travis.yml b/.travis.yml index d5980d1e5..56e65d817 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,6 +32,7 @@ install: before_script: - find . -name "*.go" | xargs gofmt -w - git diff --name-only --exit-code || exit 1 +- echo "USE mysql;\nUPDATE user SET password=PASSWORD('12345678') WHERE user='root';\nFLUSH PRIVILEGES;\n" | mysql -u root - psql -c 'create database travis_ci_test;' -U postgres script: diff --git a/database/gdb/gdb_unit_init_mssql_test.go b/database/gdb/gdb_unit_init_mssql_test.go index de1d44801..af13afb14 100644 --- a/database/gdb/gdb_unit_init_mssql_test.go +++ b/database/gdb/gdb_unit_init_mssql_test.go @@ -16,7 +16,6 @@ import ( ) var ( - // 数据库对象/接口 msdb gdb.DB ) @@ -44,7 +43,6 @@ func InitMssql() { msdb = r } - // 创建默认用户表 createTableMssql("t_user") //msdb.SetDebug(true) } @@ -74,7 +72,6 @@ func createTableMssql(table ...string) (name string) { //msdb.Exec("DROP DATABASE test") //msdb.Exec("CREATE DATABASE test") - // 选择操作数据库 msdb.SetSchema("test") //msdb.SetDebug(true) @@ -102,7 +99,6 @@ func createInitTableMssql(table ...string) (name string) { return } -// 删除指定表. func dropTableMssql(table string) { if _, err := msdb.Exec(fmt.Sprintf(` IF EXISTS (SELECT * FROM sysobjects WHERE name='%s' and xtype='U') diff --git a/database/gdb/gdb_unit_init_mysql_test.go b/database/gdb/gdb_unit_init_mysql_test.go index c55e44fdc..2fcfcb868 100644 --- a/database/gdb/gdb_unit_init_mysql_test.go +++ b/database/gdb/gdb_unit_init_mysql_test.go @@ -8,8 +8,6 @@ package gdb_test import ( "fmt" - "os" - "github.com/gogf/gf/container/garray" "github.com/gogf/gf/frame/g" @@ -19,25 +17,22 @@ import ( ) const ( - INIT_DATA_SIZE = 10 // 初始化表数据量 - TABLE = "user" // 测试数据表 - SCHEMA1 = "test1" // 测试数据库1 - SCHEMA2 = "test2" // 测试数据库2 + INIT_DATA_SIZE = 10 + TABLE = "user" + SCHEMA1 = "test1" + SCHEMA2 = "test2" ) var ( - // 测试包变量,ORM对象 db gdb.DB ) -// 初始化连接参数。 -// 测试前需要修改连接参数。 func InitMysql() { node := gdb.ConfigNode{ Host: "127.0.0.1", Port: "3306", User: "root", - Pass: "", + Pass: "12345678", Name: "", Type: "mysql", Role: "master", @@ -47,10 +42,6 @@ func InitMysql() { MaxOpenConnCount: 10, MaxConnLifetime: 600, } - // 作者本地测试hack - if hostname, _ := os.Hostname(); hostname == "ijohn" { - node.Pass = "12345678" - } gdb.AddConfigNode("test", node) gdb.AddConfigNode(gdb.DEFAULT_GROUP_NAME, node) if r, err := gdb.New(); err != nil { @@ -58,24 +49,21 @@ func InitMysql() { } else { db = r } - // 准备测试数据结构:数据库 + schemaTemplate := "CREATE DATABASE IF NOT EXISTS `%s` CHARACTER SET UTF8" if _, err := db.Exec(fmt.Sprintf(schemaTemplate, SCHEMA1)); err != nil { gtest.Error(err) } - // 多个数据库,用于测试数据库切换 + if _, err := db.Exec(fmt.Sprintf(schemaTemplate, SCHEMA2)); err != nil { gtest.Error(err) } - // 设置默认操作数据库 + db.SetSchema(SCHEMA1) - // 创建默认用户表 + createTable(TABLE) } -// 创建指定名称的user测试表,当table为空时,创建随机的表名。 -// 创建的测试表默认没有任何数据。 -// 执行完成后返回该表名。 func createTable(table ...string) (name string) { if len(table) > 0 { name = table[0] @@ -85,11 +73,11 @@ func createTable(table ...string) (name string) { dropTable(name) if _, err := db.Exec(fmt.Sprintf(` CREATE TABLE %s ( - id int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '用户ID', - passport varchar(45) NULL COMMENT '账号', - password char(32) NULL COMMENT '密码', - nickname varchar(45) NULL COMMENT '昵称', - create_time timestamp NULL COMMENT '创建时间/注册时间', + id int(10) unsigned NOT NULL AUTO_INCREMENT, + passport varchar(45) NULL, + password char(32) NULL, + nickname varchar(45) NULL, + create_time timestamp NULL, PRIMARY KEY (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; `, name)); err != nil { @@ -98,7 +86,6 @@ func createTable(table ...string) (name string) { return } -// 创建测试表,并初始化默认数据。 func createInitTable(table ...string) (name string) { name = createTable(table...) array := garray.New(true) @@ -120,7 +107,6 @@ func createInitTable(table ...string) (name string) { return } -// 删除指定表. func dropTable(table string) { if _, err := db.Exec(fmt.Sprintf("DROP TABLE IF EXISTS `%s`", table)); err != nil { gtest.Error(err) diff --git a/database/gdb/gdb_unit_init_oracle_test.go b/database/gdb/gdb_unit_init_oracle_test.go index e110c819e..6e9e56f13 100644 --- a/database/gdb/gdb_unit_init_oracle_test.go +++ b/database/gdb/gdb_unit_init_oracle_test.go @@ -17,7 +17,6 @@ import ( ) var ( - // 数据库对象/接口 oradb gdb.DB ) @@ -46,7 +45,6 @@ func InitOracle() { oradb = r } - // 创建默认用户表 createTableOracle("t_user") } @@ -94,7 +92,6 @@ func createInitTableOracle(table ...string) (name string) { return } -// 删除指定表. func dropTableOracle(table string) { count, err := oradb.GetCount("SELECT COUNT(*) FROM USER_TABLES WHERE TABLE_NAME = ?", strings.ToUpper(table)) diff --git a/database/gdb/gdb_unit_init_pgsql_test.go b/database/gdb/gdb_unit_init_pgsql_test.go index 5ba629a3b..72feabe29 100644 --- a/database/gdb/gdb_unit_init_pgsql_test.go +++ b/database/gdb/gdb_unit_init_pgsql_test.go @@ -16,12 +16,9 @@ import ( ) var ( - // 数据库对象/接口 pgdb gdb.DB ) -// 初始化连接参数。 -// 测试前需要修改连接参数。 func InitPgsql() { node := gdb.ConfigNode{ Host: "127.0.0.1", @@ -64,10 +61,6 @@ func InitPgsql() { } -// 创建指定名称的user测试表,当table为空时,创建随机的表名。 -// 创建的测试表默认没有任何数据。 -// 执行完成后返回该表名。 -// TODO 支持更多数据库 func createTablePgsql(table ...string) (name string) { if len(table) > 0 { name = table[0] @@ -91,7 +84,6 @@ func createTablePgsql(table ...string) (name string) { return } -// 创建测试表,并初始化默认数据。 func createInitTablePgsql(table ...string) (name string) { name = createTablePgsql(table...) array := garray.New(true) @@ -113,7 +105,6 @@ func createInitTablePgsql(table ...string) (name string) { return } -// 删除指定表. func dropTablePgsql(table string) { if _, err := pgdb.Exec(fmt.Sprintf("DROP TABLE IF EXISTS %s", table)); err != nil { gtest.Fatal(err) diff --git a/database/gdb/gdb_unit_z_mysql_model_test.go b/database/gdb/gdb_unit_z_mysql_model_test.go index 850b1413d..466a43cc4 100644 --- a/database/gdb/gdb_unit_z_mysql_model_test.go +++ b/database/gdb/gdb_unit_z_mysql_model_test.go @@ -315,6 +315,9 @@ func Test_Model_Safe(t *testing.T) { }) gtest.Case(t, func() { + table := createInitTable() + defer dropTable(table) + md1 := db.Table(table).Where("id>", 0).Safe() md2 := md1.Where("id in (?)", g.Slice{1, 3}) md3 := md1.Where("id in (?)", g.Slice{4, 5, 6}) diff --git a/net/ghttp/ghttp_response.go b/net/ghttp/ghttp_response.go index de3e1ccc3..0d9fd0ed4 100644 --- a/net/ghttp/ghttp_response.go +++ b/net/ghttp/ghttp_response.go @@ -11,6 +11,7 @@ import ( "bytes" "encoding/json" "fmt" + "github.com/gogf/gf/os/gview" "net/http" "github.com/gogf/gf/os/gres" @@ -20,13 +21,14 @@ import ( "github.com/gogf/gf/util/gconv" ) -// Response is the writer for response buffer. +// Response is the http response manager. // Note that it implements the http.ResponseWriter interface with buffering feature. type Response struct { *ResponseWriter // Underlying ResponseWriter. Server *Server // Parent server. Writer *ResponseWriter // Alias of ResponseWriter. Request *Request // According request. + view *gview.View // Custom template view engine object for this response. } // newResponse creates and returns a new Response object. @@ -162,7 +164,7 @@ func (r *Response) ServeFile(path string, allowIndex ...bool) { r.Server.serveFile(r.Request, serveFile, allowIndex...) } -// ServeFileDownload serves file as file downloading to the response. +// ServeFileDownload serves file downloading to the response. func (r *Response) ServeFileDownload(path string, name ...string) { serveFile := (*staticServeFile)(nil) downloadName := "" @@ -194,29 +196,29 @@ func (r *Response) ServeFileDownload(path string, name ...string) { r.Server.serveFile(r.Request, serveFile) } -// RedirectTo redirects client to another location. +// RedirectTo redirects client to another location using http status 302. func (r *Response) RedirectTo(location string) { r.Header().Set("Location", location) r.WriteHeader(http.StatusFound) r.Request.Exit() } -// RedirectBack redirects client back to referer. +// RedirectBack redirects client back to referer using http status 302. func (r *Response) RedirectBack() { r.RedirectTo(r.Request.GetReferer()) } -// BufferString returns the buffer content as []byte. +// BufferString returns the buffered content as []byte. func (r *Response) Buffer() []byte { return r.buffer.Bytes() } -// BufferString returns the buffer content as string. +// BufferString returns the buffered content as string. func (r *Response) BufferString() string { return r.buffer.String() } -// BufferLength returns the length of the buffer content. +// BufferLength returns the length of the buffered content. func (r *Response) BufferLength() int { return r.buffer.Len() } @@ -237,6 +239,5 @@ func (r *Response) Output() { if r.Server.config.ServerAgent != "" { r.Header().Set("Server", r.Server.config.ServerAgent) } - //r.handleGzip() r.Writer.OutputBuffer() } diff --git a/net/ghttp/ghttp_response_cors.go b/net/ghttp/ghttp_response_cors.go index 5da9ad10b..88042785c 100644 --- a/net/ghttp/ghttp_response_cors.go +++ b/net/ghttp/ghttp_response_cors.go @@ -14,6 +14,7 @@ import ( "github.com/gogf/gf/util/gconv" ) +// CORSOptions is the options for CORS feature. // See https://www.w3.org/TR/cors/ . type CORSOptions struct { AllowDomain []string // Used for allowing requests from custom domains @@ -70,7 +71,7 @@ func (r *Response) CORS(options CORSOptions) { } } -// CORSAllowed checks whether the current request origin is allowed CORS. +// CORSAllowed checks whether the current request origin is allowed cross-domain. func (r *Response) CORSAllowedOrigin(options CORSOptions) bool { if options.AllowDomain == nil { return true diff --git a/net/ghttp/ghttp_response_view.go b/net/ghttp/ghttp_response_view.go index 8b2cd42b1..9f90e5142 100644 --- a/net/ghttp/ghttp_response_view.go +++ b/net/ghttp/ghttp_response_view.go @@ -13,7 +13,25 @@ import ( "github.com/gogf/gf/util/gmode" ) -// 展示模板,可以给定模板参数,及临时的自定义模板函数 +// SetView sets template view engine object for this response. +func (r *Response) SetView(view *gview.View) { + r.view = view +} + +// GetView returns the template view engine object for this response. +func (r *Response) GetView() *gview.View { + view := r.view + if view == nil { + view = r.Server.config.View + } + if view == nil { + gview.Instance() + } + return view +} + +// WriteTpl parses and responses given template file. +// The parameter specifies the template variables for parsing. func (r *Response) WriteTpl(tpl string, params ...gview.Params) error { if b, err := r.ParseTpl(tpl, params...); err != nil { if !gmode.IsProduct() { @@ -26,7 +44,22 @@ func (r *Response) WriteTpl(tpl string, params ...gview.Params) error { return nil } -// 展示模板内容,可以给定模板参数,及临时的自定义模板函数 +// WriteTplDefault parses and responses the default template file. +// The parameter specifies the template variables for parsing. +func (r *Response) WriteTplDefault(params ...gview.Params) error { + if b, err := r.ParseTplDefault(params...); err != nil { + if !gmode.IsProduct() { + r.Write("Template Parsing Error: " + err.Error()) + } + return err + } else { + r.Write(b) + } + return nil +} + +// WriteTplContent parses and responses the template content. +// The parameter specifies the template variables for parsing. func (r *Response) WriteTplContent(content string, params ...gview.Params) error { if b, err := r.ParseTplContent(content, params...); err != nil { if !gmode.IsProduct() { @@ -39,23 +72,24 @@ func (r *Response) WriteTplContent(content string, params ...gview.Params) error return nil } -// 解析模板文件,并返回模板内容 +// ParseTpl parses given template file with given template variables +// and returns the parsed template content. func (r *Response) ParseTpl(tpl string, params ...gview.Params) (string, error) { - if r.Server.config.View != nil { - return r.Server.config.View.Parse(tpl, r.buildInVars(params...)) - } - return gview.Instance().Parse(tpl, r.buildInVars(params...)) + return r.GetView().Parse(tpl, r.buildInVars(params...)) } -// 解析并返回模板内容 +// ParseDefault parses the default template file with params. +func (r *Response) ParseTplDefault(params ...gview.Params) (string, error) { + return r.GetView().ParseDefault(r.buildInVars(params...)) +} + +// ParseTplContent parses given template file with given template parameters +// and returns the parsed template content. func (r *Response) ParseTplContent(content string, params ...gview.Params) (string, error) { - if r.Server.config.View != nil { - return r.Server.config.View.ParseContent(content, r.buildInVars(params...)) - } - return gview.Instance().ParseContent(content, r.buildInVars(params...)) + return r.GetView().ParseContent(content, r.buildInVars(params...)) } -// 内置变量/对象 +// buildInVars merges build-in variables into and returns the new template variables. func (r *Response) buildInVars(params ...map[string]interface{}) map[string]interface{} { var vars map[string]interface{} if len(params) > 0 && params[0] != nil { diff --git a/net/ghttp/ghttp_response_writer.go b/net/ghttp/ghttp_response_writer.go index 722dee9d4..646596e46 100644 --- a/net/ghttp/ghttp_response_writer.go +++ b/net/ghttp/ghttp_response_writer.go @@ -14,13 +14,13 @@ import ( "net/http" ) -// Custom ResponseWriter, which is used for controlling the output buffer. +// ResponseWriter is the custom writer for http response. type ResponseWriter struct { Status int // HTTP status. writer http.ResponseWriter // The underlying ResponseWriter. buffer *bytes.Buffer // The output buffer. hijacked bool // Mark this request is hijacked or not. - wroteHeader bool // Is header wrote, avoiding error: superfluous/multiple response.WriteHeader call. + wroteHeader bool // Is header wrote or not, avoiding error: superfluous/multiple response.WriteHeader call. } // RawWriter returns the underlying ResponseWriter. diff --git a/os/gview/gview_doparse.go b/os/gview/gview_doparse.go index 0a5e548ad..348283416 100644 --- a/os/gview/gview_doparse.go +++ b/os/gview/gview_doparse.go @@ -48,9 +48,8 @@ type fileCacheItem struct { content string } -// ParseContent parses given template file -// with given template parameters and function map -// and returns the parsed string content. +// Parse parses given template file with given template variables +// and returns the parsed template content. func (view *View) Parse(file string, params ...Params) (result string, err error) { var tpl *template.Template // It caches the file, folder and its content to enhance performance. @@ -143,8 +142,7 @@ func (view *View) ParseDefault(params ...Params) (result string, err error) { return view.Parse(view.defaultFile, params...) } -// ParseContent parses given template content -// with given template parameters and function map +// ParseContent parses given template content with template variables // and returns the parsed content in []byte. func (view *View) ParseContent(content string, params ...Params) (string, error) { err := (error)(nil) @@ -201,7 +199,7 @@ func (view *View) ParseContent(content string, params ...Params) (string, error) // getTemplate returns the template object associated with given template folder . // It uses template cache to enhance performance, that is, it will return the same template object -// with the same given . It will also refresh the template cache +// with the same given . It will also automatically refresh the template cache // if the template files under changes (recursively). func (view *View) getTemplate(path string, pattern string) (tpl *template.Template, err error) { r := templates.GetOrSetFuncLock(path, func() interface{} { @@ -237,7 +235,7 @@ func (view *View) getTemplate(path string, pattern string) (tpl *template.Templa return } -// searchFile returns the found absolute path for , and its template folder path. +// searchFile returns the found absolute path for and its template folder path. func (view *View) searchFile(file string) (path string, folder string, resource *gres.File, err error) { // Firstly checking the resource manager. if !gres.IsEmpty() {