Skip to content

Commit 0dee22c

Browse files
authored
Merge pull request #256 from roadrunner-server/chore/cleanup-modernize-deps
chore: simplify, modernize (Go 1.26), update deps
2 parents 40adf9b + e336bd5 commit 0dee22c

9 files changed

Lines changed: 89 additions & 128 deletions

File tree

acme/acme.go

Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -20,36 +20,24 @@ func IssueCertificates(cacheDir, email, challengeType string, domains []string,
2020
cache := certmagic.NewCache(certmagic.CacheOptions{
2121
GetConfigForCert: func(_ certmagic.Certificate) (*certmagic.Config, error) {
2222
return &certmagic.Config{
23-
RenewalWindowRatio: 0,
24-
MustStaple: false,
25-
OCSP: certmagic.OCSPConfig{},
26-
Storage: &certmagic.FileStorage{Path: cacheDir},
23+
Storage: &certmagic.FileStorage{Path: cacheDir},
2724
}, nil
2825
},
29-
OCSPCheckInterval: 0,
30-
RenewCheckInterval: 0,
31-
Capacity: 0,
3226
})
3327

3428
cfg := certmagic.New(cache, certmagic.Config{
35-
RenewalWindowRatio: 0,
36-
MustStaple: false,
37-
OCSP: certmagic.OCSPConfig{},
38-
Storage: &certmagic.FileStorage{Path: cacheDir},
29+
Storage: &certmagic.FileStorage{Path: cacheDir},
3930
})
4031

4132
myAcme := certmagic.NewACMEIssuer(cfg, certmagic.ACMEIssuer{
42-
CA: certmagic.LetsEncryptProductionCA,
43-
TestCA: certmagic.LetsEncryptStagingCA,
44-
Email: email,
45-
Agreed: true,
46-
DisableHTTPChallenge: false,
47-
DisableTLSALPNChallenge: false,
48-
ListenHost: "0.0.0.0",
49-
AltHTTPPort: altHTTPPort,
50-
AltTLSALPNPort: altTLSAlpnPort,
51-
CertObtainTimeout: time.Second * 240,
52-
PreferredChains: certmagic.ChainPreference{},
33+
CA: certmagic.LetsEncryptProductionCA,
34+
TestCA: certmagic.LetsEncryptStagingCA,
35+
Email: email,
36+
Agreed: true,
37+
ListenHost: "0.0.0.0",
38+
AltHTTPPort: altHTTPPort,
39+
AltTLSALPNPort: altTLSAlpnPort,
40+
CertObtainTimeout: time.Second * 240,
5341
})
5442

5543
if !useProduction {

attributes/attributes.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,11 @@ func Get(r *http.Request, key string) any {
7272
return nil
7373
}
7474

75-
return v.(attrs).get(key)
75+
a, ok := v.(attrs)
76+
if !ok {
77+
return nil
78+
}
79+
return a.get(key)
7680
}
7781

7882
// Set sets the key to value. It replaces any existing
@@ -83,7 +87,11 @@ func Set(r *http.Request, key string, value string) error {
8387
return errors.New("unable to find `psr:attributes` context key")
8488
}
8589

86-
v.(attrs).set(key, value)
90+
a, ok := v.(attrs)
91+
if !ok {
92+
return errors.New("unexpected type stored under `psr:attributes` context key")
93+
}
94+
a.set(key, value)
8795
return nil
8896
}
8997

handler/request.go

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,6 @@ const (
2424
// FetchIP extracts the client IP from net/http's RemoteAddr ("host:port"
2525
// or a bare IP). Returns the empty string for unparseable input.
2626
func FetchIP(pair string, log *slog.Logger) string {
27-
if !strings.ContainsRune(pair, ':') {
28-
return pair
29-
}
30-
3127
addr, _, err := net.SplitHostPort(pair)
3228
if err == nil {
3329
return addr
@@ -44,9 +40,7 @@ func FetchIP(pair string, log *slog.Logger) string {
4440
// URI returns the fully-qualified request URI, stripping CR/LF to prevent
4541
// header smuggling via the URL.
4642
func URI(r *http.Request) string {
47-
uri := r.URL.String()
48-
uri = strings.ReplaceAll(uri, "\n", "")
49-
uri = strings.ReplaceAll(uri, "\r", "")
43+
uri := strings.ReplaceAll(strings.ReplaceAll(r.URL.String(), "\n", ""), "\r", "")
5044

5145
if r.URL.Host != "" {
5246
return uri
@@ -88,9 +82,7 @@ func extractCookies(r *http.Request) map[string]string {
8882

8983
// cleanRawQuery strips CR/LF from the URL raw query before exposing it to PHP.
9084
func cleanRawQuery(q string) string {
91-
q = strings.ReplaceAll(q, "\n", "")
92-
q = strings.ReplaceAll(q, "\r", "")
93-
return q
85+
return strings.ReplaceAll(strings.ReplaceAll(q, "\n", ""), "\r", "")
9486
}
9587

9688
// populateBody fills req.Body / req.Parsed based on the request content-type.

handler/uploads.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ package handler
22

33
import (
44
"encoding/json"
5+
"errors"
56
"io"
7+
"io/fs"
68
"log/slog"
79
"mime/multipart"
810
"os"
@@ -166,8 +168,6 @@ func (f *FileUpload) Open(dir string, forbid, allow map[string]struct{}) error {
166168
// exists if file exists.
167169
func exists(path string) bool {
168170
// path is RR-generated TempFilename, not user-controlled.
169-
if _, err := os.Stat(path); os.IsNotExist(err) { //nolint:gosec // G703
170-
return false
171-
}
172-
return true
171+
_, err := os.Stat(path) //nolint:gosec // G703
172+
return !errors.Is(err, fs.ErrNotExist)
173173
}

middleware/log.go

Lines changed: 30 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ import (
1616
var _ io.ReadCloser = (*wrapper)(nil)
1717
var _ http.ResponseWriter = (*wrapper)(nil)
1818

19+
// stripCRLF removes CR/LF to prevent log injection (CWE-117).
20+
func stripCRLF(s string) string {
21+
return strings.ReplaceAll(strings.ReplaceAll(s, "\n", ""), "\r", "")
22+
}
23+
1924
type wrapper struct {
2025
io.ReadCloser
2126
read int
@@ -27,7 +32,6 @@ type wrapper struct {
2732

2833
w http.ResponseWriter
2934
code int
30-
data []byte
3135
}
3236

3337
func (w *wrapper) Read(b []byte) (int, error) {
@@ -85,7 +89,6 @@ func (w *wrapper) reset() {
8589
w.wc = false
8690
w.write = 0
8791
w.w = nil
88-
w.data = nil
8992
w.ReadCloser = nil
9093
}
9194

@@ -128,8 +131,7 @@ func (l *lm) Log(next http.Handler, accessLogs bool) http.Handler {
128131
}
129132

130133
func (l *lm) writeLog(accessLog bool, r *http.Request, bw *wrapper, start time.Time) {
131-
switch accessLog {
132-
case false:
134+
if !accessLog {
133135
l.log.Info("http log",
134136
"status", bw.code,
135137
"method", r.Method,
@@ -140,38 +142,31 @@ func (l *lm) writeLog(accessLog bool, r *http.Request, bw *wrapper, start time.T
140142
"write_bytes", bw.write,
141143
"start", start,
142144
"elapsed", time.Since(start).Milliseconds())
143-
case true:
144-
// external/cwe/cwe-117
145-
usrA := r.UserAgent()
146-
usrA = strings.ReplaceAll(usrA, "\n", "")
147-
usrA = strings.ReplaceAll(usrA, "\r", "")
148-
149-
rfr := r.Referer()
150-
rfr = strings.ReplaceAll(rfr, "\n", "")
151-
rfr = strings.ReplaceAll(rfr, "\r", "")
152-
153-
rq := r.URL.RawQuery
154-
rq = strings.ReplaceAll(rq, "\n", "")
155-
rq = strings.ReplaceAll(rq, "\r", "")
156-
157-
l.log.Info("http access log",
158-
"read_bytes", bw.read,
159-
"write_bytes", bw.write,
160-
"status", bw.code,
161-
"method", r.Method,
162-
"URI", r.RequestURI,
163-
"URL", r.URL.String(),
164-
"remote_address", r.RemoteAddr,
165-
"query", rq,
166-
"content_len", r.ContentLength,
167-
"host", r.Host,
168-
"user_agent", usrA,
169-
"referer", rfr,
170-
"time_local", time.Now().Format("02/Jan/06:15:04:05 -0700"),
171-
"request_time", time.Now(),
172-
"start", start,
173-
"elapsed", time.Since(start).Milliseconds())
145+
return
174146
}
147+
148+
// external/cwe/cwe-117
149+
usrA := stripCRLF(r.UserAgent())
150+
rfr := stripCRLF(r.Referer())
151+
rq := stripCRLF(r.URL.RawQuery)
152+
153+
l.log.Info("http access log",
154+
"read_bytes", bw.read,
155+
"write_bytes", bw.write,
156+
"status", bw.code,
157+
"method", r.Method,
158+
"URI", r.RequestURI,
159+
"URL", r.URL.String(),
160+
"remote_address", r.RemoteAddr,
161+
"query", rq,
162+
"content_len", r.ContentLength,
163+
"host", r.Host,
164+
"user_agent", usrA,
165+
"referer", rfr,
166+
"time_local", start.Format("02/Jan/06:15:04:05 -0700"),
167+
"request_time", start,
168+
"start", start,
169+
"elapsed", time.Since(start).Milliseconds())
175170
}
176171

177172
func (l *lm) getW(w http.ResponseWriter) *wrapper {

middleware/maxRequest.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,8 @@ import (
66

77
func MaxRequestSize(next http.Handler, maxReqSize uint64) http.Handler {
88
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
9-
// validating request size
10-
11-
r2 := r.Clone(r.Context())
12-
r2.Body = http.MaxBytesReader(w, r2.Body, int64(maxReqSize)) //nolint:gosec
13-
149
// use max_request_size limit in megabytes
15-
next.ServeHTTP(w, r2)
10+
r.Body = http.MaxBytesReader(w, r.Body, int64(maxReqSize)) //nolint:gosec
11+
next.ServeHTTP(w, r)
1612
})
1713
}

plugin.go

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import (
1717
"github.com/roadrunner-server/http/v6/handler"
1818
"github.com/roadrunner-server/http/v6/proxy"
1919
"github.com/roadrunner-server/http/v6/servers"
20-
"github.com/roadrunner-server/pool/v2/pool/static_pool"
2120
"github.com/roadrunner-server/pool/v2/state/process"
2221
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
2322
jprop "go.opentelemetry.io/contrib/propagators/jaeger"
@@ -128,12 +127,18 @@ func (p *Plugin) Serve() chan error {
128127
p.mu.Lock()
129128
defer p.mu.Unlock()
130129

131-
var err error
132-
p.pool, err = p.server.NewPool(context.Background(), p.cfg.Pool, map[string]string{RrMode: RrModeHTTP}, p.log)
130+
// NewPool returns a concrete *static_pool.Pool; assign it to the api.Pool
131+
// interface field only when non-nil so p.pool never holds a typed nil
132+
// (which would make the p.pool != nil guard in Stop spuriously true and
133+
// panic inside Destroy on a nil receiver).
134+
np, err := p.server.NewPool(context.Background(), p.cfg.Pool, map[string]string{RrMode: RrModeHTTP}, p.log)
133135
if err != nil {
134136
errCh <- err
135137
return errCh
136138
}
139+
if np != nil {
140+
p.pool = np
141+
}
137142

138143
// request queue + worker-facing ConnectRPC server
139144
p.queue = proxy.NewQueue(p.cfg.Proxy.InboxSize)
@@ -161,14 +166,12 @@ func (p *Plugin) Serve() chan error {
161166
p.applyBundledMiddleware()
162167

163168
// start all servers
164-
for i := range p.servers {
165-
go func(idx int) {
166-
errSt := p.servers[idx].Serve(p.mdwr, p.cfg.Middleware)
167-
if errSt != nil {
169+
for _, srv := range p.servers {
170+
go func(s servers.InternalServer[any]) {
171+
if errSt := s.Serve(p.mdwr, p.cfg.Middleware); errSt != nil {
168172
errCh <- errSt
169-
return
170173
}
171-
}(i)
174+
}(srv)
172175
}
173176

174177
return errCh
@@ -201,14 +204,7 @@ func (p *Plugin) Stop(ctx context.Context) error {
201204
}
202205

203206
if p.pool != nil {
204-
switch pp := p.pool.(type) {
205-
case *static_pool.Pool:
206-
if pp != nil {
207-
pp.Destroy(ctx)
208-
}
209-
default:
210-
// pool is nil, nothing to do
211-
}
207+
p.pool.Destroy(ctx)
212208
}
213209

214210
doneCh <- struct{}{}
@@ -242,8 +238,6 @@ func (p *Plugin) ServeHTTP(w http.ResponseWriter, r *http.Request) {
242238
p.handler.ServeHTTP(w, r)
243239
p.mu.RUnlock()
244240

245-
_ = r.Body.Close()
246-
247241
if span != nil {
248242
span.End()
249243
}

servers/https/config.go

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
package https
22

33
import (
4+
"errors"
5+
"io/fs"
46
"net"
57
"os"
68
"strconv"
79

8-
"github.com/roadrunner-server/errors"
10+
rrerrors "github.com/roadrunner-server/errors"
911
"github.com/roadrunner-server/http/v6/acme"
1012
)
1113

@@ -95,11 +97,11 @@ func (s *SSL) EnableACME() bool {
9597
}
9698

9799
func (s *SSL) Valid() error {
98-
const op = errors.Op("ssl_valid")
100+
const op = rrerrors.Op("ssl_valid")
99101

100102
host, portStr, err := net.SplitHostPort(s.Address)
101103
if err != nil {
102-
return errors.E(op, err)
104+
return rrerrors.E(op, err)
103105
}
104106
if host == "" {
105107
s.host = "127.0.0.1"
@@ -108,23 +110,23 @@ func (s *SSL) Valid() error {
108110
}
109111
port, err := strconv.ParseUint(portStr, 10, 16)
110112
if err != nil {
111-
return errors.E(op, err)
113+
return rrerrors.E(op, err)
112114
}
113115
s.Port = int(port)
114116

115117
// the user use they own certificates
116118
if s.Acme == nil {
117119
if _, err := os.Stat(s.Key); err != nil {
118-
if os.IsNotExist(err) {
119-
return errors.E(op, errors.Errorf("key file '%s' does not exists", s.Key))
120+
if errors.Is(err, fs.ErrNotExist) {
121+
return rrerrors.E(op, rrerrors.Errorf("key file '%s' does not exists", s.Key))
120122
}
121123

122124
return err
123125
}
124126

125127
if _, err := os.Stat(s.Cert); err != nil {
126-
if os.IsNotExist(err) {
127-
return errors.E(op, errors.Errorf("cert file '%s' does not exists", s.Cert))
128+
if errors.Is(err, fs.ErrNotExist) {
129+
return rrerrors.E(op, rrerrors.Errorf("cert file '%s' does not exists", s.Cert))
128130
}
129131

130132
return err
@@ -134,8 +136,8 @@ func (s *SSL) Valid() error {
134136
// RootCA is optional, but if provided - check it
135137
if s.RootCA != "" {
136138
if _, err := os.Stat(s.RootCA); err != nil {
137-
if os.IsNotExist(err) {
138-
return errors.E(op, errors.Errorf("root ca path provided, but path '%s' does not exists", s.RootCA))
139+
if errors.Is(err, fs.ErrNotExist) {
140+
return rrerrors.E(op, rrerrors.Errorf("root ca path provided, but path '%s' does not exists", s.RootCA))
139141
}
140142
return err
141143
}

0 commit comments

Comments
 (0)