Forked from perillo/try-http-ctx-cancellation.go
Last active
January 7, 2020 15:32
-
-
Save vigliag/92046915cb0c3377464b9841a9216aa7 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"io" | |
"log" | |
"net/http" | |
"time" | |
) | |
func newReader(delay time.Duration) io.Reader { | |
r, w := io.Pipe() | |
go func() { | |
for { | |
n, err := w.Write([]byte("x\n")) | |
if err != nil { | |
log.Printf("writing request body: %v", n) | |
continue | |
} | |
fmt.Printf("wrote %d bytes to request body\n", n) | |
time.Sleep(delay) | |
} | |
w.Close() | |
}() | |
return r | |
} | |
func client(addr string, delay time.Duration) error { | |
addr = "http://" + addr // make a correct URL from a IP address | |
body := newReader(delay) | |
fmt.Println("starting client") | |
res, err := http.Post(addr, "text/plain", body) | |
if err != nil { | |
log.Fatal(err) | |
} | |
log.Println(res) | |
return err | |
} | |
func server(addr string, handler http.HandlerFunc, timeout time.Duration) error { | |
srv := http.Server{ | |
Addr: addr, | |
Handler: handler, | |
ReadTimeout: timeout, | |
} | |
fmt.Println("starting server") | |
return srv.ListenAndServe() | |
} | |
func handler(w http.ResponseWriter, req *http.Request) { | |
buf := make([]byte, 2) | |
ctx := req.Context() | |
// A simple concurrent worker. | |
for { | |
select { | |
case <-ctx.Done(): | |
log.Printf("cancelling job") | |
return | |
default: | |
n, err := req.Body.Read(buf) | |
if err != nil { | |
log.Printf("reading request body: %v", err) | |
continue // give ctx.Done a chance | |
} | |
fmt.Printf("read %d bytes from request body\n", n) | |
} | |
} | |
} | |
func main() { | |
const ( | |
addr = "127.0.0.1:8080" | |
delay = time.Second | |
timeout = 3 * time.Second | |
) | |
log.SetFlags(0) | |
go func() { | |
if err := server(addr, handler, timeout); err != nil { | |
log.Fatal(err) | |
} | |
}() | |
time.Sleep(1 * time.Second) // poor man synchronization with the server | |
client(addr, delay) // the client will wait forever for the server response | |
fmt.Println("done") | |
time.Sleep(1 * time.Second) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment