56 lines
1.2 KiB
Go
56 lines
1.2 KiB
Go
package gopher
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"io"
|
|
"net"
|
|
|
|
"tildegit.org/tjp/gus"
|
|
)
|
|
|
|
// Client is used for sending gopher requests and producing the responses.
|
|
//
|
|
// It carries no state and is reusable simultaneously by multiple goroutines.
|
|
//
|
|
// The zero value is immediately usable.
|
|
type Client struct{}
|
|
|
|
// RoundTrip sends a single gopher request and returns its response.
|
|
func (c Client) RoundTrip(request *gus.Request) (*gus.Response, error) {
|
|
if request.Scheme != "gopher" && request.Scheme != "" {
|
|
return nil, errors.New("non-gopher protocols not supported")
|
|
}
|
|
|
|
host := request.Host
|
|
if _, port, _ := net.SplitHostPort(host); port == "" {
|
|
host = net.JoinHostPort(host, "70")
|
|
}
|
|
|
|
conn, err := net.Dial("tcp", host)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer conn.Close()
|
|
|
|
request.RemoteAddr = conn.RemoteAddr()
|
|
request.TLSState = nil
|
|
|
|
requestBody := request.Path
|
|
if request.RawQuery != "" {
|
|
requestBody += "\t" + request.UnescapedQuery()
|
|
}
|
|
requestBody += "\r\n"
|
|
|
|
if _, err := conn.Write([]byte(requestBody)); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
response, err := io.ReadAll(conn)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &gus.Response{Body: bytes.NewBuffer(response)}, nil
|
|
}
|