2014-05-05 15:55:27 -06:00
// 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 (
"flag"
"fmt"
"go/build"
"log"
"net"
"net/http"
"net/url"
"os"
"strings"
2014-11-09 14:50:40 -07:00
"golang.org/x/tools/present"
2014-05-05 15:55:27 -06:00
)
2014-11-09 14:50:40 -07:00
const basePkg = "golang.org/x/tools/cmd/present"
2014-05-05 15:55:27 -06:00
2015-09-16 20:11:32 -06:00
var (
2018-10-09 15:35:48 -06:00
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" )
2018-10-12 14:38:04 -06:00
usePlayground = flag . Bool ( "use_playground" , false , "run code snippets using play.golang.org; if false, run them locally and deliver results by WebSocket transport" )
2018-10-09 15:35:48 -06:00
nativeClient = flag . Bool ( "nacl" , false , "use Native Client environment playground (prevents non-Go code execution) when using local WebSocket transport" )
2015-09-16 20:11:32 -06:00
)
2014-05-05 15:55:27 -06:00
func main ( ) {
flag . BoolVar ( & present . PlayEnabled , "play" , true , "enable playground (permit execution of arbitrary user code)" )
2016-04-03 17:33:36 -06:00
flag . BoolVar ( & present . NotesEnabled , "notes" , false , "enable presenter notes (press 'N' from the browser to display them)" )
2014-05-05 15:55:27 -06:00
flag . Parse ( )
2018-10-09 15:35:48 -06:00
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 {
2018-10-12 14:38:04 -06:00
log . Fatalf ( "Couldn't get pwd: %v\n" , err )
2018-10-09 15:35:48 -06:00
}
* basePath = pwd
* usePlayground = true
* contentPath = "./content/"
}
2015-09-16 20:11:32 -06:00
if * basePath == "" {
2014-05-05 15:55:27 -06:00
p , err := build . Default . Import ( basePkg , "" , build . FindOnly )
if err != nil {
fmt . Fprintf ( os . Stderr , "Couldn't find gopresent files: %v\n" , err )
fmt . Fprintf ( os . Stderr , basePathMessage , basePkg )
os . Exit ( 1 )
}
2015-09-16 20:11:32 -06:00
* basePath = p . Dir
2014-05-05 15:55:27 -06:00
}
2015-09-16 20:11:32 -06:00
err := initTemplates ( * basePath )
2014-07-07 23:27:33 -06:00
if err != nil {
log . Fatalf ( "Failed to parse templates: %v" , err )
}
2014-05-05 15:55:27 -06:00
2014-06-02 06:39:33 -06:00
ln , err := net . Listen ( "tcp" , * httpAddr )
if err != nil {
log . Fatal ( err )
}
defer ln . Close ( )
_ , port , err := net . SplitHostPort ( ln . Addr ( ) . String ( ) )
if err != nil {
log . Fatal ( err )
}
2015-09-16 20:11:32 -06:00
2014-06-02 06:39:33 -06:00
origin := & url . URL { Scheme : "http" }
if * originHost != "" {
origin . Host = net . JoinHostPort ( * originHost , port )
} else if ln . Addr ( ) . ( * net . TCPAddr ) . IP . IsUnspecified ( ) {
name , _ := os . Hostname ( )
origin . Host = net . JoinHostPort ( name , port )
} else {
reqHost , reqPort , err := net . SplitHostPort ( * httpAddr )
if err != nil {
log . Fatal ( err )
}
if reqPort == "0" {
origin . Host = net . JoinHostPort ( reqHost , port )
} else {
origin . Host = * httpAddr
}
}
2015-09-16 20:11:32 -06:00
initPlayground ( * basePath , origin )
http . Handle ( "/static/" , http . FileServer ( http . Dir ( * basePath ) ) )
2014-05-05 15:55:27 -06:00
2014-06-02 06:39:33 -06:00
if ! ln . Addr ( ) . ( * net . TCPAddr ) . IP . IsLoopback ( ) &&
2018-10-09 15:35:48 -06:00
present . PlayEnabled && ! * nativeClient && ! * usePlayground {
2014-05-05 15:55:27 -06:00
log . Print ( localhostWarning )
}
2014-06-02 06:39:33 -06:00
log . Printf ( "Open your web browser and visit %s" , origin . String ( ) )
2016-04-03 17:33:36 -06:00
if present . NotesEnabled {
log . Println ( "Notes are enabled, press 'N' from the browser to display them." )
}
2014-06-02 06:39:33 -06:00
log . Fatal ( http . Serve ( ln , nil ) )
2014-05-05 15:55:27 -06:00
}
func environ ( vars ... string ) [ ] string {
env := os . Environ ( )
for _ , r := range vars {
k := strings . SplitAfter ( r , "=" ) [ 0 ]
var found bool
for i , v := range env {
if strings . HasPrefix ( v , k ) {
env [ i ] = r
found = true
}
}
if ! found {
env = append ( env , r )
}
}
return env
}
const basePathMessage = `
By default , gopresent locates the slide template files and associated
static content by looking for a % q package
in your Go workspaces ( GOPATH ) .
You may use the - base flag to specify an alternate location .
`
const localhostWarning = `
WARNING ! WARNING ! WARNING !
2018-10-09 15:35:48 -06:00
The present server appears to be listening on an address that is not localhost
2018-10-12 14:38:04 -06:00
and is configured to run code snippets locally . Anyone with access to this address
2018-10-09 15:35:48 -06:00
and port will have access to this machine as the user running present .
2014-05-05 15:55:27 -06:00
2018-10-09 15:35:48 -06:00
To avoid this message , listen on localhost , run with - play = false , or run with
- play_socket = false .
2014-05-05 15:55:27 -06:00
If you don ' t understand this message , hit Control - C to terminate this process .
WARNING ! WARNING ! WARNING !
`