mirror of https://github.com/beego/bee.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
666 lines
16 KiB
666 lines
16 KiB
// Copyright 2013 bee authors |
|
// |
|
// Licensed under the Apache License, Version 2.0 (the "License"): you may |
|
// not use this file except in compliance with the License. You may obtain |
|
// a copy of the License at |
|
// |
|
// http://www.apache.org/licenses/LICENSE-2.0 |
|
// |
|
// Unless required by applicable law or agreed to in writing, software |
|
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
|
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
|
// License for the specific language governing permissions and limitations |
|
// under the License. |
|
|
|
package main |
|
|
|
import ( |
|
"fmt" |
|
"os" |
|
path "path/filepath" |
|
"strings" |
|
) |
|
|
|
var cmdApiapp = &Command{ |
|
// CustomFlags: true, |
|
UsageLine: "api [appname]", |
|
Short: "create an api application base on beego framework", |
|
Long: ` |
|
create an api application base on beego framework |
|
|
|
bee api [appname] [-tables=""] [-driver=mysql] [-conn=root:@tcp(127.0.0.1:3306)/test] |
|
-tables: a list of table names separated by ',', default is empty, indicating all tables |
|
-driver: [mysql | postgresql | sqlite], the default is mysql |
|
-conn: the connection string used by the driver, the default is '' |
|
|
|
if conn is empty will create a example api application. otherwise generate api application based on an existing database. |
|
|
|
In the current path, will create a folder named [appname] |
|
|
|
In the appname folder has the follow struct: |
|
|
|
├── conf |
|
│ └── app.conf |
|
├── controllers |
|
│ └── object.go |
|
│ └── user.go |
|
├── routers |
|
│ └── router.go |
|
├── tests |
|
│ └── default_test.go |
|
├── main.go |
|
└── models |
|
└── object.go |
|
└── user.go |
|
|
|
`, |
|
} |
|
|
|
var apiconf = `appname = {{.Appname}} |
|
httpport = 8080 |
|
runmode = dev |
|
autorender = false |
|
copyrequestbody = true |
|
EnableDocs = true |
|
` |
|
var apiMaingo = `package main |
|
|
|
import ( |
|
_ "{{.Appname}}/docs" |
|
_ "{{.Appname}}/routers" |
|
|
|
"github.com/astaxie/beego" |
|
) |
|
|
|
func main() { |
|
if beego.RunMode == "dev" { |
|
beego.DirectoryIndex = true |
|
beego.StaticDir["/swagger"] = "swagger" |
|
} |
|
beego.Run() |
|
} |
|
` |
|
|
|
var apiMainconngo = `package main |
|
|
|
import ( |
|
_ "{{.Appname}}/docs" |
|
_ "{{.Appname}}/routers" |
|
|
|
"github.com/astaxie/beego" |
|
"github.com/astaxie/beego/orm" |
|
_ "github.com/go-sql-driver/mysql" |
|
) |
|
|
|
func init() { |
|
orm.RegisterDataBase("default", "mysql", "{{.conn}}") |
|
} |
|
|
|
func main() { |
|
if beego.RunMode == "dev" { |
|
beego.DirectoryIndex = true |
|
beego.StaticDir["/swagger"] = "swagger" |
|
} |
|
beego.Run() |
|
} |
|
|
|
` |
|
|
|
var apirouter = `// @APIVersion 1.0.0 |
|
// @Title beego Test API |
|
// @Description beego has a very cool tools to autogenerate documents for your API |
|
// @Contact astaxie@gmail.com |
|
// @TermsOfServiceUrl http://beego.me/ |
|
// @License Apache 2.0 |
|
// @LicenseUrl http://www.apache.org/licenses/LICENSE-2.0.html |
|
package routers |
|
|
|
import ( |
|
"{{.Appname}}/controllers" |
|
|
|
"github.com/astaxie/beego" |
|
) |
|
|
|
func init() { |
|
ns := beego.NewNamespace("/v1", |
|
beego.NSNamespace("/object", |
|
beego.NSInclude( |
|
&controllers.ObjectController{}, |
|
), |
|
), |
|
beego.NSNamespace("/user", |
|
beego.NSInclude( |
|
&controllers.UserController{}, |
|
), |
|
), |
|
) |
|
beego.AddNamespace(ns) |
|
} |
|
` |
|
|
|
var apiModels = `package models |
|
|
|
import ( |
|
"errors" |
|
"strconv" |
|
"time" |
|
) |
|
|
|
var ( |
|
Objects map[string]*Object |
|
) |
|
|
|
type Object struct { |
|
ObjectId string |
|
Score int64 |
|
PlayerName string |
|
} |
|
|
|
func init() { |
|
Objects = make(map[string]*Object) |
|
Objects["hjkhsbnmn123"] = &Object{"hjkhsbnmn123", 100, "astaxie"} |
|
Objects["mjjkxsxsaa23"] = &Object{"mjjkxsxsaa23", 101, "someone"} |
|
} |
|
|
|
func AddOne(object Object) (ObjectId string) { |
|
object.ObjectId = "astaxie" + strconv.FormatInt(time.Now().UnixNano(), 10) |
|
Objects[object.ObjectId] = &object |
|
return object.ObjectId |
|
} |
|
|
|
func GetOne(ObjectId string) (object *Object, err error) { |
|
if v, ok := Objects[ObjectId]; ok { |
|
return v, nil |
|
} |
|
return nil, errors.New("ObjectId Not Exist") |
|
} |
|
|
|
func GetAll() map[string]*Object { |
|
return Objects |
|
} |
|
|
|
func Update(ObjectId string, Score int64) (err error) { |
|
if v, ok := Objects[ObjectId]; ok { |
|
v.Score = Score |
|
return nil |
|
} |
|
return errors.New("ObjectId Not Exist") |
|
} |
|
|
|
func Delete(ObjectId string) { |
|
delete(Objects, ObjectId) |
|
} |
|
|
|
` |
|
|
|
var apiModels2 = `package models |
|
|
|
import ( |
|
"errors" |
|
"strconv" |
|
"time" |
|
) |
|
|
|
var ( |
|
UserList map[string]*User |
|
) |
|
|
|
func init() { |
|
UserList = make(map[string]*User) |
|
u := User{"user_11111", "astaxie", "11111", Profile{"male", 20, "Singapore", "astaxie@gmail.com"}} |
|
UserList["user_11111"] = &u |
|
} |
|
|
|
type User struct { |
|
Id string |
|
Username string |
|
Password string |
|
Profile Profile |
|
} |
|
|
|
type Profile struct { |
|
Gender string |
|
Age int |
|
Address string |
|
Email string |
|
} |
|
|
|
func AddUser(u User) string { |
|
u.Id = "user_" + strconv.FormatInt(time.Now().UnixNano(), 10) |
|
UserList[u.Id] = &u |
|
return u.Id |
|
} |
|
|
|
func GetUser(uid string) (u *User, err error) { |
|
if u, ok := UserList[uid]; ok { |
|
return u, nil |
|
} |
|
return nil, errors.New("User not exists") |
|
} |
|
|
|
func GetAllUsers() map[string]*User { |
|
return UserList |
|
} |
|
|
|
func UpdateUser(uid string, uu *User) (a *User, err error) { |
|
if u, ok := UserList[uid]; ok { |
|
if uu.Username != "" { |
|
u.Username = uu.Username |
|
} |
|
if uu.Password != "" { |
|
u.Password = uu.Password |
|
} |
|
if uu.Profile.Age != 0 { |
|
u.Profile.Age = uu.Profile.Age |
|
} |
|
if uu.Profile.Address != "" { |
|
u.Profile.Address = uu.Profile.Address |
|
} |
|
if uu.Profile.Gender != "" { |
|
u.Profile.Gender = uu.Profile.Gender |
|
} |
|
if uu.Profile.Email != "" { |
|
u.Profile.Email = uu.Profile.Email |
|
} |
|
return u, nil |
|
} |
|
return nil, errors.New("User Not Exist") |
|
} |
|
|
|
func Login(username, password string) bool { |
|
for _, u := range UserList { |
|
if u.Username == username && u.Password == password { |
|
return true |
|
} |
|
} |
|
return false |
|
} |
|
|
|
func DeleteUser(uid string) { |
|
delete(UserList, uid) |
|
} |
|
` |
|
|
|
var apiControllers = `package controllers |
|
|
|
import ( |
|
"{{.Appname}}/models" |
|
"encoding/json" |
|
|
|
"github.com/astaxie/beego" |
|
) |
|
|
|
// Operations about object |
|
type ObjectController struct { |
|
beego.Controller |
|
} |
|
|
|
// @Title create |
|
// @Description create object |
|
// @Param body body models.Object true "The object content" |
|
// @Success 200 {string} models.Object.Id |
|
// @Failure 403 body is empty |
|
// @router / [post] |
|
func (this *ObjectController) Post() { |
|
var ob models.Object |
|
json.Unmarshal(this.Ctx.Input.RequestBody, &ob) |
|
objectid := models.AddOne(ob) |
|
this.Data["json"] = map[string]string{"ObjectId": objectid} |
|
this.ServeJson() |
|
} |
|
|
|
// @Title Get |
|
// @Description find object by objectid |
|
// @Param objectId path string true "the objectid you want to get" |
|
// @Success 200 {object} models.Object |
|
// @Failure 403 :objectId is empty |
|
// @router /:objectId [get] |
|
func (this *ObjectController) Get() { |
|
objectId := this.Ctx.Input.Params[":objectId"] |
|
if objectId != "" { |
|
ob, err := models.GetOne(objectId) |
|
if err != nil { |
|
this.Data["json"] = err |
|
} else { |
|
this.Data["json"] = ob |
|
} |
|
} |
|
this.ServeJson() |
|
} |
|
|
|
// @Title GetAll |
|
// @Description get all objects |
|
// @Success 200 {object} models.Object |
|
// @Failure 403 :objectId is empty |
|
// @router / [get] |
|
func (this *ObjectController) GetAll() { |
|
obs := models.GetAll() |
|
this.Data["json"] = obs |
|
this.ServeJson() |
|
} |
|
|
|
// @Title update |
|
// @Description update the object |
|
// @Param objectId path string true "The objectid you want to update" |
|
// @Param body body models.Object true "The body" |
|
// @Success 200 {object} models.Object |
|
// @Failure 403 :objectId is empty |
|
// @router /:objectId [put] |
|
func (this *ObjectController) Put() { |
|
objectId := this.Ctx.Input.Params[":objectId"] |
|
var ob models.Object |
|
json.Unmarshal(this.Ctx.Input.RequestBody, &ob) |
|
|
|
err := models.Update(objectId, ob.Score) |
|
if err != nil { |
|
this.Data["json"] = err |
|
} else { |
|
this.Data["json"] = "update success!" |
|
} |
|
this.ServeJson() |
|
} |
|
|
|
// @Title delete |
|
// @Description delete the object |
|
// @Param objectId path string true "The objectId you want to delete" |
|
// @Success 200 {string} delete success! |
|
// @Failure 403 objectId is empty |
|
// @router /:objectId [delete] |
|
func (this *ObjectController) Delete() { |
|
objectId := this.Ctx.Input.Params[":objectId"] |
|
models.Delete(objectId) |
|
this.Data["json"] = "delete success!" |
|
this.ServeJson() |
|
} |
|
|
|
` |
|
var apiControllers2 = `package controllers |
|
|
|
import ( |
|
"{{.Appname}}/models" |
|
"encoding/json" |
|
|
|
"github.com/astaxie/beego" |
|
) |
|
|
|
// Operations about Users |
|
type UserController struct { |
|
beego.Controller |
|
} |
|
|
|
// @Title createUser |
|
// @Description create users |
|
// @Param body body models.User true "body for user content" |
|
// @Success 200 {int} models.User.Id |
|
// @Failure 403 body is empty |
|
// @router / [post] |
|
func (u *UserController) Post() { |
|
var user models.User |
|
json.Unmarshal(u.Ctx.Input.RequestBody, &user) |
|
uid := models.AddUser(user) |
|
u.Data["json"] = map[string]string{"uid": uid} |
|
u.ServeJson() |
|
} |
|
|
|
// @Title Get |
|
// @Description get all Users |
|
// @Success 200 {object} models.User |
|
// @router / [get] |
|
func (u *UserController) GetAll() { |
|
users := models.GetAllUsers() |
|
u.Data["json"] = users |
|
u.ServeJson() |
|
} |
|
|
|
// @Title Get |
|
// @Description get user by uid |
|
// @Param uid path string true "The key for staticblock" |
|
// @Success 200 {object} models.User |
|
// @Failure 403 :uid is empty |
|
// @router /:uid [get] |
|
func (u *UserController) Get() { |
|
uid := u.GetString(":uid") |
|
if uid != "" { |
|
user, err := models.GetUser(uid) |
|
if err != nil { |
|
u.Data["json"] = err |
|
} else { |
|
u.Data["json"] = user |
|
} |
|
} |
|
u.ServeJson() |
|
} |
|
|
|
// @Title update |
|
// @Description update the user |
|
// @Param uid path string true "The uid you want to update" |
|
// @Param body body models.User true "body for user content" |
|
// @Success 200 {object} models.User |
|
// @Failure 403 :uid is not int |
|
// @router /:uid [put] |
|
func (u *UserController) Put() { |
|
uid := u.GetString(":uid") |
|
if uid != "" { |
|
var user models.User |
|
json.Unmarshal(u.Ctx.Input.RequestBody, &user) |
|
uu, err := models.UpdateUser(uid, &user) |
|
if err != nil { |
|
u.Data["json"] = err |
|
} else { |
|
u.Data["json"] = uu |
|
} |
|
} |
|
u.ServeJson() |
|
} |
|
|
|
// @Title delete |
|
// @Description delete the user |
|
// @Param uid path string true "The uid you want to delete" |
|
// @Success 200 {string} delete success! |
|
// @Failure 403 uid is empty |
|
// @router /:uid [delete] |
|
func (u *UserController) Delete() { |
|
uid := u.GetString(":uid") |
|
models.DeleteUser(uid) |
|
u.Data["json"] = "delete success!" |
|
u.ServeJson() |
|
} |
|
|
|
// @Title login |
|
// @Description Logs user into the system |
|
// @Param username query string true "The username for login" |
|
// @Param password query string true "The password for login" |
|
// @Success 200 {string} lonin success |
|
// @Failure 403 user not exist |
|
// @router /login [get] |
|
func (u *UserController) Login() { |
|
username := u.GetString("username") |
|
password := u.GetString("password") |
|
if models.Login(username, password) { |
|
u.Data["json"] = "login success" |
|
} else { |
|
u.Data["json"] = "user not exist" |
|
} |
|
u.ServeJson() |
|
} |
|
|
|
// @Title logout |
|
// @Description Logs out current logged in user session |
|
// @Success 200 {string} logout success |
|
// @router /logout [get] |
|
func (u *UserController) Logout() { |
|
u.Data["json"] = "logout success" |
|
u.ServeJson() |
|
} |
|
|
|
` |
|
|
|
var apiTests = `package test |
|
|
|
import ( |
|
"net/http" |
|
"net/http/httptest" |
|
"testing" |
|
"runtime" |
|
"path/filepath" |
|
_ "{{.Appname}}/routers" |
|
|
|
"github.com/astaxie/beego" |
|
. "github.com/smartystreets/goconvey/convey" |
|
) |
|
|
|
func init() { |
|
_, file, _, _ := runtime.Caller(1) |
|
apppath, _ := filepath.Abs(filepath.Dir(filepath.Join(file, ".." + string(filepath.Separator)))) |
|
beego.TestBeegoInit(apppath) |
|
} |
|
|
|
// TestGet is a sample to run an endpoint test |
|
func TestGet(t *testing.T) { |
|
r, _ := http.NewRequest("GET", "/object", nil) |
|
w := httptest.NewRecorder() |
|
beego.BeeApp.Handlers.ServeHTTP(w, r) |
|
|
|
beego.Trace("testing", "TestGet", "Code[%d]\n%s", w.Code, w.Body.String()) |
|
|
|
Convey("Subject: Test Station Endpoint\n", t, func() { |
|
Convey("Status Code Should Be 200", func() { |
|
So(w.Code, ShouldEqual, 200) |
|
}) |
|
Convey("The Result Should Not Be Empty", func() { |
|
So(w.Body.Len(), ShouldBeGreaterThan, 0) |
|
}) |
|
}) |
|
} |
|
|
|
` |
|
|
|
func init() { |
|
cmdApiapp.Run = createapi |
|
cmdApiapp.Flag.Var(&tables, "tables", "specify tables to generate model") |
|
cmdApiapp.Flag.Var(&driver, "driver", "database driver: mysql, postgresql, etc.") |
|
cmdApiapp.Flag.Var(&conn, "conn", "connection string used by the driver to connect to a database instance") |
|
} |
|
|
|
func createapi(cmd *Command, args []string) int { |
|
curpath, _ := os.Getwd() |
|
if len(args) > 1 { |
|
cmd.Flag.Parse(args[1:]) |
|
} |
|
apppath, packpath, err := checkEnv(args[0]) |
|
if err != nil { |
|
fmt.Println(err) |
|
os.Exit(2) |
|
} |
|
if driver == "" { |
|
driver = "mysql" |
|
} |
|
if conn == "" { |
|
} |
|
os.MkdirAll(apppath, 0755) |
|
fmt.Println("create app folder:", apppath) |
|
os.Mkdir(path.Join(apppath, "conf"), 0755) |
|
fmt.Println("create conf:", path.Join(apppath, "conf")) |
|
os.Mkdir(path.Join(apppath, "controllers"), 0755) |
|
fmt.Println("create controllers:", path.Join(apppath, "controllers")) |
|
os.Mkdir(path.Join(apppath, "docs"), 0755) |
|
fmt.Println("create docs:", path.Join(apppath, "docs")) |
|
os.Mkdir(path.Join(apppath, "tests"), 0755) |
|
fmt.Println("create tests:", path.Join(apppath, "tests")) |
|
|
|
fmt.Println("create conf app.conf:", path.Join(apppath, "conf", "app.conf")) |
|
writetofile(path.Join(apppath, "conf", "app.conf"), |
|
strings.Replace(apiconf, "{{.Appname}}", args[0], -1)) |
|
|
|
if conn != "" { |
|
fmt.Println("create main.go:", path.Join(apppath, "main.go")) |
|
writetofile(path.Join(apppath, "main.go"), |
|
strings.Replace( |
|
strings.Replace(apiMainconngo, "{{.Appname}}", packpath, -1), |
|
"{{.conn}}", |
|
conn.String(), |
|
-1, |
|
), |
|
) |
|
ColorLog("[INFO] Using '%s' as 'driver'\n", driver) |
|
ColorLog("[INFO] Using '%s' as 'conn'\n", conn) |
|
ColorLog("[INFO] Using '%s' as 'tables'", tables) |
|
generateAppcode(string(driver), string(conn), "3", string(tables), path.Join(curpath, packpath)) |
|
} else { |
|
os.Mkdir(path.Join(apppath, "models"), 0755) |
|
fmt.Println("create models:", path.Join(apppath, "models")) |
|
os.Mkdir(path.Join(apppath, "routers"), 0755) |
|
fmt.Println(path.Join(apppath, "routers") + string(path.Separator)) |
|
|
|
fmt.Println("create controllers object.go:", path.Join(apppath, "controllers", "object.go")) |
|
writetofile(path.Join(apppath, "controllers", "object.go"), |
|
strings.Replace(apiControllers, "{{.Appname}}", packpath, -1)) |
|
|
|
fmt.Println("create controllers user.go:", path.Join(apppath, "controllers", "user.go")) |
|
writetofile(path.Join(apppath, "controllers", "user.go"), |
|
strings.Replace(apiControllers2, "{{.Appname}}", packpath, -1)) |
|
|
|
fmt.Println("create tests default.go:", path.Join(apppath, "tests", "default_test.go")) |
|
writetofile(path.Join(apppath, "tests", "default_test.go"), |
|
strings.Replace(apiTests, "{{.Appname}}", packpath, -1)) |
|
|
|
fmt.Println("create routers router.go:", path.Join(apppath, "routers", "router.go")) |
|
writetofile(path.Join(apppath, "routers", "router.go"), |
|
strings.Replace(apirouter, "{{.Appname}}", packpath, -1)) |
|
|
|
fmt.Println("create models object.go:", path.Join(apppath, "models", "object.go")) |
|
writetofile(path.Join(apppath, "models", "object.go"), apiModels) |
|
|
|
fmt.Println("create models user.go:", path.Join(apppath, "models", "user.go")) |
|
writetofile(path.Join(apppath, "models", "user.go"), apiModels2) |
|
|
|
fmt.Println("create docs doc.go:", path.Join(apppath, "docs", "doc.go")) |
|
writetofile(path.Join(apppath, "docs", "doc.go"), "package docs") |
|
|
|
fmt.Println("create main.go:", path.Join(apppath, "main.go")) |
|
writetofile(path.Join(apppath, "main.go"), |
|
strings.Replace(apiMaingo, "{{.Appname}}", packpath, -1)) |
|
} |
|
return 0 |
|
} |
|
|
|
func checkEnv(appname string) (apppath, packpath string, err error) { |
|
curpath, err := os.Getwd() |
|
if err != nil { |
|
return |
|
} |
|
|
|
gopath := os.Getenv("GOPATH") |
|
Debugf("gopath:%s", gopath) |
|
if gopath == "" { |
|
err = fmt.Errorf("you should set GOPATH in the env") |
|
return |
|
} |
|
|
|
appsrcpath := "" |
|
haspath := false |
|
wgopath := path.SplitList(gopath) |
|
for _, wg := range wgopath { |
|
wg, _ = path.EvalSymlinks(path.Join(wg, "src")) |
|
|
|
if path.HasPrefix(strings.ToLower(curpath), strings.ToLower(wg)) { |
|
haspath = true |
|
appsrcpath = wg |
|
break |
|
} |
|
} |
|
|
|
if !haspath { |
|
err = fmt.Errorf("can't create application outside of GOPATH `%s`\n"+ |
|
"you first should `cd $GOPATH%ssrc` then use create\n", gopath, string(path.Separator)) |
|
return |
|
} |
|
apppath = path.Join(curpath, appname) |
|
|
|
if _, e := os.Stat(apppath); os.IsNotExist(e) == false { |
|
err = fmt.Errorf("path `%s` exists, can not create app without remove it\n", apppath) |
|
return |
|
} |
|
packpath = strings.Join(strings.Split(apppath[len(appsrcpath)+1:], string(path.Separator)), "/") |
|
return |
|
}
|
|
|