Commit d3e48aa3 by Iwasaki Yudai

Merge profile and config files and support custom index file

1 parent 25a5bc0b
...@@ -3,7 +3,7 @@ gotty: app/resource.go main.go app/*.go ...@@ -3,7 +3,7 @@ gotty: app/resource.go main.go app/*.go
resource: app/resource.go resource: app/resource.go
app/resource.go: bindata/static/hterm.js bindata/static/gotty.js bindata/static/index.html app/resource.go: bindata/static/js/hterm.js bindata/static/js/gotty.js bindata/static/index.html
go-bindata -prefix bindata -pkg app -ignore=\\.gitkeep -o app/resource.go bindata/... go-bindata -prefix bindata -pkg app -ignore=\\.gitkeep -o app/resource.go bindata/...
gofmt -w app/resource.go gofmt -w app/resource.go
...@@ -13,12 +13,15 @@ bindata: ...@@ -13,12 +13,15 @@ bindata:
bindata/static: bindata bindata/static: bindata
mkdir bindata/static mkdir bindata/static
bindata/static/hterm.js: bindata/static libapps/hterm/js/*.js
cd libapps && \
LIBDOT_SEARCH_PATH=`pwd` ./libdot/bin/concat.sh -i ./hterm/concat/hterm_all.concat -o ../bindata/static/hterm.js
bindata/static/gotty.js: bindata/static resources/gotty.js
cp resources/gotty.js bindata/static/gotty.js
bindata/static/index.html: bindata/static resources/index.html bindata/static/index.html: bindata/static resources/index.html
cp resources/index.html bindata/static/index.html cp resources/index.html bindata/static/index.html
bindata/static/js: bindata/static
mkdir bindata/static/js
bindata/static/js/hterm.js: bindata/static/js libapps/hterm/js/*.js
cd libapps && \
LIBDOT_SEARCH_PATH=`pwd` ./libdot/bin/concat.sh -i ./hterm/concat/hterm_all.concat -o ../bindata/static/js/hterm.js
bindata/static/js/gotty.js: bindata/static/js resources/gotty.js
cp resources/gotty.js bindata/static/js/gotty.js
...@@ -58,26 +58,36 @@ By default, gotty starts a web server at port 8080. Open the URL on your web bro ...@@ -58,26 +58,36 @@ By default, gotty starts a web server at port 8080. Open the URL on your web bro
--tls, -t Enable TLS/SSL [$GOTTY_TLS] --tls, -t Enable TLS/SSL [$GOTTY_TLS]
--tls-crt "~/.gotty.key" TLS/SSL crt file path [$GOTTY_TLS_CRT] --tls-crt "~/.gotty.key" TLS/SSL crt file path [$GOTTY_TLS_CRT]
--tls-key "~/.gotty.crt" TLS/SSL key file path [$GOTTY_TLS_KEY] --tls-key "~/.gotty.crt" TLS/SSL key file path [$GOTTY_TLS_KEY]
--profile "~/.gotty.prf" Profile file path [$GOTTY_PROFILE] --index Custom index file [$GOTTY_INDEX]
--title-format "GoTTY - {{ .Command }} ({{ .Hostname }})" Title format of browser window [$GOTTY_TITLE_FORMAT] --title-format "GoTTY - {{ .Command }} ({{ .Hostname }})" Title format of browser window [$GOTTY_TITLE_FORMAT]
--reconnect Enable reconnection [$GOTTY_RECONNECT] --reconnect Enable reconnection [$GOTTY_RECONNECT]
--reconnect-time "10" Time to reconnect [$GOTTY_RECONNECT_TIME] --reconnect-time "10" Time to reconnect [$GOTTY_RECONNECT_TIME]
--once Accept only one client and exit on disconnection [$GOTTY_ONCE] --once Accept only one client and exit on disconnection [$GOTTY_ONCE]
--config "~/.gotty" Config file path [$GOTTY_CONFIG] --config "~/.gotty" Config file path [$GOTTY_CONFIG]
``` --version, -v print the version
### Profile File ```
You can customize your terminal (hterm) by providing a profile file to the `gotty` command, which is a HCL file that has a map of preference keys and values. Gotty loads a profile file at `~/.gotty` by default when it exists. ### Config File
The following example makes the font size smaller and the background color a little bit blue. You can customize default options and your terminal (hterm) by providing a config file to the `gotty` command. Gotty loads a profile file at `~/.gotty` by default when it exists.
``` ```
font-size = 5, // Listen at port 9000 by default
background-color = "rgb(16, 16, 32)" port = "9000"
// Enable TSL/SSL by default
enable_tls = true
// hterm preferences
// Smaller font and a little bit bluer background color
preferences {
font_size = 5,
background_color = "rgb(16, 16, 32)"
}
``` ```
Available preferences are listed in [the hterm source code](https://chromium.googlesource.com/apps/libapps/+/master/hterm/js/hterm_preference_manager.js) Available hterm preference options are listed in [the hterm source code](https://chromium.googlesource.com/apps/libapps/+/master/hterm/js/hterm_preference_manager.js). Note that hifens (`-`) in the preference names must be replaced by underscores (`_`).
### Security Options ### Security Options
......
...@@ -32,7 +32,6 @@ type App struct { ...@@ -32,7 +32,6 @@ type App struct {
upgrader *websocket.Upgrader upgrader *websocket.Upgrader
server *manners.GracefulServer server *manners.GracefulServer
preferences map[string]interface{}
titleTemplate *template.Template titleTemplate *template.Template
} }
...@@ -44,7 +43,7 @@ type Options struct { ...@@ -44,7 +43,7 @@ type Options struct {
Credential string Credential string
EnableRandomUrl bool EnableRandomUrl bool
RandomUrlLength int RandomUrlLength int
ProfileFile string IndexFile string
EnableTLS bool EnableTLS bool
TLSCrtFile string TLSCrtFile string
TLSKeyFile string TLSKeyFile string
...@@ -52,6 +51,7 @@ type Options struct { ...@@ -52,6 +51,7 @@ type Options struct {
EnableReconnect bool EnableReconnect bool
ReconnectTime int ReconnectTime int
Once bool Once bool
Preferences map[string]interface{}
} }
var DefaultOptions = Options{ var DefaultOptions = Options{
...@@ -62,7 +62,7 @@ var DefaultOptions = Options{ ...@@ -62,7 +62,7 @@ var DefaultOptions = Options{
Credential: "", Credential: "",
EnableRandomUrl: false, EnableRandomUrl: false,
RandomUrlLength: 8, RandomUrlLength: 8,
ProfileFile: "~/.gotty.prf", IndexFile: "",
EnableTLS: false, EnableTLS: false,
TLSCrtFile: "~/.gotty.key", TLSCrtFile: "~/.gotty.key",
TLSKeyFile: "~/.gotty.crt", TLSKeyFile: "~/.gotty.crt",
...@@ -70,6 +70,7 @@ var DefaultOptions = Options{ ...@@ -70,6 +70,7 @@ var DefaultOptions = Options{
EnableReconnect: false, EnableReconnect: false,
ReconnectTime: 10, ReconnectTime: 10,
Once: false, Once: false,
Preferences: make(map[string]interface{}),
} }
func New(command []string, options *Options) (*App, error) { func New(command []string, options *Options) (*App, error) {
...@@ -78,11 +79,6 @@ func New(command []string, options *Options) (*App, error) { ...@@ -78,11 +79,6 @@ func New(command []string, options *Options) (*App, error) {
return nil, errors.New("Title format string syntax error") return nil, errors.New("Title format string syntax error")
} }
prefMap, err := loadProfileFile(options)
if err != nil {
return nil, err
}
return &App{ return &App{
command: command, command: command,
options: options, options: options,
...@@ -93,7 +89,6 @@ func New(command []string, options *Options) (*App, error) { ...@@ -93,7 +89,6 @@ func New(command []string, options *Options) (*App, error) {
Subprotocols: []string{"gotty"}, Subprotocols: []string{"gotty"},
}, },
preferences: prefMap,
titleTemplate: titleTemplate, titleTemplate: titleTemplate,
}, nil }, nil
} }
...@@ -126,12 +121,25 @@ func applyConfigFile(options *Options, filePath string) error { ...@@ -126,12 +121,25 @@ func applyConfigFile(options *Options, filePath string) error {
if val, ok := config[configName]; ok { if val, ok := config[configName]; ok {
field, ok := o.FieldOk(name) field, ok := o.FieldOk(name)
if !ok { if !ok {
return errors.New("No such field: " + name) return errors.New("No such option: " + name)
}
var err error
if name == "Preferences" {
prefs := val.([]map[string]interface{})[0]
htermPrefs := make(map[string]interface{})
for key, value := range prefs {
htermPrefs[strings.Replace(key, "_", "-", -1)] = value
} }
err := field.Set(val) err = field.Set(htermPrefs)
} else {
err = field.Set(val)
}
if err != nil { if err != nil {
return err return err
} }
} }
} }
...@@ -146,28 +154,6 @@ func ExpandHomeDir(path string) string { ...@@ -146,28 +154,6 @@ func ExpandHomeDir(path string) string {
} }
} }
func loadProfileFile(options *Options) (map[string]interface{}, error) {
prefString := []byte{}
prefPath := options.ProfileFile
if options.ProfileFile == DefaultOptions.ProfileFile {
prefPath = os.Getenv("HOME") + "/.gotty.prf"
}
if _, err := os.Stat(prefPath); os.IsNotExist(err) {
if options.ProfileFile != DefaultOptions.ProfileFile {
return nil, err
}
} else {
log.Printf("Loading profile path: %s", prefPath)
prefString, _ = ioutil.ReadFile(prefPath)
}
var prefMap map[string]interface{}
err := hcl.Decode(&prefMap, string(prefString))
if err != nil {
return nil, err
}
return prefMap, nil
}
func (app *App) Run() error { func (app *App) Run() error {
if app.options.PermitWrite { if app.options.PermitWrite {
log.Printf("Permitting clients to write input to the PTY.") log.Printf("Permitting clients to write input to the PTY.")
...@@ -190,7 +176,20 @@ func (app *App) Run() error { ...@@ -190,7 +176,20 @@ func (app *App) Run() error {
} }
var siteMux = http.NewServeMux() var siteMux = http.NewServeMux()
if app.options.IndexFile != "" {
log.Printf("Using index file at " + app.options.IndexFile)
indexHandler := http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, ExpandHomeDir(app.options.IndexFile))
},
)
siteMux.Handle(path+"/", indexHandler)
} else {
siteMux.Handle(path+"/", http.StripPrefix(path+"/", staticHandler)) siteMux.Handle(path+"/", http.StripPrefix(path+"/", staticHandler))
}
siteMux.Handle(path+"/js/", http.StripPrefix(path+"/", staticHandler))
siteMux.Handle(path+"/ws", wsHandler) siteMux.Handle(path+"/ws", wsHandler)
siteHandler := http.Handler(siteMux) siteHandler := http.Handler(siteMux)
......
...@@ -126,7 +126,7 @@ func (context *clientContext) sendInitialize() error { ...@@ -126,7 +126,7 @@ func (context *clientContext) sendInitialize() error {
} }
writer.Close() writer.Close()
prefs, _ := json.Marshal(context.app.preferences) prefs, _ := json.Marshal(context.app.options.Preferences)
context.connection.WriteMessage( context.connection.WriteMessage(
websocket.TextMessage, websocket.TextMessage,
append([]byte{SetPreferences}, prefs...), append([]byte{SetPreferences}, prefs...),
......
This diff could not be displayed because it is too large.
...@@ -28,7 +28,7 @@ func main() { ...@@ -28,7 +28,7 @@ func main() {
flag{"tls", "t", "Enable TLS/SSL"}, flag{"tls", "t", "Enable TLS/SSL"},
flag{"tls-crt", "", "TLS/SSL crt file path"}, flag{"tls-crt", "", "TLS/SSL crt file path"},
flag{"tls-key", "", "TLS/SSL key file path"}, flag{"tls-key", "", "TLS/SSL key file path"},
flag{"profile", "", "Profile file path"}, flag{"index", "", "Custom index file"},
flag{"title-format", "", "Title format of browser window"}, flag{"title-format", "", "Title format of browser window"},
flag{"reconnect", "", "Enable reconnection"}, flag{"reconnect", "", "Enable reconnection"},
flag{"reconnect-time", "", "Time to reconnect"}, flag{"reconnect-time", "", "Time to reconnect"},
...@@ -36,7 +36,7 @@ func main() { ...@@ -36,7 +36,7 @@ func main() {
} }
mappingHint := map[string]string{ mappingHint := map[string]string{
"profile": "ProfileFile", "index": "IndexFile",
"tls": "EnableTLS", "tls": "EnableTLS",
"tls-crt": "TLSCrtFile", "tls-crt": "TLSCrtFile",
"tls-key": "TLSKeyFile", "tls-key": "TLSKeyFile",
......
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
term.installKeyboard(); term.installKeyboard();
}; };
term.decorate(document.body); term.decorate(document.getElementById("terminal"));
}; };
ws.onmessage = function(event) { ws.onmessage = function(event) {
......
...@@ -2,10 +2,11 @@ ...@@ -2,10 +2,11 @@
<html> <html>
<head> <head>
<title>GoTTY</title> <title>GoTTY</title>
<style>body {position: absolute; height: 100%; width: 100%; margin: 0px;}</style> <style>body, #terminal {position: absolute; height: 100%; width: 100%; margin: 0px;}</style>
</head> </head>
<body> <body>
<script src="hterm.js"></script> <div id="terminal"></div>
<script src="gotty.js"></script> <script src="./js/hterm.js"></script>
<script src="./js/gotty.js"></script>
</body> </body>
</html> </html>
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!