update travis for adding mysql password; add custom view feature for ghttp.Response

This commit is contained in:
john 2019-11-20 12:09:26 +08:00
parent a4f191c1c6
commit ad540f7c25
11 changed files with 83 additions and 75 deletions

View File

@ -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:

View File

@ -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')

View File

@ -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)

View File

@ -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))

View File

@ -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)

View File

@ -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})

View File

@ -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()
}

View File

@ -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

View File

@ -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 <params> 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 <params> 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 <params> 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 <tpl> with given template variables <params>
// 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 <file> with given template parameters <params>
// 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 <params> 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 {

View File

@ -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.

View File

@ -48,9 +48,8 @@ type fileCacheItem struct {
content string
}
// ParseContent parses given template file <file>
// with given template parameters <params> and function map <funcMap>
// and returns the parsed string content.
// Parse parses given template file <file> with given template variables <params>
// 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 <content>
// with given template parameters <params> and function map <funcMap>
// ParseContent parses given template content <content> with template variables <params>
// 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 <path>.
// It uses template cache to enhance performance, that is, it will return the same template object
// with the same given <path>. It will also refresh the template cache
// with the same given <path>. It will also automatically refresh the template cache
// if the template files under <path> 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 <file>, and its template folder path.
// searchFile returns the found absolute path for <file> 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() {