aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gcloudignore2
-rw-r--r--.gitignore3
-rw-r--r--app.yaml17
-rw-r--r--appengine.go49
-rw-r--r--local.go34
5 files changed, 48 insertions, 57 deletions
diff --git a/.gcloudignore b/.gcloudignore
new file mode 100644
index 0000000..0030d4f
--- /dev/null
+++ b/.gcloudignore
@@ -0,0 +1,2 @@
+.gcloudignore
+.git
diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index d8c2c11..0000000
--- a/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-last-change
-*.orig
-*.rej
diff --git a/app.yaml b/app.yaml
index e6552eb..fcd8f17 100644
--- a/app.yaml
+++ b/app.yaml
@@ -1,12 +1,14 @@
service: tour
-runtime: go
-api_version: go1
+runtime: go111
-default_expiration: "7d"
+env_variables:
+ GOLANGORG_CHECK_COUNTRY: true
-handlers:
+default_expiration: "7d"
# Keep these static file handlers in sync with local.go.
+# They're here for improved latency across global regions.
+handlers:
- url: /favicon.ico
static_files: static/img/favicon.ico
upload: static/img/favicon.ico
@@ -16,11 +18,4 @@ handlers:
secure: always
- url: /static
static_dir: static
- application_readable: true
secure: always
-
-- url: /(.*|list|lesson/.*|compile|fmt|script\.js)
- script: _go_app
- secure: always
-
-nobuild_files: (solutions|content)/.*
diff --git a/appengine.go b/appengine.go
index 4767a2c..5db885b 100644
--- a/appengine.go
+++ b/appengine.go
@@ -2,56 +2,43 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build appengine
-
package main
import (
"bufio"
"bytes"
"io"
+ "log"
"net/http"
- "strings"
-
- "appengine"
+ "os"
_ "golang.org/x/tools/playground"
)
-const runUrl = "https://golang.org/compile"
-
-func init() {
- http.Handle("/lesson/", hstsHandler(lessonHandler))
- http.Handle("/", hstsHandler(rootHandler))
+func gaeMain() {
+ prepContent = gaePrepContent
+ socketAddr = gaeSocketAddr
if err := initTour(".", "HTTPTransport"); err != nil {
- panic(err)
+ log.Fatal(err)
}
-}
-func rootHandler(w http.ResponseWriter, r *http.Request) {
- c := appengine.NewContext(r)
- if err := renderUI(w); err != nil {
- c.Criticalf("UI render: %v", err)
- }
-}
+ http.Handle("/", hstsHandler(rootHandler))
+ http.Handle("/lesson/", hstsHandler(lessonHandler))
-func lessonHandler(w http.ResponseWriter, r *http.Request) {
- c := appengine.NewContext(r)
- lesson := strings.TrimPrefix(r.URL.Path, "/lesson/")
- if err := writeLesson(lesson, w); err != nil {
- if err == lessonNotFound {
- http.NotFound(w, r)
- } else {
- c.Criticalf("tour render: %v", err)
- }
+ registerStatic(".")
+
+ port := os.Getenv("PORT")
+ if port == "" {
+ port = "8080"
}
+ log.Fatal(http.ListenAndServe(":"+port, nil))
}
-// prepContent returns a Reader that produces the content from the given
+// gaePrepContent returns a Reader that produces the content from the given
// Reader, but strips the prefix "#appengine: " from each line. It also drops
// any non-blank like that follows a series of 1 or more lines with the prefix.
-func prepContent(in io.Reader) io.Reader {
+func gaePrepContent(in io.Reader) io.Reader {
var prefix = []byte("#appengine: ")
out, w := io.Pipe()
go func() {
@@ -84,9 +71,9 @@ func prepContent(in io.Reader) io.Reader {
return out
}
-// socketAddr returns the WebSocket handler address.
+// gaeSocketAddr returns the WebSocket handler address.
// The App Engine version does not provide a WebSocket handler.
-func socketAddr() string { return "" }
+func gaeSocketAddr() string { return "" }
// hstsHandler wraps an http.HandlerFunc such that it sets the HSTS header.
func hstsHandler(fn http.HandlerFunc) http.Handler {
diff --git a/local.go b/local.go
index 170dcf0..21421af 100644
--- a/local.go
+++ b/local.go
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build !appengine
-
package main
import (
@@ -31,7 +29,7 @@ import (
)
const (
- basePkg = "golang.org/x/tour/"
+ basePkg = "golang.org/x/tour"
socketPath = "/socket"
)
@@ -76,6 +74,12 @@ func findRoot() (string, error) {
func main() {
flag.Parse()
+ if os.Getenv("GAE_ENV") == "standard" {
+ log.Println("running in App Engine Standard mode")
+ gaeMain()
+ return
+ }
+
// find and serve the go tour files
root, err := findRoot()
if err != nil {
@@ -106,12 +110,7 @@ func main() {
origin := &url.URL{Scheme: "http", Host: host + ":" + port}
http.Handle(socketPath, socket.NewHandler(origin))
- // Keep these static file handlers in sync with app.yaml.
- static := http.FileServer(http.Dir(root))
- http.Handle("/content/img/", static)
- http.Handle("/static/", static)
- imgDir := filepath.Join(root, "static", "img")
- http.Handle("/favicon.ico", http.FileServer(http.Dir(imgDir)))
+ registerStatic(root)
go func() {
url := "http://" + httpAddr
@@ -124,6 +123,16 @@ func main() {
log.Fatal(http.ListenAndServe(httpAddr, nil))
}
+// registerStatic registers handlers to serve static content
+// from the directory root.
+func registerStatic(root string) {
+ // Keep these static file handlers in sync with app.yaml.
+ http.Handle("/favicon.ico", http.FileServer(http.Dir(filepath.Join(root, "static", "img"))))
+ static := http.FileServer(http.Dir(root))
+ http.Handle("/content/img/", static)
+ http.Handle("/static/", static)
+}
+
// rootHandler returns a handler for all the requests except the ones for lessons.
func rootHandler(w http.ResponseWriter, r *http.Request) {
if err := renderUI(w); err != nil {
@@ -146,7 +155,8 @@ func lessonHandler(w http.ResponseWriter, r *http.Request) {
const localhostWarning = `
WARNING! WARNING! WARNING!
-I appear to be listening on an address that is not localhost.
+The tour server appears to be listening on an address that is
+not localhost and is configured to run code snippets locally.
Anyone with access to this address and port will have access
to this machine as the user running gotour.
@@ -210,7 +220,7 @@ func startBrowser(url string) bool {
}
// prepContent for the local tour simply returns the content as-is.
-func prepContent(r io.Reader) io.Reader { return r }
+var prepContent = func(r io.Reader) io.Reader { return r }
// socketAddr returns the WebSocket handler address.
-func socketAddr() string { return "ws://" + httpAddr + socketPath }
+var socketAddr = func() string { return "ws://" + httpAddr + socketPath }