-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.go
124 lines (116 loc) · 3.09 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
package main
import (
"bytes"
"flag"
"fmt"
"io/ioutil"
"log"
"net"
"net/http"
"os"
"path/filepath"
"strconv"
)
const (
defaultAddr = ":8080"
addrEnvVarName = "ADDR"
portEnvVarName = "PORT"
quietEnvVarName = "QUIET"
httpStatusEnvVarName = "HTTP_STATUS"
)
var (
addrFlag = os.Getenv(addrEnvVarName)
portFlag64, _ = strconv.ParseInt(os.Getenv(portEnvVarName), 10, 64)
portFlag = int(portFlag64)
quietFlag bool
httpStatusFlag = http.StatusOK
)
func init() {
log.SetFlags(log.LUTC | log.Ldate | log.Ltime | log.Lmicroseconds)
log.SetOutput(os.Stderr)
if addrFlag == "" {
addrFlag = defaultAddr
}
flag.StringVar(&addrFlag, "addr", addrFlag, fmt.Sprintf("address to listen on (environment variable %q)", addrEnvVarName))
flag.StringVar(&addrFlag, "a", addrFlag, "(alias for -addr)")
flag.IntVar(&portFlag, "port", portFlag, fmt.Sprintf("port to listen on (overrides -addr port) (environment variable %q)", portEnvVarName))
flag.IntVar(&portFlag, "p", portFlag, "(alias for -port)")
flag.BoolVar(&quietFlag, "quiet", quietFlag, fmt.Sprintf("disable all log output (environment variable %q)", quietEnvVarName))
flag.BoolVar(&quietFlag, "q", quietFlag, "(alias for -quiet)")
flag.IntVar(&httpStatusFlag, "http-status", httpStatusFlag, fmt.Sprintf("use this HTTP status for responses (environment variable %q)", httpStatusEnvVarName))
flag.Parse()
if quietFlag {
log.SetOutput(ioutil.Discard)
}
}
func main() {
addr, err := addr()
if err != nil {
log.Fatalf("address/port: %v", err)
}
status, err := status()
if err != nil {
log.Fatal(err)
}
binaryPath, _ := os.Executable()
if binaryPath == "" {
binaryPath = "server"
}
statusText := http.StatusText(status)
if statusText == "" {
statusText = "unknown status code"
}
log.Printf("%s listening on %q, responding with HTTP %d (%s)", filepath.Base(binaryPath), addr, status, statusText)
err = server(addr, status)
if err != nil {
log.Fatalf("start server: %v", err)
}
}
func server(addr string, status int) error {
mux := http.DefaultServeMux
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(status)
err := r.Write(w)
if err != nil {
log.Printf("writing response: %v", err)
return
}
if !quietFlag {
var buf bytes.Buffer
r.Write(&buf)
log.Printf("request: %q", buf.String())
}
})
return http.ListenAndServe(addr, mux)
}
func status() (int, error) {
if httpStatusFlag < 100 || httpStatusFlag > 999 {
return 0, fmt.Errorf("invalid HTTP status code: %d", httpStatusFlag)
}
return httpStatusFlag, nil
}
func addr() (string, error) {
portSet := portFlag != 0
addrSet := addrFlag != ""
switch {
case portSet && addrSet:
a, err := net.ResolveTCPAddr("tcp", addrFlag)
if err != nil {
return "", err
}
a.Port = portFlag
return a.String(), nil
case !portSet && addrSet:
a, err := net.ResolveTCPAddr("tcp", addrFlag)
if err != nil {
return "", err
}
return a.String(), nil
case portSet && !addrSet:
return fmt.Sprintf(":%d", portFlag), nil
case !portSet && !addrSet:
fallthrough
default:
return defaultAddr, nil
}
}