Go GAE app在本地工作,部署后我得到404 /没有

时间:2015-03-25 17:50:34

标签: google-app-engine go

我正在研究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
}

知道为什么会这样吗?在此先感谢:)

1 个答案:

答案 0 :(得分:2)

对于Go应用程序,set the script handler为“_go_app”。例如:

handlers:
    url: /api/.* 
    script: _go_app

AppEngine将对Go应用程序的所有请求分派给单个已编译的可执行文件。这与Python不同,您可以为每个处理程序指定不同的脚本。