• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

test-fixtures/H01-Feb-2017-

tests/H01-Feb-2017-

.gitignoreH A D01-Feb-2017259

.travis.ymlH A D01-Feb-2017229

LICENSEH A D01-Feb-20171.1 KiB

README.mdH A D01-Feb-20175 KiB

graceful.goH A D01-Feb-201713.6 KiB

graceful_test.goH A D01-Feb-201714.2 KiB

http2_test.goH A D01-Feb-20172.6 KiB

keepalive_listener.goH A D01-Feb-2017680

limit_listen.goH A D01-Feb-20171.9 KiB

signal.goH A D01-Feb-2017271

signal_appengine.goH A D01-Feb-2017243

README.md

1graceful [![GoDoc](https://godoc.org/github.com/tylerb/graceful?status.png)](http://godoc.org/github.com/tylerb/graceful) [![Build Status](https://travis-ci.org/tylerb/graceful.svg?branch=master)](https://travis-ci.org/tylerb/graceful) [![Coverage Status](https://coveralls.io/repos/tylerb/graceful/badge.svg)](https://coveralls.io/r/tylerb/graceful) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/tylerb/graceful?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
2========
3
4Graceful is a Go 1.3+ package enabling graceful shutdown of http.Handler servers.
5
6## Installation
7
8To install, simply execute:
9
10```
11go get gopkg.in/tylerb/graceful.v1
12```
13
14I am using [gopkg.in](http://labix.org/gopkg.in) to control releases.
15
16## Usage
17
18Using Graceful is easy. Simply create your http.Handler and pass it to the `Run` function:
19
20```go
21package main
22
23import (
24  "gopkg.in/tylerb/graceful.v1"
25  "net/http"
26  "fmt"
27  "time"
28)
29
30func main() {
31  mux := http.NewServeMux()
32  mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
33    fmt.Fprintf(w, "Welcome to the home page!")
34  })
35
36  graceful.Run(":3001",10*time.Second,mux)
37}
38```
39
40Another example, using [Negroni](https://github.com/codegangsta/negroni), functions in much the same manner:
41
42```go
43package main
44
45import (
46  "github.com/codegangsta/negroni"
47  "gopkg.in/tylerb/graceful.v1"
48  "net/http"
49  "fmt"
50  "time"
51)
52
53func main() {
54  mux := http.NewServeMux()
55  mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
56    fmt.Fprintf(w, "Welcome to the home page!")
57  })
58
59  n := negroni.Classic()
60  n.UseHandler(mux)
61  //n.Run(":3000")
62  graceful.Run(":3001",10*time.Second,n)
63}
64```
65
66In addition to Run there are the http.Server counterparts ListenAndServe, ListenAndServeTLS and Serve, which allow you to configure HTTPS, custom timeouts and error handling.
67Graceful may also be used by instantiating its Server type directly, which embeds an http.Server:
68
69```go
70mux := // ...
71
72srv := &graceful.Server{
73  Timeout: 10 * time.Second,
74
75  Server: &http.Server{
76    Addr: ":1234",
77    Handler: mux,
78  },
79}
80
81srv.ListenAndServe()
82```
83
84This form allows you to set the ConnState callback, which works in the same way as in http.Server:
85
86```go
87mux := // ...
88
89srv := &graceful.Server{
90  Timeout: 10 * time.Second,
91
92  ConnState: func(conn net.Conn, state http.ConnState) {
93    // conn has a new state
94  },
95
96  Server: &http.Server{
97    Addr: ":1234",
98    Handler: mux,
99  },
100}
101
102srv.ListenAndServe()
103```
104
105## Behaviour
106
107When Graceful is sent a SIGINT or SIGTERM (possibly from ^C or a kill command), it:
108
1091. Disables keepalive connections.
1102. Closes the listening socket, allowing another process to listen on that port immediately.
1113. Starts a timer of `timeout` duration to give active requests a chance to finish.
1124. When timeout expires, closes all active connections.
1135. Closes the `stopChan`, waking up any blocking goroutines.
1146. Returns from the function, allowing the server to terminate.
115
116## Notes
117
118If the `timeout` argument to `Run` is 0, the server never times out, allowing all active requests to complete.
119
120If you wish to stop the server in some way other than an OS signal, you may call the `Stop()` function.
121This function stops the server, gracefully, using the new timeout value you provide. The `StopChan()` function
122returns a channel on which you can block while waiting for the server to stop. This channel will be closed when
123the server is stopped, allowing your execution to proceed. Multiple goroutines can block on this channel at the
124same time and all will be signalled when stopping is complete.
125
126### Important things to note when setting `timeout` to 0:
127
128If you set the `timeout` to `0`, it waits for all connections to the server to disconnect before shutting down.
129This means that even though requests over a connection have finished, it is possible for the client to hold the
130connection open and block the server from shutting down indefinitely.
131
132This is especially evident when graceful is used to run HTTP/2 servers. Clients like Chrome and Firefox have been
133observed to hold onto the open connection indefinitely over HTTP/2, preventing the server from shutting down. In
134addition, there is also the risk of malicious clients holding and keeping the connection alive.
135
136It is understandable that sometimes, you might want to wait for the client indefinitely because they might be
137uploading large files. In these type of cases, it is recommended that you set a reasonable timeout to kill the
138connection, and have the client perform resumable uploads. For example, the client can divide the file into chunks
139and reupload chunks that were in transit when the connection was terminated.
140
141## Contributing
142
143If you would like to contribute, please:
144
1451. Create a GitHub issue regarding the contribution. Features and bugs should be discussed beforehand.
1462. Fork the repository.
1473. Create a pull request with your solution. This pull request should reference and close the issues (Fix #2).
148
149All pull requests should:
150
1511. Pass [gometalinter -t .](https://github.com/alecthomas/gometalinter) with no warnings.
1522. Be `go fmt` formatted.
153