Merge profile and config files and support custom index file

This commit is contained in:
Iwasaki Yudai 2015-08-28 21:12:04 -07:00
parent 25a5bc0b89
commit d3e48aa3ae
8 changed files with 111 additions and 121 deletions

View File

@ -3,7 +3,7 @@ gotty: app/resource.go main.go app/*.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/...
gofmt -w app/resource.go
@ -13,12 +13,15 @@ bindata:
bindata/static: bindata
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
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

View File

@ -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-crt "~/.gotty.key" TLS/SSL crt file path [$GOTTY_TLS_CRT]
--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]
--reconnect Enable reconnection [$GOTTY_RECONNECT]
--reconnect-time "10" Time to reconnect [$GOTTY_RECONNECT_TIME]
--once Accept only one client and exit on disconnection [$GOTTY_ONCE]
--config "~/.gotty" Config file path [$GOTTY_CONFIG]
```
### 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.
The following example makes the font size smaller and the background color a little bit blue.
--version, -v print the version
```
font-size = 5,
background-color = "rgb(16, 16, 32)"
### Config File
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.
```
// Listen at port 9000 by default
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

View File

@ -32,7 +32,6 @@ type App struct {
upgrader *websocket.Upgrader
server *manners.GracefulServer
preferences map[string]interface{}
titleTemplate *template.Template
}
@ -44,7 +43,7 @@ type Options struct {
Credential string
EnableRandomUrl bool
RandomUrlLength int
ProfileFile string
IndexFile string
EnableTLS bool
TLSCrtFile string
TLSKeyFile string
@ -52,6 +51,7 @@ type Options struct {
EnableReconnect bool
ReconnectTime int
Once bool
Preferences map[string]interface{}
}
var DefaultOptions = Options{
@ -62,7 +62,7 @@ var DefaultOptions = Options{
Credential: "",
EnableRandomUrl: false,
RandomUrlLength: 8,
ProfileFile: "~/.gotty.prf",
IndexFile: "",
EnableTLS: false,
TLSCrtFile: "~/.gotty.key",
TLSKeyFile: "~/.gotty.crt",
@ -70,6 +70,7 @@ var DefaultOptions = Options{
EnableReconnect: false,
ReconnectTime: 10,
Once: false,
Preferences: make(map[string]interface{}),
}
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")
}
prefMap, err := loadProfileFile(options)
if err != nil {
return nil, err
}
return &App{
command: command,
options: options,
@ -93,7 +89,6 @@ func New(command []string, options *Options) (*App, error) {
Subprotocols: []string{"gotty"},
},
preferences: prefMap,
titleTemplate: titleTemplate,
}, nil
}
@ -126,12 +121,25 @@ func applyConfigFile(options *Options, filePath string) error {
if val, ok := config[configName]; ok {
field, ok := o.FieldOk(name)
if !ok {
return errors.New("No such field: " + name)
return errors.New("No such option: " + name)
}
err := field.Set(val)
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(htermPrefs)
} else {
err = field.Set(val)
}
if err != nil {
return err
}
}
}
@ -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 {
if app.options.PermitWrite {
log.Printf("Permitting clients to write input to the PTY.")
@ -190,7 +176,20 @@ func (app *App) Run() error {
}
var siteMux = http.NewServeMux()
siteMux.Handle(path+"/", http.StripPrefix(path+"/", staticHandler))
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+"/js/", http.StripPrefix(path+"/", staticHandler))
siteMux.Handle(path+"/ws", wsHandler)
siteHandler := http.Handler(siteMux)

View File

@ -126,7 +126,7 @@ func (context *clientContext) sendInitialize() error {
}
writer.Close()
prefs, _ := json.Marshal(context.app.preferences)
prefs, _ := json.Marshal(context.app.options.Preferences)
context.connection.WriteMessage(
websocket.TextMessage,
append([]byte{SetPreferences}, prefs...),

File diff suppressed because one or more lines are too long

View File

@ -28,7 +28,7 @@ func main() {
flag{"tls", "t", "Enable TLS/SSL"},
flag{"tls-crt", "", "TLS/SSL crt 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{"reconnect", "", "Enable reconnection"},
flag{"reconnect-time", "", "Time to reconnect"},
@ -36,7 +36,7 @@ func main() {
}
mappingHint := map[string]string{
"profile": "ProfileFile",
"index": "IndexFile",
"tls": "EnableTLS",
"tls-crt": "TLSCrtFile",
"tls-key": "TLSKeyFile",

View File

@ -40,7 +40,7 @@
term.installKeyboard();
};
term.decorate(document.body);
term.decorate(document.getElementById("terminal"));
};
ws.onmessage = function(event) {

View File

@ -2,10 +2,11 @@
<html>
<head>
<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>
<body>
<script src="hterm.js"></script>
<script src="gotty.js"></script>
<div id="terminal"></div>
<script src="./js/hterm.js"></script>
<script src="./js/gotty.js"></script>
</body>
</html>