diff options
-rw-r--r-- | finger/client.go | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/finger/client.go b/finger/client.go new file mode 100644 index 0000000..8ebf3ca --- /dev/null +++ b/finger/client.go @@ -0,0 +1,59 @@ +package finger + +import ( + "bytes" + "errors" + "io" + "net" + "strings" + + sr "tildegit.org/tjp/sliderule" +) + +// Client is used for sending finger requests and reading 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 finger request and returns its response. +func (c Client) RoundTrip(request *sr.Request) (*sr.Response, error) { + if request.Scheme != "finger" && request.Scheme != "" { + return nil, errors.New("non-finger protocols not supported") + } + + host := request.Host + if _, port, _ := net.SplitHostPort(host); port == "" { + host = net.JoinHostPort(host, "79") + } + + conn, err := net.Dial("tcp", host) + if err != nil { + return nil, err + } + defer conn.Close() + + request.RemoteAddr = conn.RemoteAddr() + request.TLSState = nil + + if _, err := conn.Write([]byte(strings.TrimPrefix(request.Path, "/") + "\r\n")); err != nil { + return nil, err + } + + response, err := io.ReadAll(conn) + if err != nil { + return nil, err + } + + return &sr.Response{Body: bytes.NewBuffer(response)}, nil +} + +// Fetch resolves a finger query. +func (c Client) Fetch(query string) (*sr.Response, error) { + req, err := ParseRequest(bytes.NewBufferString(query + "\r\n")) + if err != nil { + return nil, err + } + return c.RoundTrip(req) +} |