Make (*Response).Body an io.ReadCloser
This commit is contained in:
parent
860a33f5a2
commit
12a9deb1a6
@ -66,7 +66,6 @@ func (c *Client) Send(req *Request) (*Response, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer conn.Close()
|
|
||||||
|
|
||||||
// Write the request
|
// Write the request
|
||||||
w := bufio.NewWriter(conn)
|
w := bufio.NewWriter(conn)
|
||||||
@ -77,8 +76,7 @@ func (c *Client) Send(req *Request) (*Response, error) {
|
|||||||
|
|
||||||
// Read the response
|
// Read the response
|
||||||
resp := &Response{}
|
resp := &Response{}
|
||||||
r := bufio.NewReader(conn)
|
if err := resp.read(conn); err != nil {
|
||||||
if err := resp.read(r); err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// Store connection information
|
// Store connection information
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
@ -80,7 +81,12 @@ func sendRequest(req *gmi.Request) error {
|
|||||||
req.URL.RawQuery = url.QueryEscape(scanner.Text())
|
req.URL.RawQuery = url.QueryEscape(scanner.Text())
|
||||||
return sendRequest(req)
|
return sendRequest(req)
|
||||||
case gmi.StatusClassSuccess:
|
case gmi.StatusClassSuccess:
|
||||||
fmt.Print(string(resp.Body))
|
defer resp.Body.Close()
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Print(string(body))
|
||||||
return nil
|
return nil
|
||||||
case gmi.StatusClassRedirect:
|
case gmi.StatusClassRedirect:
|
||||||
fmt.Println("Redirecting to", resp.Meta)
|
fmt.Println("Redirecting to", resp.Meta)
|
||||||
|
53
response.go
53
response.go
@ -3,7 +3,7 @@ package gemini
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -18,19 +18,20 @@ type Response struct {
|
|||||||
// Meta should not be longer than 1024 bytes.
|
// Meta should not be longer than 1024 bytes.
|
||||||
Meta string
|
Meta string
|
||||||
|
|
||||||
// Body contains the response body.
|
// Body contains the response body for successful responses.
|
||||||
Body []byte
|
Body io.ReadCloser
|
||||||
|
|
||||||
// TLS contains information about the TLS connection on which the response
|
// TLS contains information about the TLS connection on which the response
|
||||||
// was received.
|
// was received.
|
||||||
TLS tls.ConnectionState
|
TLS tls.ConnectionState
|
||||||
}
|
}
|
||||||
|
|
||||||
// read reads a Gemini response from the provided buffered reader.
|
// read reads a Gemini response from the provided io.ReadCloser.
|
||||||
func (resp *Response) read(r *bufio.Reader) error {
|
func (resp *Response) read(rc io.ReadCloser) error {
|
||||||
|
br := bufio.NewReader(rc)
|
||||||
// Read the status
|
// Read the status
|
||||||
statusB := make([]byte, 2)
|
statusB := make([]byte, 2)
|
||||||
if _, err := r.Read(statusB); err != nil {
|
if _, err := br.Read(statusB); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
status, err := strconv.Atoi(string(statusB))
|
status, err := strconv.Atoi(string(statusB))
|
||||||
@ -47,14 +48,14 @@ func (resp *Response) read(r *bufio.Reader) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Read one space
|
// Read one space
|
||||||
if b, err := r.ReadByte(); err != nil {
|
if b, err := br.ReadByte(); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if b != ' ' {
|
} else if b != ' ' {
|
||||||
return ErrInvalidResponse
|
return ErrInvalidResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the meta
|
// Read the meta
|
||||||
meta, err := r.ReadString('\r')
|
meta, err := br.ReadString('\r')
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -67,19 +68,41 @@ func (resp *Response) read(r *bufio.Reader) error {
|
|||||||
resp.Meta = meta
|
resp.Meta = meta
|
||||||
|
|
||||||
// Read terminating newline
|
// Read terminating newline
|
||||||
if b, err := r.ReadByte(); err != nil {
|
if b, err := br.ReadByte(); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if b != '\n' {
|
} else if b != '\n' {
|
||||||
return ErrInvalidResponse
|
return ErrInvalidResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read response body
|
|
||||||
if resp.Status.Class() == StatusClassSuccess {
|
if resp.Status.Class() == StatusClassSuccess {
|
||||||
var err error
|
resp.Body = newReadCloserBody(br, rc)
|
||||||
resp.Body, err = ioutil.ReadAll(r)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type readCloserBody struct {
|
||||||
|
br *bufio.Reader // used until empty
|
||||||
|
io.ReadCloser
|
||||||
|
}
|
||||||
|
|
||||||
|
func newReadCloserBody(br *bufio.Reader, rc io.ReadCloser) io.ReadCloser {
|
||||||
|
body := &readCloserBody{ReadCloser: rc}
|
||||||
|
if br.Buffered() != 0 {
|
||||||
|
body.br = br
|
||||||
|
}
|
||||||
|
return body
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *readCloserBody) Read(p []byte) (n int, err error) {
|
||||||
|
if b.br != nil {
|
||||||
|
if n := b.br.Buffered(); len(p) > n {
|
||||||
|
p = p[:n]
|
||||||
|
}
|
||||||
|
n, err = b.br.Read(p)
|
||||||
|
if b.br.Buffered() == 0 {
|
||||||
|
b.br = nil
|
||||||
|
}
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
return b.ReadCloser.Read(p)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user