Add tests
Add unit tests, this required some refactoring.
This commit is contained in:
parent
d0509e3f8a
commit
c950ef5b02
|
@ -81,6 +81,10 @@ func cmdSplit(command string) []string {
|
|||
|
||||
// Run executes the given command and return it's return code. It also respects the given concurrency number and will block until resources are free
|
||||
func (hook *Hook) Run() error {
|
||||
if hook.Command == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
split := cmdSplit(hook.Command)
|
||||
args := make([]string, 0)
|
||||
if len(split) > 1 {
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"crypto/tls"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
|
@ -99,65 +100,60 @@ func main() {
|
|||
}
|
||||
}
|
||||
|
||||
// Create default handlers
|
||||
http.HandleFunc("/", createDefaultHandler())
|
||||
http.HandleFunc("/health", createHealthHandler())
|
||||
http.HandleFunc("/health.json", createHealthHandler())
|
||||
http.HandleFunc("/robots.txt", createRobotsHandler())
|
||||
|
||||
// Register hooks
|
||||
if err := RegisterHandlers(cf); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
for i, hook := range cf.Hooks {
|
||||
if hook.Route == "" {
|
||||
fmt.Fprintf(os.Stderr, "Invalid hook %s: No route defined\n", hook.Name)
|
||||
}
|
||||
if hook.Concurrency < 1 {
|
||||
hook.Concurrency = 1
|
||||
}
|
||||
log.Printf("Webhook %d: '%s' [%s] \"%s\"\n", i, hook.Name, hook.Route, hook.Command)
|
||||
http.HandleFunc(hook.Route, createHandler(hook))
|
||||
}
|
||||
|
||||
awaitTerminationSignal()
|
||||
|
||||
var listener net.Listener
|
||||
var err error
|
||||
if cf.Settings.TLS.Enabled {
|
||||
if err := LaunchTLSWebserver(cf); err != nil {
|
||||
log.Printf("Launching tls webserver on %s", cf.Settings.BindAddress)
|
||||
listener, err = CreateTLSListener(cf)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
} else {
|
||||
if err := LaunchWebserver(cf); err != nil {
|
||||
log.Printf("Launching webserver on %s", cf.Settings.BindAddress)
|
||||
listener, err = CreateListener(cf)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
server := CreateWebserver(cf)
|
||||
server.Serve(listener)
|
||||
|
||||
// read guard, should never ever ever be called.
|
||||
// If we end up here, the only safe thing we can do is terminate the program
|
||||
panic("unexpected end of main loop")
|
||||
}
|
||||
|
||||
func LaunchTLSWebserver(cf Config) error {
|
||||
func CreateListener(cf Config) (net.Listener, error) {
|
||||
return net.Listen("tcp", cf.Settings.BindAddress)
|
||||
}
|
||||
|
||||
func CreateTLSListener(cf Config) (net.Listener, error) {
|
||||
var err error
|
||||
log.Printf("Launching tls webserver on %s", cf.Settings.BindAddress)
|
||||
server := &http.Server{
|
||||
Addr: cf.Settings.BindAddress,
|
||||
ReadTimeout: time.Duration(cf.Settings.ReadTimeout) * time.Second,
|
||||
WriteTimeout: time.Duration(cf.Settings.WriteTimeout) * time.Second,
|
||||
MaxHeaderBytes: cf.Settings.MaxHeaderBytes,
|
||||
}
|
||||
tlsConfig := &tls.Config{
|
||||
MinVersion: tls.VersionTLS12,
|
||||
}
|
||||
if cf.Settings.TLS.MinVersion != "" {
|
||||
tlsConfig.MinVersion, err = ParseTLSVersion(cf.Settings.TLS.MinVersion)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid tls min version\n")
|
||||
return nil, fmt.Errorf("invalid tls min version")
|
||||
}
|
||||
}
|
||||
if cf.Settings.TLS.MaxVersion != "" {
|
||||
tlsConfig.MaxVersion, err = ParseTLSVersion(cf.Settings.TLS.MinVersion)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid tls max version\n")
|
||||
return nil, fmt.Errorf("invalid tls max version")
|
||||
}
|
||||
}
|
||||
if tlsConfig.MinVersion == tls.VersionTLS10 || tlsConfig.MinVersion == tls.VersionTLS11 {
|
||||
|
@ -167,14 +163,14 @@ func LaunchTLSWebserver(cf Config) error {
|
|||
// Create self-signed certificate, when no keyfile and no certificates are present
|
||||
if len(cf.Settings.TLS.Keypairs) == 0 {
|
||||
// TODO
|
||||
return fmt.Errorf("creating self-signed certificates is not yet supported")
|
||||
return nil, fmt.Errorf("creating self-signed certificates is not yet supported")
|
||||
} else {
|
||||
// Load key/certificates keypairs
|
||||
tlsConfig.Certificates = make([]tls.Certificate, len(cf.Settings.TLS.Keypairs))
|
||||
for i, keypair := range cf.Settings.TLS.Keypairs {
|
||||
tlsConfig.Certificates[i], err = tls.LoadX509KeyPair(keypair.Certificate, keypair.Keyfile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid tls keypair '%s,%s' - %s\n", keypair.Certificate, keypair.Keyfile, err)
|
||||
return nil, fmt.Errorf("invalid tls keypair '%s,%s' - %s", keypair.Certificate, keypair.Keyfile, err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -184,24 +180,36 @@ func LaunchTLSWebserver(cf Config) error {
|
|||
log.Printf("Loaded %d tls certificates", len(tlsConfig.Certificates))
|
||||
}
|
||||
}
|
||||
listener, err := tls.Listen("tcp", cf.Settings.BindAddress, tlsConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Printf("Serving tls requests now on %s", cf.Settings.BindAddress)
|
||||
return server.Serve(listener)
|
||||
return tls.Listen("tcp", cf.Settings.BindAddress, tlsConfig)
|
||||
}
|
||||
|
||||
func LaunchWebserver(cf Config) error {
|
||||
log.Printf("Launching webserver on %s", cf.Settings.BindAddress)
|
||||
func CreateWebserver(cf Config) *http.Server {
|
||||
server := &http.Server{
|
||||
Addr: cf.Settings.BindAddress,
|
||||
ReadTimeout: time.Duration(cf.Settings.ReadTimeout) * time.Second,
|
||||
WriteTimeout: time.Duration(cf.Settings.WriteTimeout) * time.Second,
|
||||
MaxHeaderBytes: cf.Settings.MaxHeaderBytes,
|
||||
}
|
||||
log.Printf("Serving requests now on %s", cf.Settings.BindAddress)
|
||||
return server.ListenAndServe()
|
||||
return server
|
||||
}
|
||||
|
||||
func RegisterHandlers(cf Config) error {
|
||||
http.HandleFunc("/", createDefaultHandler())
|
||||
http.HandleFunc("/health", createHealthHandler())
|
||||
http.HandleFunc("/health.json", createHealthHandler())
|
||||
http.HandleFunc("/robots.txt", createRobotsHandler())
|
||||
|
||||
// Register hooks
|
||||
for _, hook := range cf.Hooks {
|
||||
if hook.Route == "" {
|
||||
return fmt.Errorf("no route defined in hook %s", hook.Name)
|
||||
}
|
||||
if hook.Concurrency < 1 {
|
||||
hook.Concurrency = 1
|
||||
}
|
||||
http.HandleFunc(hook.Route, createHandler(hook))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// create a http handler function from the given hook
|
||||
|
|
49
cmd/weblug/weblug_test.go
Normal file
49
cmd/weblug/weblug_test.go
Normal file
|
@ -0,0 +1,49 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
// Run tests
|
||||
ret := m.Run()
|
||||
os.Exit(ret)
|
||||
}
|
||||
|
||||
func TestWebserver(t *testing.T) {
|
||||
var cf Config
|
||||
|
||||
cf.Settings.BindAddress = "127.0.0.1:2088"
|
||||
cf.Hooks = make([]Hook, 0)
|
||||
cf.Hooks = append(cf.Hooks, Hook{Route: "/test1", Name: "test1", Command: ""})
|
||||
|
||||
listener, err := CreateListener(cf)
|
||||
if err != nil {
|
||||
t.Fatalf("Cannot create listener: %s", err)
|
||||
return
|
||||
}
|
||||
server := CreateWebserver(cf)
|
||||
RegisterHandlers(cf)
|
||||
go server.Serve(listener)
|
||||
|
||||
assertStatusCode := func(url string, statusCode int) {
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
t.Fatalf("%s", err)
|
||||
return
|
||||
}
|
||||
if resp.StatusCode != statusCode {
|
||||
t.Fatalf("GET / returns status code %d != %d", resp.StatusCode, statusCode)
|
||||
}
|
||||
}
|
||||
|
||||
// Check default sites
|
||||
baseUrl := fmt.Sprintf("http://%s/", cf.Settings.BindAddress)
|
||||
assertStatusCode(baseUrl, 200)
|
||||
|
||||
server.Shutdown(context.Background())
|
||||
}
|
Loading…
Reference in a new issue