我正在研究PartyCon项目的服务器端部分。它是在Google App Engine平台上的Golang中编写的。我刚刚实现了一些完全可以在局部工作的新东西。但是,在部署时,我无法使用console.go脚本。
这是我的app.yaml配置(抱歉,这就是stackoverflow显示yaml文件的方式):
application: party-serverside version: alpha-1 runtime: go
api_version: go1
handlers:
#handlers for api
- url: /api/.*
script: api/api.go
#handlers for console and webpage routing
- url: /redirect
script: redirecter/redirecter.go
- url: /admin_console/choose
script: admin_console/choose.go
- url: /post-request
script: webpage/post-request.go
- url: /console
script: console/console.go
#handlers for static files
- url: /css/console.css
static_files: console/page/css/console.css upload: console/page/css/console.css
- url: /console/page
static_dir: console/page
- url: /
static_files: webpage/index.html
upload: webpage/index.html
- url: /
static_dir: webpage
- url: /css
static_dir: webpage/css
- url: /js
static_dir: webpage/js
- url: /img
static_dir: webpage/img
- url: /fonts
static_dir: webpage/fonts
我的console.go文件:
package console
import (
"appengine"
"appengine/user"
"database/sql"
_ "github.com/go-sql-driver/mysql"
"html/template"
"io/ioutil"
"net/http"
"strconv"
"time"
)
//for deployment
var dbConnectString string = "****************************"
//for local testing
//var dbConnectString string = "root@/party"
func init() {
http.HandleFunc("/console", consoleHandler)
}
func consoleHandler(w http.ResponseWriter, r *http.Request) {
redirectIfNeeded(w, r)
c := appengine.NewContext(r)
u := user.Current(c)
logoutUrl, e := user.LogoutURL(c, "/redirect")
if e != nil {
panic(e)
}
email := u.Email
data := WebpageData{LogoutUrl: logoutUrl, UserName: email, NewPartyUrl: "/console/newparty"}
template := template.Must(template.New("template").Parse(generateUnsignedHtml(u)))
err := template.Execute(w, data)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
func generateUnsignedHtml(u *user.User) string {
firstPart := fileValue("./console/page/firstPart.html")
table := generateTable(u)
secondPart := fileValue("./console/page/secondPart.html")
html := firstPart + table + secondPart
return html
}
func generateTable(u *user.User) string {
con, e := sql.Open("mysql", dbConnectString)
if e != nil {
panic(e)
}
defer con.Close()
var parties []Party
partyRows, err := con.Query("select id, name, datetime, host, location from parties where author='" + u.Email + "';")
if err != nil {
panic(err)
}
var id int
var name string
var datetime string
var host string
var location string
for partyRows.Next() {
partyRows.Scan(&id, &name, &datetime, &host, &location)
parties = append(parties, Party{Id: id, Name: name, DatetimeString: datetime, Host: host, Location: location})
}
html := ""
for i, party := range parties {
actionsHtml := "<a href=\"/console/edit?id=" + strconv.Itoa(party.Id) + "\" class=\"uk-button uk-button-primary editButton\">Edit</a> <a href=\"/console/delete?id=" + strconv.Itoa(party.Id) + "\" class=\"uk-button uk-button-danger\">Delete</a>"
html += "<tr>" + makeTd(strconv.Itoa(i+1)) + makeTd(party.Name) + makeTd(party.DatetimeString) + makeTd(party.Host) + makeTd(party.Location) + makeTd(actionsHtml) + "</tr>"
}
html += "</table>"
return html
}
func makeTd(content string) string {
return "<td>" + content + "</td>"
}
func redirectIfNeeded(w http.ResponseWriter, r *http.Request) {
expire := time.Date(2000, 1, 1, 1, 1, 1, 0, time.UTC)
cookie := &http.Cookie{Name: "ACSID", Value: "", Expires: expire, HttpOnly: true}
http.SetCookie(w, cookie)
cookie2 := &http.Cookie{Name: "SACSID", Value: "", Expires: expire, HttpOnly: true}
http.SetCookie(w, cookie2)
c := appengine.NewContext(r)
u := user.Current(c)
if u == nil {
url, err := user.LoginURL(c, r.URL.String())
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Location", url)
w.WriteHeader(http.StatusFound)
return
}
con, e := sql.Open("mysql", dbConnectString)
if e != nil {
panic(e)
}
defer con.Close()
//check whether user is admin
admRows, error := con.Query("select email from admin_users;")
if error != nil {
panic(error)
}
var email string
isAdmin := false
for admRows.Next() {
admRows.Scan(&email)
if email == u.Email {
isAdmin = true
}
}
//check if he is validated user
validRows, error2 := con.Query("select email from party_validated_users;")
if error2 != nil {
panic(error2)
}
email = ""
isValidated := false
for validRows.Next() {
validRows.Scan(&email)
if email == u.Email {
isValidated = true
}
}
var url string
if user.IsAdmin(c) || isAdmin {
//user is declared as admin in db or is admin of gae app
//we are allready here
url = "/console"
} else if isValidated {
//user is validated
//we are allready here
url = "/console"
} else {
//user is not validated yet
url = "/redirect"
w.Header().Set("Location", url)
w.WriteHeader(http.StatusFound)
}
}
func fileValue(path string) string {
content, err := ioutil.ReadFile(path)
if err != nil {
panic(err)
}
return string(content)
}
type WebpageData struct {
LogoutUrl string
UserName string
NewPartyUrl string
}
type Party struct {
Id int
Name string
DatetimeString string
Host string
Location string
}
知道为什么会这样吗?在此先感谢:)
答案 0 :(得分:2)
对于Go应用程序,set the script handler为“_go_app”。例如:
handlers:
url: /api/.*
script: _go_app
AppEngine将对Go应用程序的所有请求分派给单个已编译的可执行文件。这与Python不同,您可以为每个处理程序指定不同的脚本。