summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--finger/client.go8
-rw-r--r--finger/request.go6
-rw-r--r--finger/response.go10
-rw-r--r--finger/serve.go8
-rw-r--r--finger/system.go6
-rw-r--r--gemini/client.go8
-rw-r--r--gemini/request.go8
-rw-r--r--gemini/response.go100
-rw-r--r--gemini/response_test.go18
-rw-r--r--gemini/roundtrip_test.go8
-rw-r--r--gemini/serve.go16
-rw-r--r--gopher/client.go10
-rw-r--r--gopher/request.go6
-rw-r--r--gopher/response.go70
-rw-r--r--gopher/serve.go10
-rw-r--r--handler.go28
-rw-r--r--internal/types/handler.go28
-rw-r--r--internal/types/request.go49
-rw-r--r--internal/types/response.go35
-rw-r--r--internal/types/server.go42
-rw-r--r--logging/middleware.go16
-rw-r--r--request.go48
-rw-r--r--response.go36
-rw-r--r--server.go41
-rw-r--r--spartan/client.go8
-rw-r--r--spartan/request.go12
-rw-r--r--spartan/response.go36
-rw-r--r--spartan/serve.go10
28 files changed, 356 insertions, 325 deletions
diff --git a/finger/client.go b/finger/client.go
index 8ebf3ca..75a382f 100644
--- a/finger/client.go
+++ b/finger/client.go
@@ -7,7 +7,7 @@ import (
"net"
"strings"
- sr "tildegit.org/tjp/sliderule"
+ "tildegit.org/tjp/sliderule/internal/types"
)
// Client is used for sending finger requests and reading responses.
@@ -18,7 +18,7 @@ import (
type Client struct{}
// RoundTrip sends a single finger request and returns its response.
-func (c Client) RoundTrip(request *sr.Request) (*sr.Response, error) {
+func (c Client) RoundTrip(request *types.Request) (*types.Response, error) {
if request.Scheme != "finger" && request.Scheme != "" {
return nil, errors.New("non-finger protocols not supported")
}
@@ -46,11 +46,11 @@ func (c Client) RoundTrip(request *sr.Request) (*sr.Response, error) {
return nil, err
}
- return &sr.Response{Body: bytes.NewBuffer(response)}, nil
+ return &types.Response{Body: bytes.NewBuffer(response)}, nil
}
// Fetch resolves a finger query.
-func (c Client) Fetch(query string) (*sr.Response, error) {
+func (c Client) Fetch(query string) (*types.Response, error) {
req, err := ParseRequest(bytes.NewBufferString(query + "\r\n"))
if err != nil {
return nil, err
diff --git a/finger/request.go b/finger/request.go
index a18ff7e..b0ef102 100644
--- a/finger/request.go
+++ b/finger/request.go
@@ -7,7 +7,7 @@ import (
"net/url"
"strings"
- sr "tildegit.org/tjp/sliderule"
+ "tildegit.org/tjp/sliderule/internal/types"
)
// ForwardingDenied is returned in response to requests for forwarding service.
@@ -47,7 +47,7 @@ var InvalidFingerQuery = errors.New("Invalid finger query.")
// In accordance with the recommendation of RFC 1288 section 3.2.1
// (https://datatracker.ietf.org/doc/html/rfc1288#section-3.2.1), any queries which
// include a jump-host (user@host1@host2) are rejected with the ForwardingDenied error.
-func ParseRequest(rdr io.Reader) (*sr.Request, error) {
+func ParseRequest(rdr io.Reader) (*types.Request, error) {
line, err := bufio.NewReader(rdr).ReadString('\n')
if err != nil {
return nil, err
@@ -66,7 +66,7 @@ func ParseRequest(rdr io.Reader) (*sr.Request, error) {
return nil, ForwardingDenied
}
- return &sr.Request{URL: &url.URL{
+ return &types.Request{URL: &url.URL{
Scheme: "finger",
Host: hostname,
Path: "/" + username,
diff --git a/finger/response.go b/finger/response.go
index 8612f45..db2dfb0 100644
--- a/finger/response.go
+++ b/finger/response.go
@@ -5,18 +5,18 @@ import (
"io"
"strings"
- sr "tildegit.org/tjp/sliderule"
+ "tildegit.org/tjp/sliderule/internal/types"
)
// Error produces a finger Response containing the error message and Status 1.
-func Error(msg string) *sr.Response {
+func Error(msg string) *types.Response {
if !strings.HasSuffix(msg, "\r\n") {
msg += "\r\n"
}
- return &sr.Response{Body: bytes.NewBufferString(msg), Status: 1}
+ return &types.Response{Body: bytes.NewBufferString(msg), Status: 1}
}
// Success produces a finger response with a Status of 0.
-func Success(body io.Reader) *sr.Response {
- return &sr.Response{Body: body}
+func Success(body io.Reader) *types.Response {
+ return &types.Response{Body: body}
}
diff --git a/finger/serve.go b/finger/serve.go
index 6456763..ff842e1 100644
--- a/finger/serve.go
+++ b/finger/serve.go
@@ -6,14 +6,14 @@ import (
"io"
"net"
- sr "tildegit.org/tjp/sliderule"
+ "tildegit.org/tjp/sliderule/internal/types"
"tildegit.org/tjp/sliderule/internal"
"tildegit.org/tjp/sliderule/logging"
)
type fingerServer struct {
internal.Server
- handler sr.Handler
+ handler types.Handler
}
func (fs fingerServer) Protocol() string { return "FINGER" }
@@ -24,9 +24,9 @@ func NewServer(
hostname string,
network string,
address string,
- handler sr.Handler,
+ handler types.Handler,
errLog logging.Logger,
-) (sr.Server, error) {
+) (types.Server, error) {
fs := &fingerServer{handler: handler}
hostname = internal.JoinDefaultPort(hostname, "79")
diff --git a/finger/system.go b/finger/system.go
index aa2cc84..30ee1e8 100644
--- a/finger/system.go
+++ b/finger/system.go
@@ -6,15 +6,15 @@ import (
"errors"
"os/exec"
- sr "tildegit.org/tjp/sliderule"
+ "tildegit.org/tjp/sliderule/internal/types"
)
// ListingDenied is returned to reject online user listing requests.
var ListingDenied = errors.New("Finger online user list denied.")
// SystemFinger handles finger requests by invoking the finger(1) command-line utility.
-func SystemFinger(allowListings bool) sr.Handler {
- return sr.HandlerFunc(func(ctx context.Context, request *sr.Request) *sr.Response {
+func SystemFinger(allowListings bool) types.Handler {
+ return types.HandlerFunc(func(ctx context.Context, request *types.Request) *types.Response {
fingerPath, err := exec.LookPath("finger")
if err != nil {
_ = request.Server.LogError(
diff --git a/gemini/client.go b/gemini/client.go
index e81e64a..34d5839 100644
--- a/gemini/client.go
+++ b/gemini/client.go
@@ -8,7 +8,7 @@ import (
"net"
neturl "net/url"
- sr "tildegit.org/tjp/sliderule"
+ "tildegit.org/tjp/sliderule/internal/types"
)
// Client is used for sending gemini requests and parsing gemini responses.
@@ -43,7 +43,7 @@ var ExceededMaxRedirects = errors.New("gemini.Client: exceeded MaxRedirects")
//
// This method will not automatically follow redirects or cache permanent failures or
// redirects.
-func (client Client) RoundTrip(request *sr.Request) (*sr.Response, error) {
+func (client Client) RoundTrip(request *types.Request) (*types.Response, error) {
if request.Scheme != "gemini" && request.Scheme != "" {
return nil, errors.New("non-gemini protocols not supported")
}
@@ -91,14 +91,14 @@ func (client Client) RoundTrip(request *sr.Request) (*sr.Response, error) {
// Fetch parses a URL string and fetches the gemini resource.
//
// It will resolve any redirects along the way, up to client.MaxRedirects.
-func (c Client) Fetch(url string) (*sr.Response, error) {
+func (c Client) Fetch(url string) (*types.Response, error) {
u, err := neturl.Parse(url)
if err != nil {
return nil, err
}
for i := 0; i <= c.MaxRedirects; i += 1 {
- response, err := c.RoundTrip(&sr.Request{URL: u})
+ response, err := c.RoundTrip(&types.Request{URL: u})
if err != nil {
return nil, err
}
diff --git a/gemini/request.go b/gemini/request.go
index 51aaae5..4eb7cf0 100644
--- a/gemini/request.go
+++ b/gemini/request.go
@@ -6,7 +6,7 @@ import (
"io"
"net/url"
- sr "tildegit.org/tjp/sliderule"
+ "tildegit.org/tjp/sliderule/internal/types"
)
// InvalidRequestLineEnding indicates that a gemini request didn't end with "\r\n".
@@ -15,7 +15,7 @@ var InvalidRequestLineEnding = errors.New("invalid request line ending")
// ParseRequest parses a single gemini request from a reader.
//
// If the reader argument is a *bufio.Reader, it will only read a single line from it.
-func ParseRequest(rdr io.Reader) (*sr.Request, error) {
+func ParseRequest(rdr io.Reader) (*types.Request, error) {
bufrdr, ok := rdr.(*bufio.Reader)
if !ok {
bufrdr = bufio.NewReader(rdr)
@@ -39,14 +39,14 @@ func ParseRequest(rdr io.Reader) (*sr.Request, error) {
u.Scheme = "gemini"
}
- return &sr.Request{URL: u}, nil
+ return &types.Request{URL: u}, nil
}
// GetTitanRequestBody fetches the request body from a titan request.
//
// It returns nil if the argument is not a titan request or it otherwise
// does not have a request body set.
-func GetTitanRequestBody(request *sr.Request) io.Reader {
+func GetTitanRequestBody(request *types.Request) io.Reader {
if request.Scheme != "titan" {
return nil
}
diff --git a/gemini/response.go b/gemini/response.go
index 9d4ede1..13f493a 100644
--- a/gemini/response.go
+++ b/gemini/response.go
@@ -8,7 +8,7 @@ import (
"strconv"
"sync"
- sr "tildegit.org/tjp/sliderule"
+ "tildegit.org/tjp/sliderule/internal/types"
)
// ResponseCategory represents the various types of gemini responses.
@@ -43,32 +43,32 @@ const (
ResponseCategoryCertificateRequired
)
-func ResponseCategoryForStatus(status sr.Status) ResponseCategory {
+func ResponseCategoryForStatus(status types.Status) ResponseCategory {
return ResponseCategory(status / 10)
}
const (
// StatusInput indicates a required query parameter at the requested URL.
- StatusInput sr.Status = sr.Status(ResponseCategoryInput) + iota
+ StatusInput types.Status = types.Status(ResponseCategoryInput) + iota
// StatusSensitiveInput indicates a sensitive query parameter is required.
StatusSensitiveInput
)
const (
// StatusSuccess is a successful response.
- StatusSuccess = sr.Status(ResponseCategorySuccess) + iota
+ StatusSuccess = types.Status(ResponseCategorySuccess) + iota
)
const (
// StatusTemporaryRedirect indicates a temporary redirect to another URL.
- StatusTemporaryRedirect = sr.Status(ResponseCategoryRedirect) + iota
+ StatusTemporaryRedirect = types.Status(ResponseCategoryRedirect) + iota
// StatusPermanentRedirect indicates that the resource should always be requested at the new URL.
StatusPermanentRedirect
)
const (
// StatusTemporaryFailure indicates that the request failed and there is no response body.
- StatusTemporaryFailure = sr.Status(ResponseCategoryTemporaryFailure) + iota
+ StatusTemporaryFailure = types.Status(ResponseCategoryTemporaryFailure) + iota
// StatusServerUnavailable occurs when the server is unavailable due to overload or maintenance.
StatusServerUnavailable
// StatusCGIError is the result of a failure of a CGI script.
@@ -84,7 +84,7 @@ const (
const (
// StatusPermanentFailure is a server failure which should be expected to continue indefinitely.
- StatusPermanentFailure = sr.Status(ResponseCategoryPermanentFailure) + iota
+ StatusPermanentFailure = types.Status(ResponseCategoryPermanentFailure) + iota
// StatusNotFound means the resource doesn't exist but it may in the future.
StatusNotFound
// StatusGone occurs when a resource will not be available any longer.
@@ -92,12 +92,12 @@ const (
// StatusProxyRequestRefused means the server is unwilling to act as a proxy for the resource.
StatusProxyRequestRefused
// StatusBadRequest indicates that the request was malformed somehow.
- StatusBadRequest = sr.Status(ResponseCategoryPermanentFailure) + 9
+ StatusBadRequest = types.Status(ResponseCategoryPermanentFailure) + 9
)
const (
// StatusClientCertificateRequired is returned when a certificate was required but not provided.
- StatusClientCertificateRequired = sr.Status(ResponseCategoryCertificateRequired) + iota
+ StatusClientCertificateRequired = types.Status(ResponseCategoryCertificateRequired) + iota
// StatusCertificateNotAuthorized means the certificate doesn't grant access to the requested resource.
StatusCertificateNotAuthorized
// StatusCertificateNotValid means the provided client certificate is invalid.
@@ -105,24 +105,24 @@ const (
)
// Input builds an input-prompting response.
-func Input(prompt string) *sr.Response {
- return &sr.Response{
+func Input(prompt string) *types.Response {
+ return &types.Response{
Status: StatusInput,
Meta: prompt,
}
}
// SensitiveInput builds a password-prompting response.
-func SensitiveInput(prompt string) *sr.Response {
- return &sr.Response{
+func SensitiveInput(prompt string) *types.Response {
+ return &types.Response{
Status: StatusSensitiveInput,
Meta: prompt,
}
}
// Success builds a success response with resource body.
-func Success(mediatype string, body io.Reader) *sr.Response {
- return &sr.Response{
+func Success(mediatype string, body io.Reader) *types.Response {
+ return &types.Response{
Status: StatusSuccess,
Meta: mediatype,
Body: body,
@@ -130,120 +130,120 @@ func Success(mediatype string, body io.Reader) *sr.Response {
}
// Redirect builds a redirect response.
-func Redirect(url string) *sr.Response {
- return &sr.Response{
+func Redirect(url string) *types.Response {
+ return &types.Response{
Status: StatusTemporaryRedirect,
Meta: url,
}
}
// PermanentRedirect builds a response with a permanent redirect.
-func PermanentRedirect(url string) *sr.Response {
- return &sr.Response{
+func PermanentRedirect(url string) *types.Response {
+ return &types.Response{
Status: StatusPermanentRedirect,
Meta: url,
}
}
// Failure builds a temporary failure response from an error.
-func Failure(err error) *sr.Response {
- return &sr.Response{
+func Failure(err error) *types.Response {
+ return &types.Response{
Status: StatusTemporaryFailure,
Meta: err.Error(),
}
}
// Unavailable build a "server unavailable" response.
-func Unavailable(msg string) *sr.Response {
- return &sr.Response{
+func Unavailable(msg string) *types.Response {
+ return &types.Response{
Status: StatusServerUnavailable,
Meta: msg,
}
}
// CGIError builds a "cgi error" response.
-func CGIError(err string) *sr.Response {
- return &sr.Response{
+func CGIError(err string) *types.Response {
+ return &types.Response{
Status: StatusCGIError,
Meta: err,
}
}
// ProxyError builds a proxy error response.
-func ProxyError(msg string) *sr.Response {
- return &sr.Response{
+func ProxyError(msg string) *types.Response {
+ return &types.Response{
Status: StatusProxyError,
Meta: msg,
}
}
// SlowDown builds a "slow down" response with the number of seconds until the resource is available.
-func SlowDown(seconds int) *sr.Response {
- return &sr.Response{
+func SlowDown(seconds int) *types.Response {
+ return &types.Response{
Status: StatusSlowDown,
Meta: strconv.Itoa(seconds),
}
}
// PermanentFailure builds a "permanent failure" from an error.
-func PermanentFailure(err error) *sr.Response {
- return &sr.Response{
+func PermanentFailure(err error) *types.Response {
+ return &types.Response{
Status: StatusPermanentFailure,
Meta: err.Error(),
}
}
// NotFound builds a "resource not found" response.
-func NotFound(msg string) *sr.Response {
- return &sr.Response{
+func NotFound(msg string) *types.Response {
+ return &types.Response{
Status: StatusNotFound,
Meta: msg,
}
}
// Gone builds a "resource gone" response.
-func Gone(msg string) *sr.Response {
- return &sr.Response{
+func Gone(msg string) *types.Response {
+ return &types.Response{
Status: StatusGone,
Meta: msg,
}
}
// RefuseProxy builds a "proxy request refused" response.
-func RefuseProxy(msg string) *sr.Response {
- return &sr.Response{
+func RefuseProxy(msg string) *types.Response {
+ return &types.Response{
Status: StatusProxyRequestRefused,
Meta: msg,
}
}
// BadRequest builds a "bad request" response.
-func BadRequest(msg string) *sr.Response {
- return &sr.Response{
+func BadRequest(msg string) *types.Response {
+ return &types.Response{
Status: StatusBadRequest,
Meta: msg,
}
}
// RequireCert builds a "client certificate required" response.
-func RequireCert(msg string) *sr.Response {
- return &sr.Response{
+func RequireCert(msg string) *types.Response {
+ return &types.Response{
Status: StatusClientCertificateRequired,
Meta: msg,
}
}
// CertAuthFailure builds a "certificate not authorized" response.
-func CertAuthFailure(msg string) *sr.Response {
- return &sr.Response{
+func CertAuthFailure(msg string) *types.Response {
+ return &types.Response{
Status: StatusCertificateNotAuthorized,
Meta: msg,
}
}
// CertInvalid builds a "client certificate not valid" response.
-func CertInvalid(msg string) *sr.Response {
- return &sr.Response{
+func CertInvalid(msg string) *types.Response {
+ return &types.Response{
Status: StatusCertificateNotValid,
Meta: msg,
}
@@ -258,7 +258,7 @@ var InvalidResponseHeaderLine = errors.New("Invalid response header line.")
// ParseResponse parses a complete gemini response from a reader.
//
// The reader must contain only one gemini response.
-func ParseResponse(rdr io.Reader) (*sr.Response, error) {
+func ParseResponse(rdr io.Reader) (*types.Response, error) {
bufrdr := bufio.NewReader(rdr)
hdrLine, err := bufrdr.ReadBytes('\n')
@@ -278,14 +278,14 @@ func ParseResponse(rdr io.Reader) (*sr.Response, error) {
return nil, InvalidResponseHeaderLine
}
- return &sr.Response{
- Status: sr.Status(status),
+ return &types.Response{
+ Status: types.Status(status),
Meta: string(hdrLine[3:]),
Body: bufrdr,
}, nil
}
-func NewResponseReader(response *sr.Response) sr.ResponseReader {
+func NewResponseReader(response *types.Response) types.ResponseReader {
return &responseReader{
Response: response,
once: &sync.Once{},
@@ -293,7 +293,7 @@ func NewResponseReader(response *sr.Response) sr.ResponseReader {
}
type responseReader struct {
- *sr.Response
+ *types.Response
reader io.Reader
once *sync.Once
}
diff --git a/gemini/response_test.go b/gemini/response_test.go
index 00166dd..784e00a 100644
--- a/gemini/response_test.go
+++ b/gemini/response_test.go
@@ -6,15 +6,15 @@ import (
"io"
"testing"
- sr "tildegit.org/tjp/sliderule"
+ "tildegit.org/tjp/sliderule/internal/types"
"tildegit.org/tjp/sliderule/gemini"
)
func TestBuildResponses(t *testing.T) {
table := []struct {
name string
- response *sr.Response
- status sr.Status
+ response *types.Response
+ status types.Status
meta string
body string
}{
@@ -154,7 +154,7 @@ func TestBuildResponses(t *testing.T) {
func TestParseResponses(t *testing.T) {
table := []struct {
input string
- status sr.Status
+ status types.Status
meta string
body string
err error
@@ -233,7 +233,7 @@ func TestParseResponses(t *testing.T) {
func TestResponseClose(t *testing.T) {
body := &rdCloser{Buffer: bytes.NewBufferString("the body here")}
- resp := &sr.Response{
+ resp := &types.Response{
Status: gemini.StatusSuccess,
Meta: "text/gemini",
Body: body,
@@ -247,7 +247,7 @@ func TestResponseClose(t *testing.T) {
t.Error("response body was not closed by response.Close()")
}
- resp = &sr.Response{
+ resp = &types.Response{
Status: gemini.StatusInput,
Meta: "give me more",
}
@@ -270,8 +270,8 @@ func (rc *rdCloser) Close() error {
func TestResponseWriteTo(t *testing.T) {
// invariant under test: WriteTo() sends the same bytes as Read()
- clone := func(resp *sr.Response) *sr.Response {
- other := &sr.Response{
+ clone := func(resp *types.Response) *types.Response {
+ other := &types.Response{
Status: resp.Status,
Meta: resp.Meta,
}
@@ -297,7 +297,7 @@ func TestResponseWriteTo(t *testing.T) {
table := []struct {
name string
- response *sr.Response
+ response *types.Response
}{
{
name: "simple success",
diff --git a/gemini/roundtrip_test.go b/gemini/roundtrip_test.go
index 0aa5648..50c1962 100644
--- a/gemini/roundtrip_test.go
+++ b/gemini/roundtrip_test.go
@@ -12,7 +12,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
- sr "tildegit.org/tjp/sliderule"
+ "tildegit.org/tjp/sliderule/internal/types"
"tildegit.org/tjp/sliderule/gemini"
)
@@ -20,7 +20,7 @@ func TestRoundTrip(t *testing.T) {
tlsConf, err := gemini.FileTLS("./testdata/server.crt", "./testdata/server.key")
require.Nil(t, err)
- handler := sr.HandlerFunc(func(ctx context.Context, req *sr.Request) *sr.Response {
+ handler := types.HandlerFunc(func(ctx context.Context, req *types.Request) *types.Response {
return gemini.Success("text/gemini", bytes.NewBufferString("you've found my page"))
})
@@ -36,7 +36,7 @@ func TestRoundTrip(t *testing.T) {
require.Nil(t, err)
cli := gemini.NewClient(testClientTLS())
- response, err := cli.RoundTrip(&sr.Request{URL: u})
+ response, err := cli.RoundTrip(&types.Request{URL: u})
require.Nil(t, err)
assert.Equal(t, gemini.StatusSuccess, response.Status)
@@ -54,7 +54,7 @@ func TestTitanRequest(t *testing.T) {
require.Nil(t, err)
invoked := false
- handler := sr.HandlerFunc(func(ctx context.Context, request *sr.Request) *sr.Response {
+ handler := types.HandlerFunc(func(ctx context.Context, request *types.Request) *types.Response {
invoked = true
body := gemini.GetTitanRequestBody(request)
diff --git a/gemini/serve.go b/gemini/serve.go
index 9173212..6fee458 100644
--- a/gemini/serve.go
+++ b/gemini/serve.go
@@ -11,7 +11,7 @@ import (
"strconv"
"strings"
- sr "tildegit.org/tjp/sliderule"
+ "tildegit.org/tjp/sliderule/internal/types"
"tildegit.org/tjp/sliderule/internal"
"tildegit.org/tjp/sliderule/logging"
)
@@ -19,7 +19,7 @@ import (
type server struct {
internal.Server
- handler sr.Handler
+ handler types.Handler
}
func (s server) Protocol() string { return "GEMINI" }
@@ -30,10 +30,10 @@ func NewServer(
hostname string,
network string,
address string,
- handler sr.Handler,
+ handler types.Handler,
errorLog logging.Logger,
tlsConfig *tls.Config,
-) (sr.Server, error) {
+) (types.Server, error) {
s := &server{handler: handler}
hostname = internal.JoinDefaultPort(hostname, "1965")
@@ -53,7 +53,7 @@ func NewServer(
func (s *server) handleConn(conn net.Conn) {
buf := bufio.NewReader(conn)
- var response *sr.Response
+ var response *types.Response
request, err := ParseRequest(buf)
if err != nil {
response = BadRequest(err.Error())
@@ -112,9 +112,9 @@ func sizeParam(path string) (int, error) {
// Optionally, it will also allow through titan:// requests.
//
// Filtered requests will be turned away with a 53 response "proxy request refused".
-func GeminiOnly(allowTitan bool) sr.Middleware {
- return func(inner sr.Handler) sr.Handler {
- return sr.HandlerFunc(func(ctx context.Context, request *sr.Request) *sr.Response {
+func GeminiOnly(allowTitan bool) types.Middleware {
+ return func(inner types.Handler) types.Handler {
+ return types.HandlerFunc(func(ctx context.Context, request *types.Request) *types.Response {
if request.Scheme == "gemini" || (allowTitan && request.Scheme == "titan") {
return inner.Handle(ctx, request)
}
diff --git a/gopher/client.go b/gopher/client.go
index 163d0cd..5ef54ff 100644
--- a/gopher/client.go
+++ b/gopher/client.go
@@ -7,7 +7,7 @@ import (
"net"
neturl "net/url"
- sr "tildegit.org/tjp/sliderule"
+ "tildegit.org/tjp/sliderule/internal/types"
)
// Client is used for sending gopher requests and producing the responses.
@@ -18,7 +18,7 @@ import (
type Client struct{}
// RoundTrip sends a single gopher request and returns its response.
-func (c Client) RoundTrip(request *sr.Request) (*sr.Response, error) {
+func (c Client) RoundTrip(request *types.Request) (*types.Response, error) {
if request.Scheme != "gopher" && request.Scheme != "" {
return nil, errors.New("non-gopher protocols not supported")
}
@@ -52,14 +52,14 @@ func (c Client) RoundTrip(request *sr.Request) (*sr.Response, error) {
return nil, err
}
- return &sr.Response{Body: bytes.NewBuffer(response)}, nil
+ return &types.Response{Body: bytes.NewBuffer(response)}, nil
}
// Fetch parses a URL string and fetches the gopher resource.
-func (c Client) Fetch(url string) (*sr.Response, error) {
+func (c Client) Fetch(url string) (*types.Response, error) {
u, err := neturl.Parse(url)
if err != nil {
return nil, err
}
- return c.RoundTrip(&sr.Request{URL: u})
+ return c.RoundTrip(&types.Request{URL: u})
}
diff --git a/gopher/request.go b/gopher/request.go
index 4aac218..eef8262 100644
--- a/gopher/request.go
+++ b/gopher/request.go
@@ -8,11 +8,11 @@ import (
"path"
"strings"
- sr "tildegit.org/tjp/sliderule"
+ "tildegit.org/tjp/sliderule/internal/types"
)
// ParseRequest parses a gopher protocol request into a sliderule.Request object.
-func ParseRequest(rdr io.Reader) (*sr.Request, error) {
+func ParseRequest(rdr io.Reader) (*types.Request, error) {
selector, search, err := readFullRequest(rdr)
if err != nil {
return nil, err
@@ -22,7 +22,7 @@ func ParseRequest(rdr io.Reader) (*sr.Request, error) {
selector = "/" + selector
}
- return &sr.Request{
+ return &types.Request{
URL: &url.URL{
Scheme: "gopher",
Path: path.Clean(selector),
diff --git a/gopher/response.go b/gopher/response.go
index 566623f..527e742 100644
--- a/gopher/response.go
+++ b/gopher/response.go
@@ -6,49 +6,49 @@ import (
"io"
"sync"
- sr "tildegit.org/tjp/sliderule"
+ "tildegit.org/tjp/sliderule/internal/types"
)
// The Canonical gopher item types.
const (
- TextFileType sr.Status = '0'
- MenuType sr.Status = '1'
- CSOPhoneBookType sr.Status = '2'
- ErrorType sr.Status = '3'
- MacBinHexType sr.Status = '4'
- DosBinType sr.Status = '5'
- UuencodedType sr.Status = '6'
- SearchType sr.Status = '7'
- TelnetSessionType sr.Status = '8'
- BinaryFileType sr.Status = '9'
- MirrorServerType sr.Status = '+'
- GifFileType sr.Status = 'g'
- ImageFileType sr.Status = 'I'
- Telnet3270Type sr.Status = 'T'
+ TextFileType types.Status = '0'
+ MenuType types.Status = '1'
+ CSOPhoneBookType types.Status = '2'
+ ErrorType types.Status = '3'
+ MacBinHexType types.Status = '4'
+ DosBinType types.Status = '5'
+ UuencodedType types.Status = '6'
+ SearchType types.Status = '7'
+ TelnetSessionType types.Status = '8'
+ BinaryFileType types.Status = '9'
+ MirrorServerType types.Status = '+'
+ GifFileType types.Status = 'g'
+ ImageFileType types.Status = 'I'
+ Telnet3270Type types.Status = 'T'
)
// The gopher+ types.
const (
- BitmapType sr.Status = ':'
- MovieFileType sr.Status = ';'
- SoundFileType sr.Status = '<'
+ BitmapType types.Status = ':'
+ MovieFileType types.Status = ';'
+ SoundFileType types.Status = '<'
)
// The various non-canonical gopher types.
const (
- DocumentType sr.Status = 'd'
- HTMLType sr.Status = 'h'
- InfoMessageType sr.Status = 'i'
- PngImageFileType sr.Status = 'p'
- RtfDocumentType sr.Status = 'r'
- WavSoundFileType sr.Status = 's'
- PdfDocumentType sr.Status = 'P'
- XmlDocumentType sr.Status = 'X'
+ DocumentType types.Status = 'd'
+ HTMLType types.Status = 'h'
+ InfoMessageType types.Status = 'i'
+ PngImageFileType types.Status = 'p'
+ RtfDocumentType types.Status = 'r'
+ WavSoundFileType types.Status = 's'
+ PdfDocumentType types.Status = 'P'
+ XmlDocumentType types.Status = 'X'
)
// MapItem is a single item in a gophermap.
type MapItem struct {
- Type sr.Status
+ Type types.Status
Display string
Selector string
Hostname string
@@ -70,8 +70,8 @@ func (mi MapItem) String() string {
// Response builds a response which contains just this single MapItem.
//
// Meta in the response will be a pointer to the MapItem.
-func (mi *MapItem) Response() *sr.Response {
- return &sr.Response{
+func (mi *MapItem) Response() *types.Response {
+ return &types.Response{
Status: mi.Type,
Meta: &mi,
Body: bytes.NewBufferString(mi.String() + ".\r\n"),
@@ -89,8 +89,8 @@ func (md MapDocument) String() string {
// Response builds a gopher response containing the gophermap.
//
// Meta will be the MapDocument itself.
-func (md MapDocument) Response() *sr.Response {
- return &sr.Response{
+func (md MapDocument) Response() *types.Response {
+ return &types.Response{
Status: DocumentType,
Meta: md,
Body: md.serialize(),
@@ -119,12 +119,12 @@ func Error(err error) *MapItem {
// File builds a minimal response delivering a file's contents.
//
// Meta is nil and Status is 0 in this response.
-func File(status sr.Status, contents io.Reader) *sr.Response {
- return &sr.Response{Status: status, Body: contents}
+func File(status types.Status, contents io.Reader) *types.Response {
+ return &types.Response{Status: status, Body: contents}
}
// NewResponseReader produces a reader which supports reading gopher protocol responses.
-func NewResponseReader(response *sr.Response) sr.ResponseReader {
+func NewResponseReader(response *types.Response) types.ResponseReader {
return &responseReader{
Response: response,
once: &sync.Once{},
@@ -132,7 +132,7 @@ func NewResponseReader(response *sr.Response) sr.ResponseReader {
}
type responseReader struct {
- *sr.Response
+ *types.Response
reader io.Reader
once *sync.Once
}
diff --git a/gopher/serve.go b/gopher/serve.go
index 7b32f2f..56b38f6 100644
--- a/gopher/serve.go
+++ b/gopher/serve.go
@@ -7,14 +7,14 @@ import (
"io"
"net"
- sr "tildegit.org/tjp/sliderule"
+ "tildegit.org/tjp/sliderule/internal/types"
"tildegit.org/tjp/sliderule/internal"
"tildegit.org/tjp/sliderule/logging"
)
type gopherServer struct {
internal.Server
- handler sr.Handler
+ handler types.Handler
}
func (gs gopherServer) Protocol() string { return "GOPHER" }
@@ -25,9 +25,9 @@ func NewServer(
hostname string,
network string,
address string,
- handler sr.Handler,
+ handler types.Handler,
errLog logging.Logger,
-) (sr.Server, error) {
+) (types.Server, error) {
gs := &gopherServer{handler: handler}
hostname = internal.JoinDefaultPort(hostname, "70")
@@ -43,7 +43,7 @@ func NewServer(
}
func (gs *gopherServer) handleConn(conn net.Conn) {
- var response *sr.Response
+ var response *types.Response
request, err := ParseRequest(conn)
if err != nil {
response = Error(errors.New("Malformed request.")).Response()
diff --git a/handler.go b/handler.go
index 1c2d6dc..f3c9edd 100644
--- a/handler.go
+++ b/handler.go
@@ -1,33 +1,19 @@
package sliderule
-import "context"
+import (
+ "context"
-// Handler is a type which can turn a request into a response.
-//
-// Handle may return a nil response, in which case the Server is expected
-// to build the protocol-appropriate "Not Found" response.
-type Handler interface {
- Handle(context.Context, *Request) *Response
-}
+ "tildegit.org/tjp/sliderule/internal/types"
+)
-type handlerFunc func(context.Context, *Request) *Response
+type Handler = types.Handler
+type Middleware = types.Middleware
// HandlerFunc is a wrapper to allow using a function as a Handler.
func HandlerFunc(f func(context.Context, *Request) *Response) Handler {
- return handlerFunc(f)
-}
-
-// Handle implements Handler.
-func (f handlerFunc) Handle(ctx context.Context, request *Request) *Response {
- return f(ctx, request)
+ return types.HandlerFunc(f)
}
-// Middleware is a handler decorator.
-//
-// It returns a handler which may call the passed-in handler or not, or may
-// transform the request or response in some way.
-type Middleware func(Handler) Handler
-
// FallthroughHandler builds a handler which tries multiple child handlers.
//
// The returned handler will invoke each of the passed-in handlers in order,
diff --git a/internal/types/handler.go b/internal/types/handler.go
new file mode 100644
index 0000000..4805c57
--- /dev/null
+++ b/internal/types/handler.go
@@ -0,0 +1,28 @@
+package types
+
+import "context"
+
+// Handler is a type which can turn a request into a response.
+//
+// Handle may return a nil response, in which case the Server is expected
+// to build the protocol-appropriate "Not Found" response.
+type Handler interface {
+ Handle(context.Context, *Request) *Response
+}
+
+// Middleware is a handler decorator.
+//
+// It returns a handler which may call the passed-in handler or not, or may
+// transform the request or response in some way.
+type Middleware func(Handler) Handler
+
+func HandlerFunc(f func(context.Context, *Request) *Response) Handler {
+ return handlerFunc(f)
+}
+
+// Handle implements Handler.
+func (f handlerFunc) Handle(ctx context.Context, request *Request) *Response {
+ return f(ctx, request)
+}
+
+type handlerFunc func(context.Context, *Request) *Response
diff --git a/internal/types/request.go b/internal/types/request.go
new file mode 100644
index 0000000..e3d2e6f
--- /dev/null
+++ b/internal/types/request.go
@@ -0,0 +1,49 @@
+package types
+
+import (
+ "crypto/tls"
+ "net"
+ "net/url"
+)
+
+// Request represents a request over any small web protocol.
+//
+// Because protocols have so many differences, this type represents a
+// greatest common denominator of request/response-oriented protocols.
+type Request struct {
+ // URL is the specific URL being fetched by the request.
+ *url.URL
+
+ // Server is the server which received the request.
+ //
+ // This is only populated in servers.
+ // It is unused on the client end.
+ Server Server
+
+ // Meta is a place for opaque data.
+ //
+ // Look for helper methods in protocol packages to use it appropriately
+ // for the protocol.
+ Meta any
+
+ // RemoteAddr is the address of the other side of the connection.
+ //
+ // This will be the server address for clients, or the connecting
+ // client's address in servers.
+ //
+ // Be aware though that proxies (and reverse proxies) can confuse this.
+ RemoteAddr net.Addr
+
+ // TLSState contains information about the TLS encryption over the connection.
+ //
+ // This includes peer certificates and version information.
+ TLSState *tls.ConnectionState
+}
+
+// UnescapedQuery performs %XX unescaping on the URL query segment.
+//
+// Like URL.Query(), it silently drops malformed %-encoded sequences.
+func (req Request) UnescapedQuery() string {
+ unescaped, _ := url.QueryUnescape(req.RawQuery)
+ return unescaped
+}
diff --git a/internal/types/response.go b/internal/types/response.go
new file mode 100644
index 0000000..26dda05
--- /dev/null
+++ b/internal/types/response.go
@@ -0,0 +1,35 @@
+package types
+
+import "io"
+
+// Status is the integer status code of a response.
+type Status int
+
+// Response contains the data in a response over the small web.
+//
+// Because protocols have so many differences, this type represents a
+// greatest common denominator of request/response-oriented protocols.
+type Response struct {
+ // Status is the status code of the response.
+ Status Status
+
+ // Meta contains status-specific additional information.
+ Meta any
+
+ // Body is the response body, if any.
+ Body io.Reader
+}
+
+func (response *Response) Close() error {
+ if cl, ok := response.Body.(io.Closer); ok {
+ return cl.Close()
+ }
+ return nil
+}
+
+// ResponseReader is an object which can serialize a response to a protocol.
+type ResponseReader interface {
+ io.Reader
+ io.WriterTo
+ io.Closer
+}
diff --git a/internal/types/server.go b/internal/types/server.go
new file mode 100644
index 0000000..80d12b5
--- /dev/null
+++ b/internal/types/server.go
@@ -0,0 +1,42 @@
+package types
+
+// Server is a type which can serve a protocol.
+type Server interface {
+ // Serve blocks listening for connections on an interface.
+ //
+ // It will only return after Close() has been called.
+ Serve() error
+
+ // Close initiates a graceful shutdown of the server.
+ //
+ // It blocks until all resources have been cleaned up and all
+ // outstanding requests have been handled and responses sent.
+ Close()
+
+ // Closed indicates whether Close has been called.
+ //
+ // It may be true even if the graceful shutdown procedure
+ // hasn't yet completed.
+ Closed() bool
+
+ // Protocol returns the protocol being served by the server.
+ Protocol() string
+
+ // Network returns the network type on which the server is running.
+ Network() string
+
+ // Address returns the address on which the server is listening.
+ Address() string
+
+ // Hostname returns just the hostname portion of the listen address.
+ Hostname() string
+
+ // Port returns the port on which the server is listening.
+ //
+ // It will return the empty string if the network type does not
+ // have ports (unix sockets, for example).
+ Port() string
+
+ // LogError sends a log message to the server's error log.
+ LogError(keyvals ...any) error
+}
diff --git a/logging/middleware.go b/logging/middleware.go
index 693cb2f..2d0e5b9 100644
--- a/logging/middleware.go
+++ b/logging/middleware.go
@@ -8,12 +8,12 @@ import (
"io"
"time"
- sr "tildegit.org/tjp/sliderule"
+ "tildegit.org/tjp/sliderule/internal/types"
)
-func LogRequests(logger Logger) sr.Middleware {
- return func(inner sr.Handler) sr.Handler {
- return sr.HandlerFunc(func(ctx context.Context, request *sr.Request) *sr.Response {
+func LogRequests(logger Logger) types.Middleware {
+ return func(inner types.Handler) types.Handler {
+ return types.HandlerFunc(func(ctx context.Context, request *types.Request) *types.Response {
start := time.Now()
response := inner.Handle(ctx, request)
if response != nil {
@@ -38,7 +38,7 @@ func LogRequests(logger Logger) sr.Middleware {
}
}
-func clientFingerprint(request *sr.Request) (string, bool) {
+func clientFingerprint(request *types.Request) (string, bool) {
if request.TLSState == nil || len(request.TLSState.PeerCertificates) == 0 {
return "", false
}
@@ -48,8 +48,8 @@ func clientFingerprint(request *sr.Request) (string, bool) {
}
type loggedResponseBody struct {
- request *sr.Request
- response *sr.Response
+ request *types.Request
+ response *types.Response
body io.Reader
start time.Time
@@ -111,7 +111,7 @@ func (lwtr loggedWriteToResponseBody) WriteTo(dst io.Writer) (int64, error) {
return n, err
}
-func loggingBody(logger Logger, request *sr.Request, response *sr.Response, start time.Time) io.Reader {
+func loggingBody(logger Logger, request *types.Request, response *types.Response, start time.Time) io.Reader {
body := &loggedResponseBody{
request: request,
response: response,
diff --git a/request.go b/request.go
index dce8acb..c934b30 100644
--- a/request.go
+++ b/request.go
@@ -1,49 +1,5 @@
package sliderule
-import (
- "crypto/tls"
- "net"
- "net/url"
-)
+import "tildegit.org/tjp/sliderule/internal/types"
-// Request represents a request over any small web protocol.
-//
-// Because protocols have so many differences, this type represents a
-// greatest common denominator of request/response-oriented protocols.
-type Request struct {
- // URL is the specific URL being fetched by the request.
- *url.URL
-
- // Server is the server which received the request.
- //
- // This is only populated in servers.
- // It is unused on the client end.
- Server Server
-
- // Meta is a place for opaque data.
- //
- // Look for helper methods in protocol packages to use it appropriately
- // for the protocol.
- Meta any
-
- // RemoteAddr is the address of the other side of the connection.
- //
- // This will be the server address for clients, or the connecting
- // client's address in servers.
- //
- // Be aware though that proxies (and reverse proxies) can confuse this.
- RemoteAddr net.Addr
-
- // TLSState contains information about the TLS encryption over the connection.
- //
- // This includes peer certificates and version information.
- TLSState *tls.ConnectionState
-}
-
-// UnescapedQuery performs %XX unescaping on the URL query segment.
-//
-// Like URL.Query(), it silently drops malformed %-encoded sequences.
-func (req Request) UnescapedQuery() string {
- unescaped, _ := url.QueryUnescape(req.RawQuery)
- return unescaped
-}
+type Request = types.Request
diff --git a/response.go b/response.go
index 249e08f..bb7c2bb 100644
--- a/response.go
+++ b/response.go
@@ -1,35 +1,7 @@
package sliderule
-import "io"
+import "tildegit.org/tjp/sliderule/internal/types"
-// Status is the integer status code of a response.
-type Status int
-
-// Response contains the data in a response over the small web.
-//
-// Because protocols have so many differences, this type represents a
-// greatest common denominator of request/response-oriented protocols.
-type Response struct {
- // Status is the status code of the response.
- Status Status
-
- // Meta contains status-specific additional information.
- Meta any
-
- // Body is the response body, if any.
- Body io.Reader
-}
-
-func (response *Response) Close() error {
- if cl, ok := response.Body.(io.Closer); ok {
- return cl.Close()
- }
- return nil
-}
-
-// ResponseReader is an object which can serialize a response to a protocol.
-type ResponseReader interface {
- io.Reader
- io.WriterTo
- io.Closer
-}
+type Status = types.Status
+type Response = types.Response
+type ResponseReader = types.ResponseReader
diff --git a/server.go b/server.go
index 1562f56..5bb8c97 100644
--- a/server.go
+++ b/server.go
@@ -1,42 +1,5 @@
package sliderule
-// Server is a type which can serve a protocol.
-type Server interface {
- // Serve blocks listening for connections on an interface.
- //
- // It will only return after Close() has been called.
- Serve() error
+import "tildegit.org/tjp/sliderule/internal/types"
- // Close initiates a graceful shutdown of the server.
- //
- // It blocks until all resources have been cleaned up and all
- // outstanding requests have been handled and responses sent.
- Close()
-
- // Closed indicates whether Close has been called.
- //
- // It may be true even if the graceful shutdown procedure
- // hasn't yet completed.
- Closed() bool
-
- // Protocol returns the protocol being served by the server.
- Protocol() string
-
- // Network returns the network type on which the server is running.
- Network() string
-
- // Address returns the address on which the server is listening.
- Address() string
-
- // Hostname returns just the hostname portion of the listen address.
- Hostname() string
-
- // Port returns the port on which the server is listening.
- //
- // It will return the empty string if the network type does not
- // have ports (unix sockets, for example).
- Port() string
-
- // LogError sends a log message to the server's error log.
- LogError(keyvals ...any) error
-}
+type Server = types.Server
diff --git a/spartan/client.go b/spartan/client.go
index 9547f74..e3025ee 100644
--- a/spartan/client.go
+++ b/spartan/client.go
@@ -8,7 +8,7 @@ import (
neturl "net/url"
"strconv"
- sr "tildegit.org/tjp/sliderule"
+ "tildegit.org/tjp/sliderule/internal/types"
)
// Client is used for sending spartan requests and receiving responses.
@@ -32,7 +32,7 @@ const DefaultMaxRedirects int = 2
var ExceededMaxRedirects = errors.New("spartan.Client: exceeded MaxRedirects")
// RoundTrip sends a single spartan request and returns its response.
-func (c Client) RoundTrip(request *sr.Request) (*sr.Response, error) {
+func (c Client) RoundTrip(request *types.Request) (*types.Response, error) {
if request.Scheme != "spartan" && request.Scheme != "" {
return nil, errors.New("non-spartan protocols not supported")
}
@@ -89,14 +89,14 @@ func (c Client) RoundTrip(request *sr.Request) (*sr.Response, error) {
// Fetch parses a URL string and fetches the spartan resource.
//
// It will resolve any redirects along the way, up to client.MaxRedirects.
-func (c Client) Fetch(url string) (*sr.Response, error) {
+func (c Client) Fetch(url string) (*types.Response, error) {
u, err := neturl.Parse(url)
if err != nil {
return nil, err
}
for i := 0; i <= c.MaxRedirects; i += 1 {
- response, err := c.RoundTrip(&sr.Request{URL: u})
+ response, err := c.RoundTrip(&types.Request{URL: u})
if err != nil {
return nil, err
}
diff --git a/spartan/request.go b/spartan/request.go
index c056af0..c88a20b 100644
--- a/spartan/request.go
+++ b/spartan/request.go
@@ -9,7 +9,7 @@ import (
"strconv"
"strings"
- sr "tildegit.org/tjp/sliderule"
+ "tildegit.org/tjp/sliderule/internal/types"
)
var (
@@ -23,7 +23,7 @@ var (
// ParseRequest parses a single spartan request and the indicated content-length from a reader.
//
// If ther reader artument is a *bufio.Reader, it will only read a single line from it.
-func ParseRequest(rdr io.Reader) (*sr.Request, int, error) {
+func ParseRequest(rdr io.Reader) (*types.Request, int, error) {
bufrdr, ok := rdr.(*bufio.Reader)
if !ok {
bufrdr = bufio.NewReader(rdr)
@@ -52,7 +52,7 @@ func ParseRequest(rdr io.Reader) (*sr.Request, int, error) {
return nil, 0, err
}
- return &sr.Request{
+ return &types.Request{
URL: &url.URL{
Scheme: "spartan",
Host: host,
@@ -65,7 +65,7 @@ func ParseRequest(rdr io.Reader) (*sr.Request, int, error) {
// GetRequestContentLength reads the remaining un-read number of bytes in a request body.
//
// It will immediately return 0 if there is no request body.
-func GetRequestContentLength(request *sr.Request) int {
+func GetRequestContentLength(request *types.Request) int {
if lr, ok := request.Meta.(*io.LimitedReader); ok {
return int(lr.N)
}
@@ -75,7 +75,7 @@ func GetRequestContentLength(request *sr.Request) int {
// GetRequestBody returns a reader of the spartan request body.
//
// It will return nil if the request has no body.
-func GetRequestBody(request *sr.Request) io.Reader {
+func GetRequestBody(request *types.Request) io.Reader {
if rdr, ok := request.Meta.(io.Reader); ok {
return rdr
}
@@ -88,7 +88,7 @@ func GetRequestBody(request *sr.Request) io.Reader {
//
// This function will read the entire contents into memory unless
// the reader is already an *io.LimitedReader.
-func SetRequestBody(request *sr.Request, body io.Reader) error {
+func SetRequestBody(request *types.Request, body io.Reader) error {
if rdr, ok := body.(*io.LimitedReader); ok {
request.Meta = rdr
return nil
diff --git a/spartan/response.go b/spartan/response.go
index aeddd68..df565f9 100644
--- a/spartan/response.go
+++ b/spartan/response.go
@@ -8,20 +8,20 @@ import (
"strconv"
"sync"
- sr "tildegit.org/tjp/sliderule"
+ "tildegit.org/tjp/sliderule/internal/types"
)
// The spartan response types.
const (
- StatusSuccess sr.Status = 2
- StatusRedirect sr.Status = 3
- StatusClientError sr.Status = 4
- StatusServerError sr.Status = 5
+ StatusSuccess types.Status = 2
+ StatusRedirect types.Status = 3
+ StatusClientError types.Status = 4
+ StatusServerError types.Status = 5
)
// Success builds a successful spartan response.
-func Success(mediatype string, body io.Reader) *sr.Response {
- return &sr.Response{
+func Success(mediatype string, body io.Reader) *types.Response {
+ return &types.Response{
Status: StatusSuccess,
Meta: mediatype,
Body: body,
@@ -29,24 +29,24 @@ func Success(mediatype string, body io.Reader) *sr.Response {
}
// Redirect builds a spartan redirect response.
-func Redirect(url string) *sr.Response {
- return &sr.Response{
+func Redirect(url string) *types.Response {
+ return &types.Response{
Status: StatusRedirect,
Meta: url,
}
}
// ClientError builds a "client error" spartan response.
-func ClientError(err error) *sr.Response {
- return &sr.Response{
+func ClientError(err error) *types.Response {
+ return &types.Response{
Status: StatusClientError,
Meta: err.Error(),
}
}
// ServerError builds a "server error" spartan response.
-func ServerError(err error) *sr.Response {
- return &sr.Response{
+func ServerError(err error) *types.Response {
+ return &types.Response{
Status: StatusServerError,
Meta: err.Error(),
}
@@ -58,7 +58,7 @@ var InvalidResponseHeaderLine = errors.New("Invalid response header line.")
// InvalidResponseLineEnding indicates that a spartan response header didn't end with "\r\n".
var InvalidResponseLineEnding = errors.New("Invalid response line ending.")
-func ParseResponse(rdr io.Reader) (*sr.Response, error) {
+func ParseResponse(rdr io.Reader) (*types.Response, error) {
bufrdr := bufio.NewReader(rdr)
hdrLine, err := bufrdr.ReadString('\n')
@@ -74,15 +74,15 @@ func ParseResponse(rdr io.Reader) (*sr.Response, error) {
return nil, InvalidResponseHeaderLine
}
- return &sr.Response{
- Status: sr.Status(status),
+ return &types.Response{
+ Status: types.Status(status),
Meta: hdrLine[2 : len(hdrLine)-2],
Body: bufrdr,
}, nil
}
// NewResponseReader builds a reader for a response.
-func NewResponseReader(response *sr.Response) sr.ResponseReader {
+func NewResponseReader(response *types.Response) types.ResponseReader {
return &responseReader{
Response: response,
once: &sync.Once{},
@@ -90,7 +90,7 @@ func NewResponseReader(response *sr.Response) sr.ResponseReader {
}
type responseReader struct {
- *sr.Response
+ *types.Response
reader io.Reader
once *sync.Once
}
diff --git a/spartan/serve.go b/spartan/serve.go
index a477a45..4b37f6a 100644
--- a/spartan/serve.go
+++ b/spartan/serve.go
@@ -8,14 +8,14 @@ import (
"io"
"net"
- sr "tildegit.org/tjp/sliderule"
+ "tildegit.org/tjp/sliderule/internal/types"
"tildegit.org/tjp/sliderule/internal"
"tildegit.org/tjp/sliderule/logging"
)
type spartanServer struct {
internal.Server
- handler sr.Handler
+ handler types.Handler
}
func (ss spartanServer) Protocol() string { return "SPARTAN" }
@@ -26,9 +26,9 @@ func NewServer(
hostname string,
network string,
address string,
- handler sr.Handler,
+ handler types.Handler,
errLog logging.Logger,
-) (sr.Server, error) {
+) (types.Server, error) {
ss := &spartanServer{handler: handler}
hostname = internal.JoinDefaultPort(hostname, "300")
@@ -46,7 +46,7 @@ func NewServer(
func (ss *spartanServer) handleConn(conn net.Conn) {
buf := bufio.NewReader(conn)
- var response *sr.Response
+ var response *types.Response
request, clen, err := ParseRequest(buf)
if err != nil {
response = ClientError(err)