summaryrefslogtreecommitdiff
path: root/gemini
diff options
context:
space:
mode:
Diffstat (limited to 'gemini')
-rw-r--r--gemini/roundtrip_test.go8
-rw-r--r--gemini/serve.go21
2 files changed, 22 insertions, 7 deletions
diff --git a/gemini/roundtrip_test.go b/gemini/roundtrip_test.go
index 4f48e47..ab7baa4 100644
--- a/gemini/roundtrip_test.go
+++ b/gemini/roundtrip_test.go
@@ -27,7 +27,9 @@ func TestRoundTrip(t *testing.T) {
server, err := gemini.NewServer(context.Background(), nil, tlsConf, "tcp", "127.0.0.1:0", handler)
require.Nil(t, err)
- go server.Serve()
+ go func() {
+ _ = server.Serve()
+ }()
defer server.Close()
u, err := url.Parse(fmt.Sprintf("gemini://%s/test", server.Address()))
@@ -70,7 +72,9 @@ func TestTitanRequest(t *testing.T) {
server, err := gemini.NewServer(context.Background(), nil, tlsConf, "tcp", "127.0.0.1:0", handler)
require.Nil(t, err)
- go server.Serve()
+ go func() {
+ _ = server.Serve()
+ }()
defer server.Close()
conn, err := tls.Dial(server.Network(), server.Address(), testClientTLS())
diff --git a/gemini/serve.go b/gemini/serve.go
index dd7ad52..abed257 100644
--- a/gemini/serve.go
+++ b/gemini/serve.go
@@ -5,6 +5,7 @@ import (
"context"
"crypto/tls"
"errors"
+ "fmt"
"io"
"net"
"strconv"
@@ -15,11 +16,13 @@ import (
"tildegit.org/tjp/gus/logging"
)
+type titanRequestBodyKey struct{}
+
// TitanRequestBody is the key set in a handler's context for titan requests.
//
// When this key is present in the context (request.URL.Scheme will be "titan"), the
// corresponding value is a *bufio.Reader from which the request body can be read.
-const TitanRequestBody = "titan_request_body"
+var TitanRequestBody = titanRequestBodyKey{}
type server struct {
ctx context.Context
@@ -70,7 +73,7 @@ func NewServer(
// but be aware that Close() must still be called in that case to avoid
// dangling goroutines.
//
-// On titan protocol requests, it sets a key/value pair in the context. The
+// On titan protocol requests it sets a key/value pair in the context. The
// key is TitanRequestBody, and the value is a *bufio.Reader from which the
// request body can be read.
func (s *server) Serve() error {
@@ -88,7 +91,7 @@ func (s *server) Serve() error {
if s.Closed() {
err = nil
} else {
- s.errorLog.Log("msg", "accept_error", "error", err)
+ _ = s.errorLog.Log("msg", "accept error", "error", err)
}
return err
@@ -135,7 +138,7 @@ func (s *server) handleConn(conn net.Conn) {
} else {
req.Server = s
req.RemoteAddr = conn.RemoteAddr()
- if tlsconn, ok := conn.(*tls.Conn); req != nil && ok {
+ if tlsconn, ok := conn.(*tls.Conn); ok {
state := tlsconn.ConnectionState()
req.TLSState = &state
}
@@ -146,12 +149,20 @@ func (s *server) handleConn(conn net.Conn) {
if err == nil {
ctx = context.WithValue(
ctx,
- "titan_request_body",
+ TitanRequestBody,
io.LimitReader(buf, int64(len)),
)
}
}
+ defer func() {
+ if r := recover(); r != nil {
+ err := fmt.Errorf("%s", r)
+ _ = s.errorLog.Log("msg", "panic in handler", "err", err)
+ _, _ = io.Copy(conn, NewResponseReader(Failure(err)))
+ }
+ }()
+
response = s.handler(ctx, req)
if response == nil {
response = NotFound("Resource does not exist.")