diff options
author | tjpcc <tjp@ctrl-c.club> | 2023-01-28 14:52:35 -0700 |
---|---|---|
committer | tjpcc <tjp@ctrl-c.club> | 2023-01-28 15:01:41 -0700 |
commit | 66a1b1f39a1e1d5499b548b36d18c8daa872d7da (patch) | |
tree | 96471dbd5486ede1a908790ac23e0c55b226dfad /gopher/client.go | |
parent | a27b879accb191b6a6c6e76a6251ed751967f73a (diff) |
gopher support.
Some of the contrib packages were originally built gemini-specific and
had to be refactored into generic core functionality and thin
protocol-specific wrappers for each of gemini and gopher.
Diffstat (limited to 'gopher/client.go')
-rw-r--r-- | gopher/client.go | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/gopher/client.go b/gopher/client.go new file mode 100644 index 0000000..8f5ca81 --- /dev/null +++ b/gopher/client.go @@ -0,0 +1,55 @@ +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 +} |