Codebase list golang-github-zenazn-goji / d2eaead
Import Upstream version 1.0.1 Thorsten Alteholz 3 years ago
8 changed file(s) with 226 addition(s) and 64 deletion(s). Raw diff Collapse all Expand all
00 language: go
11
2 matrix:
3 include:
4 - go: 1.2
5 install:
6 - go get golang.org/x/tools/cmd/cover
7 - go list -f '{{range .Imports}}{{.}} {{end}}' ./... | xargs go get -v
8 - go list -f '{{range .TestImports}}{{.}} {{end}}' ./... | xargs go get -v
9 - go: 1.3
10 install:
11 - go get golang.org/x/tools/cmd/cover
12 - go list -f '{{range .Imports}}{{.}} {{end}}' ./... | xargs go get -v
13 - go list -f '{{range .TestImports}}{{.}} {{end}}' ./... | xargs go get -v
14 - go: 1.4
15 install:
16 - go get golang.org/x/tools/cmd/cover
17 - go list -f '{{range .Imports}}{{.}} {{end}}' ./... | xargs go get -v
18 - go list -f '{{range .TestImports}}{{.}} {{end}}' ./... | xargs go get -v
19 - go: 1.5
20 install:
21 - go list -f '{{range .Imports}}{{.}} {{end}}' ./... | xargs go get -v
22 - go list -f '{{range .TestImports}}{{.}} {{end}}' ./... | xargs go get -v
23 - go: 1.6
24 install:
25 - go list -f '{{range .Imports}}{{.}} {{end}}' ./... | xargs go get -v
26 - go list -f '{{range .TestImports}}{{.}} {{end}}' ./... | xargs go get -v
27 - go: tip
28 install:
29 - go list -f '{{range .Imports}}{{.}} {{end}}' ./... | xargs go get -v
30 - go list -f '{{range .TestImports}}{{.}} {{end}}' ./... | xargs go get -v
31 script:
32 - go test -cover ./...
2 go:
3 - "1.5.x"
4 - "1.6.x"
5 - "1.7.x"
6 - "1.8.x"
7 - "1.9.x"
8 - "1.10.x"
9 - "1.11.x"
10
11 install:
12 - go list -f '{{range .Imports}}{{.}} {{end}}' ./... | xargs go get -v
13 - go list -f '{{range .TestImports}}{{.}} {{end}}' ./... | xargs go get -v
14
15 script: go test -cover ./...
16
88
99 import (
1010 "net"
11 "runtime"
1211 "sync/atomic"
1312
1413 "github.com/zenazn/goji/graceful/listener"
4948 // Unfortunately Go doesn't really give us a better way to select errors
5049 // than this, so *shrug*.
5150 if oe, ok := err.(*net.OpError); ok {
52 errOp := "accept"
53 if runtime.GOOS == "windows" {
54 errOp = "AcceptEx"
55 }
56 if oe.Op == errOp && oe.Err.Error() == errClosing {
57 return nil
51 switch oe.Op {
52 // backward compatibility: older golang returns AcceptEx on Windows.
53 // Current golang returns "accept" consistently. It's platform independent.
54 // See https://github.com/golang/go/commit/b0f4ee533a875c258ac1030ee382f0ffe2de304b
55 case "AcceptEx":
56 fallthrough
57 case "accept":
58 if oe.Err.Error() == errClosing {
59 return nil
60 }
5861 }
5962 }
6063 return err
1111
1212 var mu sync.Mutex // protects everything that follows
1313 var listeners = make([]*listener.T, 0)
14 var prehooks = make([]func(), 0)
15 var posthooks = make([]func(), 0)
14 var prehooks = make([]func(os.Signal), 0)
15 var posthooks = make([]func(os.Signal), 0)
1616 var closing int32
1717 var doubleKick, timeout time.Duration
1818
3939 signal.Stop(sigchan)
4040 }
4141
42 // PreHookWithSignal registers a function to be called before any of this
43 // package's normal shutdown actions, which recieves the signal that caused the
44 // shutdown (or nil for manual shutdowns). All listeners will be called in the
45 // order they were added, from a single goroutine.
46 func PreHookWithSignal(f func(os.Signal)) {
47 mu.Lock()
48 defer mu.Unlock()
49
50 prehooks = append(prehooks, f)
51 }
52
4253 // PreHook registers a function to be called before any of this package's normal
4354 // shutdown actions. All listeners will be called in the order they were added,
4455 // from a single goroutine.
4556 func PreHook(f func()) {
46 mu.Lock()
47 defer mu.Unlock()
48
49 prehooks = append(prehooks, f)
57 PreHookWithSignal(func(_ os.Signal) {
58 f()
59 })
60 }
61
62 // PostHookWithSignal registers a function to be called after all of this
63 // package's normal shutdown actions, which receives the signal that caused the
64 // shutdown (or nil for manual shutdowns). All listeners will be called in the
65 // order they were added, from a single goroutine, and are guaranteed to be
66 // called after all listening connections have been closed, but before Wait()
67 // returns.
68 //
69 // If you've Hijacked any connections that must be gracefully shut down in some
70 // other way (since this library disowns all hijacked connections), it's
71 // reasonable to use a PostHook to signal and wait for them.
72 func PostHookWithSignal(f func(os.Signal)) {
73 mu.Lock()
74 defer mu.Unlock()
75
76 posthooks = append(posthooks, f)
5077 }
5178
5279 // PostHook registers a function to be called after all of this package's normal
5885 // other way (since this library disowns all hijacked connections), it's
5986 // reasonable to use a PostHook to signal and wait for them.
6087 func PostHook(f func()) {
61 mu.Lock()
62 defer mu.Unlock()
63
64 posthooks = append(posthooks, f)
88 PostHookWithSignal(func(_ os.Signal) {
89 f()
90 })
6591 }
6692
6793 // Shutdown manually triggers a shutdown from your application. Like Wait,
6894 // blocks until all connections have gracefully shut down.
6995 func Shutdown() {
70 shutdown(false)
96 shutdown(false, nil)
7197 }
7298
7399 // ShutdownNow triggers an immediate shutdown from your application. All
74100 // connections (not just those that are idle) are immediately closed, even if
75101 // they are in the middle of serving a request.
76102 func ShutdownNow() {
77 shutdown(true)
103 shutdown(true, nil)
78104 }
79105
80106 // DoubleKickWindow sets the length of the window during which two back-to-back
122148 func sigLoop() {
123149 var last time.Time
124150 for {
125 <-sigchan
151 sig := <-sigchan
126152 now := time.Now()
127153 mu.Lock()
128154 force := doubleKick != 0 && now.Sub(last) < doubleKick
129155 if t := timeout; t != 0 && !force {
130156 go func() {
131157 time.Sleep(t)
132 shutdown(true)
158 shutdown(true, sig)
133159 }()
134160 }
135161 mu.Unlock()
136 go shutdown(force)
162 go shutdown(force, sig)
137163 last = now
138164 }
139165 }
140166
141167 var preOnce, closeOnce, forceOnce, postOnce, notifyOnce sync.Once
142168
143 func shutdown(force bool) {
169 func shutdown(force bool, sig os.Signal) {
144170 preOnce.Do(func() {
145171 mu.Lock()
146172 defer mu.Unlock()
147173 for _, f := range prehooks {
148 f()
174 f(sig)
149175 }
150176 })
151177
163189 mu.Lock()
164190 defer mu.Unlock()
165191 for _, f := range posthooks {
166 f()
192 f(sig)
167193 }
168194 })
169195
6363 for _, test := range funcEqualTests {
6464 r := funcEqual(test.a, test.b)
6565 if r != test.result {
66 t.Errorf("funcEqual(%v, %v) should have been %v",
66 t.Errorf("funcEqual(%p, %p) should have been %v",
6767 test.a, test.b, test.result)
6868 }
6969 }
147147 }
148148
149149 copy(m.stack[i:], m.stack[i+1:])
150 m.stack = m.stack[:len(m.stack)-1 : len(m.stack)]
150 m.stack = m.stack[: len(m.stack)-1 : len(m.stack)]
151151
152152 m.invalidate()
153153 return nil
0 // +build !go1.8
1
02 package mutil
13
24 import (
6163 b.ResponseWriter.WriteHeader(code)
6264 }
6365 }
66
6467 func (b *basicWriter) Write(buf []byte) (int, error) {
6568 b.WriteHeader(http.StatusOK)
6669 n, err := b.ResponseWriter.Write(buf)
7477 b.bytes += n
7578 return n, err
7679 }
80
7781 func (b *basicWriter) maybeWriteHeader() {
7882 if !b.wroteHeader {
7983 b.WriteHeader(http.StatusOK)
8084 }
8185 }
86
8287 func (b *basicWriter) Status() int {
8388 return b.code
8489 }
90
8591 func (b *basicWriter) BytesWritten() int {
8692 return b.bytes
8793 }
94
8895 func (b *basicWriter) Tee(w io.Writer) {
8996 b.tee = w
9097 }
98
9199 func (b *basicWriter) Unwrap() http.ResponseWriter {
92100 return b.ResponseWriter
93101 }
104112 cn := f.basicWriter.ResponseWriter.(http.CloseNotifier)
105113 return cn.CloseNotify()
106114 }
115
107116 func (f *fancyWriter) Flush() {
108117 fl := f.basicWriter.ResponseWriter.(http.Flusher)
109118 fl.Flush()
110119 }
120
111121 func (f *fancyWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
112122 hj := f.basicWriter.ResponseWriter.(http.Hijacker)
113123 return hj.Hijack()
114124 }
125
115126 func (f *fancyWriter) ReadFrom(r io.Reader) (int64, error) {
116127 if f.basicWriter.tee != nil {
117128 return io.Copy(&f.basicWriter, r)
120131 f.basicWriter.maybeWriteHeader()
121132 return rf.ReadFrom(r)
122133 }
123
124 var _ http.CloseNotifier = &fancyWriter{}
125 var _ http.Flusher = &fancyWriter{}
126 var _ http.Hijacker = &fancyWriter{}
127 var _ io.ReaderFrom = &fancyWriter{}
128134
129135 type flushWriter struct {
130136 basicWriter
135141 fl.Flush()
136142 }
137143
138 var _ http.Flusher = &flushWriter{}
144 var (
145 _ http.CloseNotifier = &fancyWriter{}
146 _ http.Flusher = &fancyWriter{}
147 _ http.Hijacker = &fancyWriter{}
148 _ io.ReaderFrom = &fancyWriter{}
149 _ http.Flusher = &flushWriter{}
150 )
0 // +build go1.8
1
2 package mutil
3
4 import (
5 "bufio"
6 "io"
7 "net"
8 "net/http"
9 )
10
11 // WriterProxy is a proxy around an http.ResponseWriter that allows you to hook
12 // into various parts of the response process.
13 type WriterProxy interface {
14 http.ResponseWriter
15 // Status returns the HTTP status of the request, or 0 if one has not
16 // yet been sent.
17 Status() int
18 // BytesWritten returns the total number of bytes sent to the client.
19 BytesWritten() int
20 // Tee causes the response body to be written to the given io.Writer in
21 // addition to proxying the writes through. Only one io.Writer can be
22 // tee'd to at once: setting a second one will overwrite the first.
23 // Writes will be sent to the proxy before being written to this
24 // io.Writer. It is illegal for the tee'd writer to be modified
25 // concurrently with writes.
26 Tee(io.Writer)
27 // Unwrap returns the original proxied target.
28 Unwrap() http.ResponseWriter
29 }
30
31 // WrapWriter wraps an http.ResponseWriter, returning a proxy that allows you to
32 // hook into various parts of the response process.
33 func WrapWriter(w http.ResponseWriter) WriterProxy {
34 _, fl := w.(http.Flusher)
35 _, hj := w.(http.Hijacker)
36 _, rf := w.(io.ReaderFrom)
37
38 bw := basicWriter{ResponseWriter: w}
39 if fl && hj && rf {
40 return &fancyWriter{bw}
41 }
42 return &bw
43 }
44
45 // basicWriter wraps a http.ResponseWriter that implements the minimal
46 // http.ResponseWriter interface.
47 type basicWriter struct {
48 http.ResponseWriter
49 wroteHeader bool
50 code int
51 bytes int
52 tee io.Writer
53 }
54
55 func (b *basicWriter) WriteHeader(code int) {
56 if !b.wroteHeader {
57 b.code = code
58 b.wroteHeader = true
59 b.ResponseWriter.WriteHeader(code)
60 }
61 }
62
63 func (b *basicWriter) Write(buf []byte) (int, error) {
64 b.WriteHeader(http.StatusOK)
65 n, err := b.ResponseWriter.Write(buf)
66 if b.tee != nil {
67 _, err2 := b.tee.Write(buf[:n])
68 // Prefer errors generated by the proxied writer.
69 if err == nil {
70 err = err2
71 }
72 }
73 b.bytes += n
74 return n, err
75 }
76
77 func (b *basicWriter) maybeWriteHeader() {
78 if !b.wroteHeader {
79 b.WriteHeader(http.StatusOK)
80 }
81 }
82
83 func (b *basicWriter) Status() int {
84 return b.code
85 }
86
87 func (b *basicWriter) BytesWritten() int {
88 return b.bytes
89 }
90
91 func (b *basicWriter) Tee(w io.Writer) {
92 b.tee = w
93 }
94
95 func (b *basicWriter) Unwrap() http.ResponseWriter {
96 return b.ResponseWriter
97 }
98
99 // fancyWriter is a writer that additionally satisfies http.Pusher,
100 // http.Flusher, http.Hijacker, and io.ReaderFrom. It exists for the common case
101 // of wrapping the http.ResponseWriter that package http gives you, in order to
102 // make the proxied object support the full method set of the proxied object.
103 type fancyWriter struct {
104 basicWriter
105 }
106
107 func (f *fancyWriter) Push(target string, opts *http.PushOptions) error {
108 return f.basicWriter.ResponseWriter.(http.Pusher).Push(target, opts)
109 }
110
111 func (f *fancyWriter) Flush() {
112 fl := f.basicWriter.ResponseWriter.(http.Flusher)
113 fl.Flush()
114 }
115
116 func (f *fancyWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
117 hj := f.basicWriter.ResponseWriter.(http.Hijacker)
118 return hj.Hijack()
119 }
120
121 func (f *fancyWriter) ReadFrom(r io.Reader) (int64, error) {
122 if f.basicWriter.tee != nil {
123 return io.Copy(&f.basicWriter, r)
124 }
125 rf := f.basicWriter.ResponseWriter.(io.ReaderFrom)
126 f.basicWriter.maybeWriteHeader()
127 return rf.ReadFrom(r)
128 }
129
130 var (
131 _ http.Pusher = &fancyWriter{}
132 _ http.Flusher = &fancyWriter{}
133 _ http.Hijacker = &fancyWriter{}
134 _ io.ReaderFrom = &fancyWriter{}
135 )