From 86763bd3aa31850eefcb550c98f4e489820e4fd3 Mon Sep 17 00:00:00 2001 From: yas-nyan Date: Sun, 27 Mar 2022 03:47:16 +0900 Subject: [PATCH] Feature: TLS and HTTP/2 (#39) --- README.md | 8 ++++++++ config/config.go | 7 +++++++ settings.toml | 8 ++++++++ web/web.go | 24 ++++++++++++++++++++++-- 4 files changed, 45 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6ed2d35..47163aa 100644 --- a/README.md +++ b/README.md @@ -116,6 +116,14 @@ manually, you can install newer version of Go into your `GOPATH`: # if you use `bolt` as database, set database_file to database file location database_file="speedtest.db" + + # TLS and HTTP/2 settings. TLS is required for HTTP/2 + enable_tls=false + enable_http2=false + + # if you use HTTP/2 or TLS, you need to prepare certificates and private keys + # tls_cert_file="cert.pem" + # tls_key_file="privkey.pem" ``` ## Differences between Go and PHP implementation and caveats diff --git a/config/config.go b/config/config.go index 1934771..384762a 100644 --- a/config/config.go +++ b/config/config.go @@ -25,6 +25,11 @@ type Config struct { DatabasePassword string `mapstructure:"database_password"` DatabaseFile string `mapstructure:"database_file"` + + EnableHTTP2 bool `mapstructure:"enable_http2"` + EnableTLS bool `mapstructure:"enable_tls"` + TLSCertFile string `mapstructure:"tls_cert_file"` + TLSKeyFile string `mapstructure:"tls_key_file"` } var ( @@ -44,6 +49,8 @@ func init() { viper.SetDefault("database_hostname", "localhost") viper.SetDefault("database_name", "speedtest") viper.SetDefault("database_username", "postgres") + viper.SetDefault("enable_tls", false) + viper.SetDefault("enable_http2", false) viper.SetConfigName("settings") viper.AddConfigPath(".") diff --git a/settings.toml b/settings.toml index 79a1b8e..83e3256 100644 --- a/settings.toml +++ b/settings.toml @@ -28,3 +28,11 @@ database_password="" # if you use `bolt` as database, set database_file to database file location database_file="speedtest.db" + +# TLS and HTTP/2 settings. TLS is required for HTTP/2 +enable_tls=false +enable_http2=false + +# if you use HTTP/2 or TLS, you need to prepare certificates and private keys +# tls_cert_file="cert.pem" +# tls_key_file="privkey.pem" \ No newline at end of file diff --git a/web/web.go b/web/web.go index a63da3d..f03d47b 100644 --- a/web/web.go +++ b/web/web.go @@ -1,6 +1,7 @@ package web import ( + "crypto/tls" "embed" "encoding/json" "io" @@ -107,10 +108,29 @@ func ListenAndServe(conf *config.Config) error { case 0: addr := net.JoinHostPort(conf.BindAddress, conf.Port) log.Infof("Starting backend server on %s", addr) - s = http.ListenAndServe(addr, r) + + // TLS and HTTP/2. + if conf.EnableTLS { + log.Info("Use TLS connection.") + if !(conf.EnableHTTP2) { + srv := &http.Server{ + Addr: addr, + Handler: r, + TLSNextProto: make(map[string]func(*http.Server, *tls.Conn, http.Handler)), + } + s = srv.ListenAndServeTLS(conf.TLSCertFile, conf.TLSKeyFile) + } else { + s = http.ListenAndServeTLS(addr, conf.TLSCertFile, conf.TLSKeyFile, r) + } + } else { + if conf.EnableHTTP2 { + log.Errorf("TLS is mandatory for HTTP/2. Ignore settings that enable HTTP/2.") + } + s = http.ListenAndServe(addr, r) + } case 1: log.Info("Starting backend server on inherited file descriptor via systemd socket activation") - if (conf.BindAddress != "" || conf.Port != "") { + if conf.BindAddress != "" || conf.Port != "" { log.Errorf("Both an address/port (%s:%s) has been specificed in the config AND externally configured socket activation has been detected", conf.BindAddress, conf.Port) log.Fatal(`Please deconfigure socket activation (e.g. in systemd unit files), or set both 'bind_address' and 'listen_port' to ''`) }