testing and linting and linter fixes
continuous-integration/drone/push Build is passing Details

This commit is contained in:
tjpcc 2023-01-24 19:59:47 -07:00
parent 23d705b93a
commit 997514292a
7 changed files with 61 additions and 43 deletions

View File

@ -6,4 +6,6 @@ steps:
- name: test - name: test
image: golang image: golang
commands: commands:
- go test -v ./... - go test -race -v ./...
- name: lint
image: rancher/drone-golangci-lint:latest

View File

@ -116,9 +116,7 @@ func RunCGI(
} }
scriptName := req.Path[:len(req.Path)-infoLen] scriptName := req.Path[:len(req.Path)-infoLen]
if strings.HasSuffix(scriptName, "/") { scriptName = strings.TrimSuffix(scriptName, "/")
scriptName = scriptName[:len(scriptName)-1]
}
cmd := exec.CommandContext(ctx, "./"+basename) cmd := exec.CommandContext(ctx, "./"+basename)
cmd.Env = prepareCGIEnv(ctx, req, scriptName, pathInfo) cmd.Env = prepareCGIEnv(ctx, req, scriptName, pathInfo)

View File

@ -38,7 +38,9 @@ func TestIdentify(t *testing.T) {
leafCert, err := x509.ParseCertificate(clientCert.Certificate[0]) leafCert, err := x509.ParseCertificate(clientCert.Certificate[0])
require.Nil(t, err) require.Nil(t, err)
go server.Serve() go func() {
_ = server.Serve()
}()
defer server.Close() defer server.Close()
requestPath(t, client, server, "/") requestPath(t, client, server, "/")
@ -75,7 +77,9 @@ func TestRequiredAuth(t *testing.T) {
gus.FallthroughHandler(handler1, handler2), gus.FallthroughHandler(handler1, handler2),
) )
go server.Serve() go func() {
_ = server.Serve()
}()
defer server.Close() defer server.Close()
requestPath(t, client, server, "/one") requestPath(t, client, server, "/one")
@ -113,7 +117,9 @@ func TestOptionalAuth(t *testing.T) {
handler, handler,
) )
go server.Serve() go func() {
_ = server.Serve()
}()
defer server.Close() defer server.Close()
requestPath(t, client, server, "/one") requestPath(t, client, server, "/one")

View File

@ -54,7 +54,9 @@ func TestGeminiAuth(t *testing.T) {
authlessClient, _ := clientFor(t, server, "", "") authlessClient, _ := clientFor(t, server, "", "")
go server.Serve() go func() {
_ = server.Serve()
}()
defer server.Close() defer server.Close()
resp := requestPath(t, authClient, server, "/one") resp := requestPath(t, authClient, server, "/one")
@ -94,7 +96,9 @@ func TestGeminiOptionalAuth(t *testing.T) {
) )
authlessClient, _ := clientFor(t, server, "", "") authlessClient, _ := clientFor(t, server, "", "")
go server.Serve() go func() {
_ = server.Serve()
}()
defer server.Close() defer server.Close()
resp := requestPath(t, authClient, server, "/one") resp := requestPath(t, authClient, server, "/one")

View File

@ -27,7 +27,9 @@ func TestRoundTrip(t *testing.T) {
server, err := gemini.NewServer(context.Background(), nil, tlsConf, "tcp", "127.0.0.1:0", handler) server, err := gemini.NewServer(context.Background(), nil, tlsConf, "tcp", "127.0.0.1:0", handler)
require.Nil(t, err) require.Nil(t, err)
go server.Serve() go func() {
_ = server.Serve()
}()
defer server.Close() defer server.Close()
u, err := url.Parse(fmt.Sprintf("gemini://%s/test", server.Address())) 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) server, err := gemini.NewServer(context.Background(), nil, tlsConf, "tcp", "127.0.0.1:0", handler)
require.Nil(t, err) require.Nil(t, err)
go server.Serve() go func() {
_ = server.Serve()
}()
defer server.Close() defer server.Close()
conn, err := tls.Dial(server.Network(), server.Address(), testClientTLS()) conn, err := tls.Dial(server.Network(), server.Address(), testClientTLS())

View File

@ -5,6 +5,7 @@ import (
"context" "context"
"crypto/tls" "crypto/tls"
"errors" "errors"
"fmt"
"io" "io"
"net" "net"
"strconv" "strconv"
@ -15,11 +16,13 @@ import (
"tildegit.org/tjp/gus/logging" "tildegit.org/tjp/gus/logging"
) )
type titanRequestBodyKey struct{}
// TitanRequestBody is the key set in a handler's context for titan requests. // 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 // 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. // 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 { type server struct {
ctx context.Context ctx context.Context
@ -70,7 +73,7 @@ func NewServer(
// but be aware that Close() must still be called in that case to avoid // but be aware that Close() must still be called in that case to avoid
// dangling goroutines. // 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 // key is TitanRequestBody, and the value is a *bufio.Reader from which the
// request body can be read. // request body can be read.
func (s *server) Serve() error { func (s *server) Serve() error {
@ -88,7 +91,7 @@ func (s *server) Serve() error {
if s.Closed() { if s.Closed() {
err = nil err = nil
} else { } else {
s.errorLog.Log("msg", "accept_error", "error", err) _ = s.errorLog.Log("msg", "accept error", "error", err)
} }
return err return err
@ -135,7 +138,7 @@ func (s *server) handleConn(conn net.Conn) {
} else { } else {
req.Server = s req.Server = s
req.RemoteAddr = conn.RemoteAddr() req.RemoteAddr = conn.RemoteAddr()
if tlsconn, ok := conn.(*tls.Conn); req != nil && ok { if tlsconn, ok := conn.(*tls.Conn); ok {
state := tlsconn.ConnectionState() state := tlsconn.ConnectionState()
req.TLSState = &state req.TLSState = &state
} }
@ -146,12 +149,20 @@ func (s *server) handleConn(conn net.Conn) {
if err == nil { if err == nil {
ctx = context.WithValue( ctx = context.WithValue(
ctx, ctx,
"titan_request_body", TitanRequestBody,
io.LimitReader(buf, int64(len)), 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) response = s.handler(ctx, req)
if response == nil { if response == nil {
response = NotFound("Resource does not exist.") response = NotFound("Resource does not exist.")

View File

@ -3,6 +3,7 @@ package logging
import ( import (
"context" "context"
"errors" "errors"
"fmt"
"io" "io"
"time" "time"
@ -12,18 +13,9 @@ import (
func LogRequests(logger Logger) gus.Middleware { func LogRequests(logger Logger) gus.Middleware {
return func(inner gus.Handler) gus.Handler { return func(inner gus.Handler) gus.Handler {
return func(ctx context.Context, request *gus.Request) *gus.Response { return func(ctx context.Context, request *gus.Request) *gus.Response {
start := time.Now()
response := inner(ctx, request) response := inner(ctx, request)
if response != nil { if response != nil {
body := loggedResponseBody{ response.Body = loggingBody(logger, request, response)
request: request,
response: response,
body: response.Body,
start: start,
logger: logger,
}
response.Body = &body
} }
return response return response
@ -42,23 +34,6 @@ type loggedResponseBody struct {
logger Logger logger Logger
} }
func loggingBody(logger Logger, request *gus.Request, response *gus.Response) io.Reader {
body := &loggedResponseBody{
request: request,
response: response,
body: response.Body,
start: time.Now(),
written: 0,
logger: logger,
}
if _, ok := response.Body.(io.WriterTo); ok {
return loggedWriteToResponseBody{body}
}
return body
}
func (lr *loggedResponseBody) log() { func (lr *loggedResponseBody) log() {
end := time.Now() end := time.Now()
_ = lr.logger.Log( _ = lr.logger.Log(
@ -98,6 +73,7 @@ type loggedWriteToResponseBody struct {
} }
func (lwtr loggedWriteToResponseBody) WriteTo(dst io.Writer) (int64, error) { func (lwtr loggedWriteToResponseBody) WriteTo(dst io.Writer) (int64, error) {
fmt.Println("lwtrb.WriteTo()")
n, err := lwtr.body.(io.WriterTo).WriteTo(dst) n, err := lwtr.body.(io.WriterTo).WriteTo(dst)
if err == nil { if err == nil {
lwtr.written += int(n) lwtr.written += int(n)
@ -105,3 +81,20 @@ func (lwtr loggedWriteToResponseBody) WriteTo(dst io.Writer) (int64, error) {
} }
return n, err return n, err
} }
func loggingBody(logger Logger, request *gus.Request, response *gus.Response) io.Reader {
body := &loggedResponseBody{
request: request,
response: response,
body: response.Body,
start: time.Now(),
written: 0,
logger: logger,
}
if _, ok := response.Body.(io.WriterTo); ok {
return loggedWriteToResponseBody{body}
}
return body
}