Skip to content

Instantly share code, notes, and snippets.

@mikemadisonweb
Created August 16, 2017 14:55
Show Gist options
  • Save mikemadisonweb/72067f5e7123b98259d87511236ccc78 to your computer and use it in GitHub Desktop.
Save mikemadisonweb/72067f5e7123b98259d87511236ccc78 to your computer and use it in GitHub Desktop.
Run a http.Get async with support for aborting
package main
import (
"errors"
"fmt"
"net"
"net/http"
"sync"
"time"
)
type GetResponse struct {
Resp *http.Response
Error error
}
type Request struct {
mu sync.Mutex
conn net.Conn
client *http.Client
Resp chan GetResponse
}
func abortDial(netw, addr string) (net.Conn, error) {
return nil, errors.New("aborted")
}
func (r *Request) Bail() {
r.mu.Lock()
defer r.mu.Unlock()
if r.conn != nil {
r.conn.Close()
}
r.client.Transport.(*http.Transport).Dial = abortDial
}
func (r *Request) set(c net.Conn) {
r.mu.Lock()
defer r.mu.Unlock()
r.conn = c
}
func Get(url string) (r *Request) {
dial := func(netw, addr string) (c net.Conn, err error) {
c, err = net.Dial(netw, addr)
r.set(c)
return
}
transport := &http.Transport{
Proxy: http.ProxyFromEnvironment,
Dial: dial,
}
r = &Request{
Resp: make(chan GetResponse),
client: &http.Client{Transport: transport},
}
go func() {
resp, err := r.client.Get(url)
r.Resp <- GetResponse{resp, err}
}()
return
}
func main() {
req := Get("http://google.com")
for {
select {
case resp := <-req.Resp:
fmt.Println(resp)
return
case <-time.After(time.Second):
req.Bail()
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment