60 lines
1.3 KiB
Go
60 lines
1.3 KiB
Go
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)
|
|
}
|