Skip to content

Commit

Permalink
cmd/present: merge appengine and non-appengine files
Browse files Browse the repository at this point in the history
Without changing the behavior of the present command for local
usage (using the local socket for running examples, defaulting to
the current directory for all content). Add flags and set them to
the appropriate values if running on App Engine.

Notably, since the Go files must be in the same directory as
app.yaml, the content root must be ./content/ to avoid listing
the present source files.

It also defaults to running example snippets via the HTTPTransport
(https://play.golang.org/compile) instead of locally when on App
Engine.

There are also some small cleanup code changes.

Update golang/go#28080

Change-Id: I40bb7923107614f88d2bfdffd34a824d4bacb3a1
Reviewed-on: https://go-review.googlesource.com/c/140841
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
  • Loading branch information
andybons committed Oct 10, 2018
1 parent f78a1e9 commit 37fd46f
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 124 deletions.
22 changes: 0 additions & 22 deletions cmd/present/appengine.go

This file was deleted.

25 changes: 14 additions & 11 deletions cmd/present/dir.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"os"
"path/filepath"
"sort"
"strings"

"golang.org/x/tools/present"
)
Expand All @@ -21,19 +22,18 @@ func init() {
http.HandleFunc("/", dirHandler)
}

// dirHandler serves a directory listing for the requested path, rooted at basePath.
// dirHandler serves a directory listing for the requested path, rooted at *contentPath.
func dirHandler(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/favicon.ico" {
http.Error(w, "not found", 404)
http.NotFound(w, r)
return
}
const base = "."
name := filepath.Join(base, r.URL.Path)
name := filepath.Join(*contentPath, r.URL.Path)
if isDoc(name) {
err := renderDoc(w, name)
if err != nil {
log.Println(err)
http.Error(w, err.Error(), 500)
http.Error(w, err.Error(), http.StatusInternalServerError)
}
return
}
Expand All @@ -43,12 +43,12 @@ func dirHandler(w http.ResponseWriter, r *http.Request) {
addr = r.RemoteAddr
}
log.Printf("request from %s: %s", addr, err)
http.Error(w, err.Error(), 500)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
} else if isDir {
return
}
http.FileServer(http.Dir(base)).ServeHTTP(w, r)
http.FileServer(http.Dir(*contentPath)).ServeHTTP(w, r)
}

func isDoc(path string) bool {
Expand Down Expand Up @@ -138,23 +138,26 @@ func dirList(w io.Writer, name string) (isDir bool, err error) {
if err != nil {
return false, err
}
d := &dirListData{Path: name}
strippedPath := strings.TrimPrefix(name, filepath.Clean(*contentPath))
strippedPath = strings.TrimPrefix(strippedPath, "/")
d := &dirListData{Path: strippedPath}
for _, fi := range fis {
// skip the golang.org directory
if name == "." && fi.Name() == "golang.org" {
continue
}
e := dirEntry{
Name: fi.Name(),
Path: filepath.ToSlash(filepath.Join(name, fi.Name())),
Path: filepath.ToSlash(filepath.Join(strippedPath, fi.Name())),
}
if fi.IsDir() && showDir(e.Name) {
d.Dirs = append(d.Dirs, e)
continue
}
if isDoc(e.Name) {
if p, err := parse(e.Path, present.TitlesOnly); err != nil {
log.Println(err)
fn := filepath.ToSlash(filepath.Join(name, fi.Name()))
if p, err := parse(fn, present.TitlesOnly); err != nil {
log.Printf("parse(%q, present.TitlesOnly): %v", fn, err)
} else {
e.Title = p.Title
}
Expand Down
37 changes: 16 additions & 21 deletions cmd/present/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,43 +8,38 @@ presents slide and article files from the current directory.
It may be run as a stand-alone command or an App Engine app.
Usage of present:
-base="": base path for slide template and static resources
-http="127.0.0.1:3999": HTTP service address (e.g., '127.0.0.1:3999')
-nacl=false: use Native Client environment playground (prevents non-Go code execution)
-notes=false: enable presenter notes (press 'N' from the browser to display them)
-orighost="": host component of web origin URL (e.g., 'localhost')
-play=true: enable playground (permit execution of arbitrary user code)
The setup of the Go version of NaCl is documented at:
https://golang.org/wiki/NativeClient
To use with App Engine, copy the tools/cmd/present directory to the root of
your application and create an app.yaml file similar to this:
To use with App Engine, copy the files in the tools/cmd/present directory to the
root of your application and create an app.yaml file similar to this:
application: [application]
version: [version]
runtime: go
api_version: go1
runtime: go111
handlers:
- url: /favicon.ico
static_files: present/static/favicon.ico
upload: present/static/favicon.ico
static_files: static/favicon.ico
upload: static/favicon.ico
- url: /static
static_dir: present/static
application_readable: true
static_dir: static
- url: /.*
script: _go_app
script: auto
# nobuild_files is a regexp that identifies which files to not build. It
# is useful for embedding static assets like code snippets and preventing
# them from producing build errors for your project.
nobuild_files: [path regexp for talk materials]
When running on App Engine, content will be served from the ./content/
subdirectory.
Present then can be tested in a local App Engine environment with
goapp serve
GAE_ENV=standard go run .
And deployed using
gcloud app deploy
Input files are named foo.extension, where "extension" defines the format of
the generated output. The supported formats are:
Expand All @@ -54,4 +49,4 @@ the generated output. The supported formats are:
The present file format is documented by the present package:
http://godoc.org/golang.org/x/tools/present
*/
package main // import "golang.org/x/tools/cmd/present"
package main
40 changes: 29 additions & 11 deletions cmd/present/local.go → cmd/present/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand All @@ -23,17 +21,36 @@ import (
const basePkg = "golang.org/x/tools/cmd/present"

var (
httpAddr = flag.String("http", "127.0.0.1:3999", "HTTP service address (e.g., '127.0.0.1:3999')")
originHost = flag.String("orighost", "", "host component of web origin URL (e.g., 'localhost')")
basePath = flag.String("base", "", "base path for slide template and static resources")
nativeClient = flag.Bool("nacl", false, "use Native Client environment playground (prevents non-Go code execution)")
httpAddr = flag.String("http", "127.0.0.1:3999", "HTTP service address (e.g., '127.0.0.1:3999')")
originHost = flag.String("orighost", "", "host component of web origin URL (e.g., 'localhost')")
basePath = flag.String("base", "", "base path for slide template and static resources")
contentPath = flag.String("content", ".", "base path for presentation content")
usePlayground = flag.Bool("use_playground", false, "if false, arbitrary code (Go, shell scripts, etc.) is run locally via WebSocket transport; otherwise it uses play.golang.org")
nativeClient = flag.Bool("nacl", false, "use Native Client environment playground (prevents non-Go code execution) when using local WebSocket transport")
)

func main() {
flag.BoolVar(&present.PlayEnabled, "play", true, "enable playground (permit execution of arbitrary user code)")
flag.BoolVar(&present.NotesEnabled, "notes", false, "enable presenter notes (press 'N' from the browser to display them)")
flag.Parse()

if os.Getenv("GAE_ENV") == "standard" {
log.Print("Configuring for App Engine Standard")
port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
*httpAddr = fmt.Sprintf("0.0.0.0:%s", port)
pwd, err := os.Getwd()
if err != nil {
fmt.Fprintf(os.Stderr, "Couldn't get pwd: %v\n", err)
os.Exit(1)
}
*basePath = pwd
*usePlayground = true
*contentPath = "./content/"
}

if *basePath == "" {
p, err := build.Default.Import(basePkg, "", build.FindOnly)
if err != nil {
Expand Down Expand Up @@ -81,7 +98,7 @@ func main() {
http.Handle("/static/", http.FileServer(http.Dir(*basePath)))

if !ln.Addr().(*net.TCPAddr).IP.IsLoopback() &&
present.PlayEnabled && !*nativeClient {
present.PlayEnabled && !*nativeClient && !*usePlayground {
log.Print(localhostWarning)
}

Expand Down Expand Up @@ -121,11 +138,12 @@ You may use the -base flag to specify an alternate location.
const localhostWarning = `
WARNING! WARNING! WARNING!
The present server appears to be listening on an address that is not localhost.
Anyone with access to this address and port will have access to this machine as
the user running present.
The present server appears to be listening on an address that is not localhost
and using socket transport for running Go code. Anyone with access to this address
and port will have access to this machine as the user running present.
To avoid this message, listen on localhost or run with -play=false.
To avoid this message, listen on localhost, run with -play=false, or run with
-play_socket=false.
If you don't understand this message, hit Control-C to terminate this process.
Expand Down
46 changes: 46 additions & 0 deletions cmd/present/play.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,21 @@ import (
"fmt"
"io/ioutil"
"net/http"
"net/url"
"path/filepath"
"runtime"
"time"

"golang.org/x/tools/godoc/static"
"golang.org/x/tools/playground/socket"
"golang.org/x/tools/present"

// This will register handlers at /compile and /share that will proxy to the
// respective endpoints at play.golang.org. This allows the frontend to call
// these endpoints without needing cross-origin request sharing (CORS).
// Note that this is imported regardless of whether the endpoints are used or
// not (in the case of a local socket connection, they are not called).
_ "golang.org/x/tools/playground"
)

var scripts = []string{"jquery.js", "jquery-ui.js", "playground.js", "play.js"}
Expand Down Expand Up @@ -41,3 +52,38 @@ func playScript(root, transport string) {
http.ServeContent(w, r, "", modTime, bytes.NewReader(b))
})
}

func initPlayground(basepath string, origin *url.URL) {
if !present.PlayEnabled {
return
}
if *usePlayground {
playScript(basepath, "HTTPTransport")
return
}

if *nativeClient {
// When specifying nativeClient, non-Go code cannot be executed
// because the NaCl setup doesn't support doing so.
socket.RunScripts = false
socket.Environ = func() []string {
if runtime.GOARCH == "amd64" {
return environ("GOOS=nacl", "GOARCH=amd64p32")
}
return environ("GOOS=nacl")
}
}
playScript(basepath, "SocketTransport")
http.Handle("/socket", socket.NewHandler(origin))
}

func playable(c present.Code) bool {
play := present.PlayEnabled && c.Play

// Restrict playable files to only Go source files when using play.golang.org,
// since there is no method to execute shell scripts there.
if *usePlayground {
return play && c.Ext == ".go"
}
return play
}
23 changes: 0 additions & 23 deletions cmd/present/play_http.go

This file was deleted.

36 changes: 0 additions & 36 deletions cmd/present/play_socket.go

This file was deleted.

0 comments on commit 37fd46f

Please sign in to comment.