Initial work toward moving play.golang.org to App Engine Flex

Update golang/go#21645

Change-Id: I4c6273161e6d9224adaeb5b0d6b0ade526f383b5
Reviewed-on: https://go-review.googlesource.com/84676
Reviewed-by: Chris Broadfoot <cbro@golang.org>
diff --git a/app/app.yaml b/app/app.yaml
deleted file mode 100644
index 624ec4b..0000000
--- a/app/app.yaml
+++ /dev/null
@@ -1,19 +0,0 @@
-application: go-playground
-version: 1
-runtime: go
-api_version: go1
-
-handlers:
-- url: /favicon.ico
-  static_files: static/favicon.ico
-  upload: static/favicon.ico
-  secure: always
-- url: /static
-  static_dir: static
-  secure: always
-- url: /(|compile|fmt|share|playground.js)
-  script: _go_app
-  secure: always
-- url: /p/.+
-  script: _go_app
-  secure: always
diff --git a/app/goplay/compile.go b/app/goplay/compile.go
deleted file mode 100644
index 4cdfa1c..0000000
--- a/app/goplay/compile.go
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2011 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package goplay
-
-import (
-	"fmt"
-	"io"
-	"net/http"
-
-	"google.golang.org/appengine"
-	"google.golang.org/appengine/log"
-	"google.golang.org/appengine/urlfetch"
-)
-
-const runURL = "http://golang.org/compile?output=json"
-
-func init() {
-	http.Handle("/compile", hstsHandler(compile))
-}
-
-func compile(w http.ResponseWriter, r *http.Request) {
-	if r.Method != "POST" {
-		code := http.StatusMethodNotAllowed
-		http.Error(w, http.StatusText(code), code)
-		return
-	}
-	if err := passThru(w, r); err != nil {
-		w.WriteHeader(http.StatusInternalServerError)
-		fmt.Fprintln(w, "Compile server error.")
-	}
-}
-
-func passThru(w io.Writer, req *http.Request) error {
-	c := appengine.NewContext(req)
-	client := urlfetch.Client(c)
-	defer req.Body.Close()
-	r, err := client.Post(runURL, req.Header.Get("Content-type"), req.Body)
-	if err != nil {
-		log.Errorf(c, "making POST request: %v", err)
-		return err
-	}
-	defer r.Body.Close()
-	if _, err := io.Copy(w, r.Body); err != nil {
-		log.Errorf(c, "copying response Body: %v", err)
-		return err
-	}
-	return nil
-}
diff --git a/app/goplay/play.go b/app/goplay/play.go
deleted file mode 100644
index e4c6c54..0000000
--- a/app/goplay/play.go
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2013 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package goplay
-
-import (
-	"io"
-	"net/http"
-
-	"golang.org/x/tools/godoc/static"
-)
-
-func init() {
-	http.Handle("/playground.js", hstsHandler(play))
-}
-
-func play(w http.ResponseWriter, r *http.Request) {
-	w.Header().Set("Content-type", "text/javascript")
-	io.WriteString(w, static.Files["playground.js"])
-}
diff --git a/frontend/app.yaml b/frontend/app.yaml
new file mode 100644
index 0000000..698746e
--- /dev/null
+++ b/frontend/app.yaml
@@ -0,0 +1,3 @@
+service: play-flex
+runtime: go
+env: flex
diff --git a/frontend/compile.go b/frontend/compile.go
new file mode 100644
index 0000000..1d1b39a
--- /dev/null
+++ b/frontend/compile.go
@@ -0,0 +1,40 @@
+// Copyright 2011 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+	"fmt"
+	"io"
+	"net/http"
+	"os"
+)
+
+const runURL = "https://golang.org/compile?output=json"
+
+func compile(w http.ResponseWriter, r *http.Request) {
+	if r.Method != "POST" {
+		http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
+		return
+	}
+	if err := passThru(w, r); err != nil {
+		http.Error(w, "Compile server error.", http.StatusInternalServerError)
+		return
+	}
+}
+
+func passThru(w io.Writer, req *http.Request) error {
+	defer req.Body.Close()
+	r, err := http.Post(runURL, req.Header.Get("Content-type"), req.Body)
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "error making POST request: %v", err)
+		return err
+	}
+	defer r.Body.Close()
+	if _, err := io.Copy(w, r.Body); err != nil {
+		fmt.Fprintf(os.Stderr, "error copying response Body: %v", err)
+		return err
+	}
+	return nil
+}
diff --git a/app/goplay/edit.go b/frontend/edit.go
similarity index 92%
rename from app/goplay/edit.go
rename to frontend/edit.go
index e63d21f..8312f4f 100644
--- a/app/goplay/edit.go
+++ b/frontend/edit.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package goplay
+package main
 
 import (
 	"fmt"
@@ -17,11 +17,7 @@
 
 const hostname = "play.golang.org"
 
-func init() {
-	http.Handle("/", hstsHandler(edit))
-}
-
-var editTemplate = template.Must(template.ParseFiles("goplay/edit.html"))
+var editTemplate = template.Must(template.ParseFiles("edit.html"))
 
 type editData struct {
 	Snippet *Snippet
diff --git a/app/goplay/edit.html b/frontend/edit.html
similarity index 100%
rename from app/goplay/edit.html
rename to frontend/edit.html
diff --git a/app/goplay/fmt.go b/frontend/fmt.go
similarity index 89%
rename from app/goplay/fmt.go
rename to frontend/fmt.go
index b6842f3..ad916fa 100644
--- a/app/goplay/fmt.go
+++ b/frontend/fmt.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package goplay
+package main
 
 import (
 	"encoding/json"
@@ -12,10 +12,6 @@
 	"golang.org/x/tools/imports"
 )
 
-func init() {
-	http.Handle("/fmt", hstsHandler(fmtHandler))
-}
-
 type fmtResponse struct {
 	Body  string
 	Error string
diff --git a/frontend/frontend.go b/frontend/frontend.go
new file mode 100644
index 0000000..fc97f08
--- /dev/null
+++ b/frontend/frontend.go
@@ -0,0 +1,32 @@
+// Copyright 2013 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+	"io"
+	"net/http"
+
+	"golang.org/x/tools/godoc/static"
+	"google.golang.org/appengine"
+)
+
+func main() {
+	http.Handle("/", hstsHandler(edit))
+	http.Handle("/compile", hstsHandler(compile))
+	http.Handle("/fmt", hstsHandler(fmtHandler))
+	http.Handle("/share", hstsHandler(share))
+	http.Handle("/playground.js", hstsHandler(play))
+	staticHandler := http.StripPrefix("/static/", http.FileServer(http.Dir("./static")))
+	http.Handle("/static/", hstsHandler(staticHandler.(http.HandlerFunc)))
+	http.HandleFunc("/favicon.ico", func(w http.ResponseWriter, r *http.Request) {
+		http.ServeFile(w, r, "./static/favicon.ico")
+	})
+	appengine.Main()
+}
+
+func play(w http.ResponseWriter, r *http.Request) {
+	w.Header().Set("Content-type", "text/javascript")
+	io.WriteString(w, static.Files["playground.js"])
+}
diff --git a/app/goplay/hsts.go b/frontend/hsts.go
similarity index 96%
rename from app/goplay/hsts.go
rename to frontend/hsts.go
index c0927d2..c463757 100644
--- a/app/goplay/hsts.go
+++ b/frontend/hsts.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package goplay
+package main
 
 import "net/http"
 
diff --git a/app/goplay/share.go b/frontend/share.go
similarity index 94%
rename from app/goplay/share.go
rename to frontend/share.go
index cf8a772..fb0c9c0 100644
--- a/app/goplay/share.go
+++ b/frontend/share.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package goplay
+package main
 
 import (
 	"bytes"
@@ -11,6 +11,7 @@
 	"fmt"
 	"io"
 	"net/http"
+	"os"
 
 	"google.golang.org/appengine"
 	"google.golang.org/appengine/datastore"
@@ -35,10 +36,6 @@
 	return string(b)[:10]
 }
 
-func init() {
-	http.Handle("/share", hstsHandler(share))
-}
-
 func share(w http.ResponseWriter, r *http.Request) {
 	w.Header().Set("Access-Control-Allow-Origin", "*")
 	if r.Method == "OPTIONS" {
@@ -84,7 +81,7 @@
 }
 
 func allowShare(r *http.Request) bool {
-	if appengine.IsDevAppServer() {
+	if os.Getenv("GAE_INSTANCE") == "" {
 		return true
 	}
 	switch r.Header.Get("X-AppEngine-Country") {
diff --git a/app/static/favicon.ico b/frontend/static/favicon.ico
similarity index 100%
rename from app/static/favicon.ico
rename to frontend/static/favicon.ico
Binary files differ
diff --git a/app/static/godoc.css b/frontend/static/godoc.css
similarity index 100%
rename from app/static/godoc.css
rename to frontend/static/godoc.css
diff --git a/app/static/gopher.png b/frontend/static/gopher.png
similarity index 100%
rename from app/static/gopher.png
rename to frontend/static/gopher.png
Binary files differ
diff --git a/app/static/jquery-linedtextarea.js b/frontend/static/jquery-linedtextarea.js
similarity index 100%
rename from app/static/jquery-linedtextarea.js
rename to frontend/static/jquery-linedtextarea.js
diff --git a/app/static/playground-embed.js b/frontend/static/playground-embed.js
similarity index 100%
rename from app/static/playground-embed.js
rename to frontend/static/playground-embed.js
diff --git a/app/static/style.css b/frontend/static/style.css
similarity index 100%
rename from app/static/style.css
rename to frontend/static/style.css