aboutsummaryrefslogtreecommitdiff
path: root/cmd/server/main.go
blob: f4f8dc3d6ea58ed872fece29ed08e0799d45e235 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package main

import (
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"
	"strings"
	"time"

	"github.com/gomodule/redigo/redis"
	"gopkg.in/yaml.v3"
	"riedstra.dev/mitch/go-website/envflag"
	"riedstra.dev/mitch/go-website/page"
)

var VersionString = ""

var logger = log.New(os.Stderr, "", 0)

func VersionPrint() {
	fmt.Println(VersionString)
	os.Exit(0)
}

func logIfErr(err error) {
	if err != nil {
		logger.Println(err)
	}
}

func main() { //nolint:funlen
	var (
		listen           = ":8001"
		directory        = "."
		version          = false
		confFn           = "conf.yml"
		authConfFn       = "auth.json"
		verbose          = false
		defaultIndexPath = "/reIndex"
		indexPath        = "/reIndex"
		redisAddr        = "127.0.0.1:6379"
		redisKey         = "go-website"
		pageTimeout      = 15
		genhash          = false
	)

	fl := flag.NewFlagSet("Website", flag.ExitOnError)

	envflag.String(fl, &directory, "d", "SITE_DIR",
		"Website directory to serve")
	envflag.String(fl, &listen, "l", "LISTEN_ADDR", "listening address")
	logIfErr(envflag.Bool(fl, &version, "v", "PRINT_VERSION_AND_EXIT",
		"print version and exit"))
	envflag.String(fl, &confFn, "c", "CONFIG_FILE",
		"Location for configuration file")
	envflag.String(fl, &authConfFn, "ac", "AUTH_CONFIG",
		"location for the authorization config")
	logIfErr(envflag.Bool(fl, &verbose, "V", "VERBOSE",
		"Be more verbose, dump config and such"))
	envflag.String(fl, &page.TimeFormat, "T", "TIME_FORMAT",
		"Override the default format used to parse page time. Be careful.")
	envflag.String(fl, &indexPath, "i", "INDEX_PATH",
		"Path in which, when called will rebuild the index and clear the cache")
	envflag.String(fl, &redisAddr, "r", "REDIS_ADDR",
		"Redis server set to \"\" to disable")
	envflag.String(fl, &redisKey, "rk", "REDIS_KEY",
		"Redis key to use for storing cached pages")
	logIfErr(envflag.Int(fl, &pageTimeout, "timeout", "HTTP_TIMEOUT",
		"Seconds until page timeout for read and write"))
	logIfErr(envflag.Bool(fl, &page.CacheIndex, "cache-index", "CACHE_INDEX",
		"If set to false, do not cache the page index"))
	logIfErr(envflag.Bool(fl, &genhash, "genhash", "INTERACTIVE_HASH_GEN",
		"If set to true, interactively generate a password hash"))

	_ = fl.Parse(os.Args[1:])

	if version {
		VersionPrint()
	}

	if genhash {
		interactiveHashGen()
		os.Exit(0)
	}

	if err := os.Chdir(directory); err != nil {
		logger.Fatal(err)
	}

	app, err := loadConf(confFn)
	if err != nil {
		logger.Println(err)

		app = &App{}
	}

	err = app.ReadAuth(authConfFn)
	if err != nil {
		logger.Println(err)
	}

	if app.ReIndexPath == "" || indexPath != defaultIndexPath {
		app.ReIndexPath = indexPath
	}

	if app.RedisKey == "" {
		app.RedisKey = redisKey
	}

	if redisAddr != "" {
		app.redisPool = &redis.Pool{
			MaxIdle:   80,    //nolint:gomnd
			MaxActive: 12000, //nolint:gomnd
			Dial: func() (redis.Conn, error) {
				c, err := redis.Dial("tcp", redisAddr)

				if strings.HasPrefix(redisAddr, "unix:") {
					c, err = redis.Dial("unix", strings.TrimPrefix(redisAddr, "unix:"))
				}

				if err != nil {
					logger.Println("Redis dial error: ", err)
				}

				return c, err //nolint
			},
		}
	}

	if verbose {
		b, _ := yaml.Marshal(app)
		os.Stderr.Write(b)
	}

	page.Funcs["ClearRedis"] = app.ClearRedis

	srv := &http.Server{
		Handler:      app,
		Addr:         listen,
		WriteTimeout: time.Duration(pageTimeout) * time.Second,
		ReadTimeout:  time.Duration(pageTimeout) * time.Second,
	}
	logger.Fatal(srv.ListenAndServe())
}