Skip to content

Instantly share code, notes, and snippets.

@donovanhide
Created September 27, 2017 13:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save donovanhide/13c4444903416e166ac51c9496d225e9 to your computer and use it in GitHub Desktop.
Save donovanhide/13c4444903416e166ac51c9496d225e9 to your computer and use it in GitHub Desktop.
package client
import (
"bufio"
"crypto/tls"
"fmt"
"net"
"net/http"
)
type OrderedHTTPResponse struct {
Response *http.Response
Err error
}
type work struct {
req *http.Request
c chan *OrderedHTTPResponse
}
type OrderedHTTPClient struct {
conn net.Conn
out chan *work
in chan *work
}
func NewOrderedHTTPClient(host string) (*OrderedHTTPClient, error) {
conn, err := tls.Dial("tcp", host, nil)
if err != nil {
return nil, err
}
client := &OrderedHTTPClient{
conn: conn,
out: make(chan *work, 100),
in: make(chan *work, 100),
}
go client.writePump()
go client.readPump()
return client, nil
}
func (c *OrderedHTTPClient) Close() {
close(c.out)
close(c.in)
}
func (c *OrderedHTTPClient) writePump() {
for job := range c.out {
if err := job.req.Write(c.conn); err != nil {
job.c <- &OrderedHTTPResponse{Err: fmt.Errorf("write: %v", err)}
continue
}
c.in <- job
}
}
func (c *OrderedHTTPClient) readPump() {
defer c.conn.Close()
r := bufio.NewReader(c.conn)
for job := range c.in {
resp, err := http.ReadResponse(r, job.req)
if err != nil {
job.c <- &OrderedHTTPResponse{Err: fmt.Errorf("read: %v", err)}
} else {
job.c <- &OrderedHTTPResponse{Response: resp}
}
}
}
func (c *OrderedHTTPClient) Do(req *http.Request) chan *OrderedHTTPResponse {
job := &work{
req: req,
c: make(chan *OrderedHTTPResponse, 1),
}
c.out <- job
return job.c
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment