forked from codeskyblue/gohttpserver
/
main.go
141 lines (122 loc) · 3.64 KB
/
main.go
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
package main
import (
"bytes"
"encoding/json"
"log"
"net/http"
"net/url"
"runtime"
"strconv"
"strings"
"text/template"
"github.com/alecthomas/kingpin"
"github.com/goji/httpauth"
"github.com/gorilla/handlers"
accesslog "github.com/mash/go-accesslog"
)
type Configure struct {
Addr string
Root string
HttpAuth string
Cert string
Key string
Cors bool
Theme string
XHeaders bool
Upload bool
PlistProxy *url.URL
Title string
}
type logger struct {
}
func (l logger) Log(record accesslog.LogRecord) {
log.Printf("%s [code %d] %s", record.Method, record.Status, record.Uri)
}
var (
defaultPlistProxy = "https://plistproxy.herokuapp.com/plist"
gcfg = Configure{}
l = logger{}
VERSION = "unknown"
BUILDTIME = "unknown time"
GITCOMMIT = "unknown git commit"
SITE = "https://github.com/codeskyblue/gohttpserver"
)
func versionMessage() string {
t := template.Must(template.New("version").Parse(`GoHTTPServer
Version: {{.Version}}
Go version: {{.GoVersion}}
OS/Arch: {{.OSArch}}
Git commit: {{.GitCommit}}
Built: {{.Built}}
Site: {{.Site}}`))
buf := bytes.NewBuffer(nil)
t.Execute(buf, map[string]interface{}{
"Version": VERSION,
"GoVersion": runtime.Version(),
"OSArch": runtime.GOOS + "/" + runtime.GOARCH,
"GitCommit": GITCOMMIT,
"Built": BUILDTIME,
"Site": SITE,
})
return buf.String()
}
func parseFlags() {
kingpin.HelpFlag.Short('h')
kingpin.Version(versionMessage())
kingpin.Flag("root", "root directory").Short('r').Default("./").StringVar(&gcfg.Root)
kingpin.Flag("addr", "listen address").Short('a').Default(":8000").StringVar(&gcfg.Addr)
kingpin.Flag("cert", "tls cert.pem path").StringVar(&gcfg.Cert)
kingpin.Flag("key", "tls key.pem path").StringVar(&gcfg.Key)
kingpin.Flag("httpauth", "HTTP basic auth (ex: user:pass)").Default("").StringVar(&gcfg.HttpAuth)
kingpin.Flag("theme", "web theme, one of <black|green>").Default("black").StringVar(&gcfg.Theme)
kingpin.Flag("upload", "enable upload support").BoolVar(&gcfg.Upload)
kingpin.Flag("xheaders", "used when behide nginx").BoolVar(&gcfg.XHeaders)
kingpin.Flag("cors", "enable cross-site HTTP request").BoolVar(&gcfg.Cors)
kingpin.Flag("plistproxy", "plist proxy when server is not https").Default(defaultPlistProxy).Short('p').URLVar(&gcfg.PlistProxy)
kingpin.Flag("title", "server title").Default("Go HTTP File Server").StringVar(&gcfg.Title)
kingpin.Parse()
}
func main() {
parseFlags()
ss := NewHTTPStaticServer(gcfg.Root)
ss.Theme = gcfg.Theme
ss.Title = gcfg.Title
if gcfg.Upload {
ss.EnableUpload()
}
if gcfg.PlistProxy != nil {
gcfg.PlistProxy.Scheme = "https"
ss.PlistProxy = gcfg.PlistProxy.String()
}
var hdlr http.Handler = ss
hdlr = accesslog.NewLoggingHandler(hdlr, l)
// HTTP Basic Authentication
userpass := strings.SplitN(gcfg.HttpAuth, ":", 2)
if len(userpass) == 2 {
user, pass := userpass[0], userpass[1]
hdlr = httpauth.SimpleBasicAuth(user, pass)(hdlr)
}
// CORS
if gcfg.Cors {
hdlr = handlers.CORS()(hdlr)
}
if gcfg.XHeaders {
hdlr = handlers.ProxyHeaders(hdlr)
}
http.Handle("/", hdlr)
http.HandleFunc("/-/sysinfo", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
data, _ := json.Marshal(map[string]interface{}{
"version": VERSION,
})
w.Write(data)
})
log.Printf("Listening on addr: %s\n", strconv.Quote(gcfg.Addr))
var err error
if gcfg.Key != "" && gcfg.Cert != "" {
err = http.ListenAndServeTLS(gcfg.Addr, gcfg.Cert, gcfg.Key, nil)
} else {
err = http.ListenAndServe(gcfg.Addr, nil)
}
log.Fatal(err)
}