-
-
Notifications
You must be signed in to change notification settings - Fork 460
/
server.go
140 lines (123 loc) · 3.67 KB
/
server.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
package main
import (
"context"
"log"
"net/http"
"net/url"
"os"
"os/signal"
"path"
"strconv"
"strings"
"syscall"
"time"
)
type ServerOptions struct {
Port int
Burst int
Concurrency int
HTTPCacheTTL int
HTTPReadTimeout int
HTTPWriteTimeout int
MaxAllowedSize int
MaxAllowedPixels float64
CORS bool
Gzip bool // deprecated
AuthForwarding bool
EnableURLSource bool
EnablePlaceholder bool
EnableURLSignature bool
URLSignatureKey string
Address string
PathPrefix string
APIKey string
Mount string
CertFile string
KeyFile string
Authorization string
Placeholder string
PlaceholderStatus int
ForwardHeaders []string
PlaceholderImage []byte
Endpoints Endpoints
AllowedOrigins []*url.URL
LogLevel string
ReturnSize bool
}
// Endpoints represents a list of endpoint names to disable.
type Endpoints []string
// IsValid validates if a given HTTP request endpoint is valid or not.
func (e Endpoints) IsValid(r *http.Request) bool {
parts := strings.Split(r.URL.Path, "/")
endpoint := parts[len(parts)-1]
for _, name := range e {
if endpoint == name {
return false
}
}
return true
}
func Server(o ServerOptions) {
addr := o.Address + ":" + strconv.Itoa(o.Port)
handler := NewLog(NewServerMux(o), os.Stdout, o.LogLevel)
server := &http.Server{
Addr: addr,
Handler: handler,
MaxHeaderBytes: 1 << 20,
ReadTimeout: time.Duration(o.HTTPReadTimeout) * time.Second,
WriteTimeout: time.Duration(o.HTTPWriteTimeout) * time.Second,
}
done := make(chan os.Signal, 1)
signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
go func() {
if err := listenAndServe(server, o); err != nil && err != http.ErrServerClosed {
log.Fatalf("listen: %s\n", err)
}
}()
<-done
log.Print("Graceful shutdown")
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer func() {
// extra handling here
cancel()
}()
if err := server.Shutdown(ctx); err != nil {
log.Fatalf("Server Shutdown Failed:%+v", err)
}
}
func listenAndServe(s *http.Server, o ServerOptions) error {
if o.CertFile != "" && o.KeyFile != "" {
return s.ListenAndServeTLS(o.CertFile, o.KeyFile)
}
return s.ListenAndServe()
}
func join(o ServerOptions, route string) string {
return path.Join(o.PathPrefix, route)
}
// NewServerMux creates a new HTTP server route multiplexer.
func NewServerMux(o ServerOptions) http.Handler {
mux := http.NewServeMux()
mux.Handle(join(o, "/"), Middleware(indexController(o), o))
mux.Handle(join(o, "/form"), Middleware(formController(o), o))
mux.Handle(join(o, "/health"), Middleware(healthController, o))
image := ImageMiddleware(o)
mux.Handle(join(o, "/resize"), image(Resize))
mux.Handle(join(o, "/fit"), image(Fit))
mux.Handle(join(o, "/enlarge"), image(Enlarge))
mux.Handle(join(o, "/extract"), image(Extract))
mux.Handle(join(o, "/crop"), image(Crop))
mux.Handle(join(o, "/smartcrop"), image(SmartCrop))
mux.Handle(join(o, "/rotate"), image(Rotate))
mux.Handle(join(o, "/autorotate"), image(AutoRotate))
mux.Handle(join(o, "/flip"), image(Flip))
mux.Handle(join(o, "/flop"), image(Flop))
mux.Handle(join(o, "/thumbnail"), image(Thumbnail))
mux.Handle(join(o, "/zoom"), image(Zoom))
mux.Handle(join(o, "/convert"), image(Convert))
mux.Handle(join(o, "/watermark"), image(Watermark))
mux.Handle(join(o, "/watermarkimage"), image(WatermarkImage))
mux.Handle(join(o, "/info"), image(Info))
mux.Handle(join(o, "/blur"), image(GaussianBlur))
mux.Handle(join(o, "/pipeline"), image(Pipeline))
return mux
}