Skip to content

Commit 4648b09

Browse files
authored
Handle only HTTP/S requests and improve excluded urls support (#128)
* Handle only http request * Direct handle excluded paths * Implement E2E to ensure exclude works
1 parent 114fd73 commit 4648b09

32 files changed

Lines changed: 175 additions & 213 deletions

cache/coalescing/requestCoalescing_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package coalescing
33
import (
44
"net/http"
55
"net/http/httptest"
6+
"regexp"
67
"testing"
78

89
"github.com/darkweak/souin/cache/providers"
@@ -17,12 +18,17 @@ func commonInitializer() (*httptest.ResponseRecorder, *http.Request, *types.Retr
1718
c := tests.MockConfiguration(tests.BaseConfiguration)
1819
prs := providers.InitializeProvider(c)
1920
regexpUrls := helpers.InitializeRegexp(c)
21+
var excludedRegexp *regexp.Regexp = nil
22+
if c.GetDefaultCache().GetRegex().Exclude != "" {
23+
excludedRegexp = regexp.MustCompile(c.GetDefaultCache().GetRegex().Exclude)
24+
}
2025
retriever := &types.RetrieverResponseProperties{
2126
Configuration: c,
2227
Provider: prs,
2328
MatchedURL: tests.GetMatchedURL(tests.PATH),
2429
RegexpUrls: regexpUrls,
2530
Transport: rfc.NewTransport(prs, ykeys.InitializeYKeys(c.Ykeys)),
31+
ExcludeRegex: excludedRegexp,
2632
}
2733
r := httptest.NewRequest("GET", "http://"+tests.DOMAIN+tests.PATH, nil)
2834
w := httptest.NewRecorder()

cache/providers/abstractProvider_test.go

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"testing"
55

66
"github.com/darkweak/souin/errors"
7-
"github.com/darkweak/souin/helpers"
87
"github.com/darkweak/souin/tests"
98
)
109

@@ -16,16 +15,3 @@ func TestInitializeProvider(t *testing.T) {
1615
errors.GenerateError(t, "Init shouldn't crash")
1716
}
1817
}
19-
20-
func TestPathnameNotInExcludeRegex(t *testing.T) {
21-
config := tests.MockConfiguration(tests.BaseConfiguration)
22-
if helpers.PathnameNotInExcludeRegex(config.GetDefaultCache().GetRegex().Exclude, config) {
23-
errors.GenerateError(t, "Pathname should be in regex")
24-
}
25-
if helpers.PathnameNotInExcludeRegex(config.GetDefaultCache().GetRegex().Exclude+"/A", config) {
26-
errors.GenerateError(t, "Pathname should be in regex")
27-
}
28-
if !helpers.PathnameNotInExcludeRegex("/BadPath", config) {
29-
errors.GenerateError(t, "Pathname shouldn't be in regex")
30-
}
31-
}

cache/service/requestService_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"net/http"
77
"net/http/httptest"
88
"net/url"
9+
"regexp"
910
"strings"
1011
"testing"
1112
"time"
@@ -159,13 +160,18 @@ func TestRequestReverseProxy(t *testing.T) {
159160
request := httptest.NewRequest("GET", "http://"+tests.DOMAIN+tests.PATH, nil)
160161
conf := tests.MockConfiguration(tests.BaseConfiguration)
161162
u, _ := url.Parse(conf.GetReverseProxyURL())
163+
var excludedRegexp *regexp.Regexp = nil
164+
if conf.GetDefaultCache().GetRegex().Exclude != "" {
165+
excludedRegexp = regexp.MustCompile(conf.GetDefaultCache().GetRegex().Exclude)
166+
}
162167
response := RequestReverseProxy(
163168
request,
164169
souintypes.SouinRetrieverResponseProperties{
165170
RetrieverResponseProperties: types.RetrieverResponseProperties{
166171
Provider: providers.InitializeProvider(conf),
167172
Configuration: conf,
168173
MatchedURL: tests.GetMatchedURL(tests.PATH),
174+
ExcludeRegex: excludedRegexp,
169175
},
170176
ReverseProxyURL: u,
171177
},

cache/types/souin.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ type RetrieverResponsePropertiesInterface interface {
4141
GetRegexpUrls() *regexp.Regexp
4242
GetTransport() TransportInterface
4343
SetTransport(TransportInterface)
44+
GetExcludeRegexp() *regexp.Regexp
4445
}
4546

4647
// RetrieverResponseProperties struct
@@ -50,6 +51,7 @@ type RetrieverResponseProperties struct {
5051
MatchedURL configurationtypes.URL
5152
RegexpUrls regexp.Regexp
5253
Transport TransportInterface
54+
ExcludeRegex *regexp.Regexp
5355
}
5456

5557
// GetProvider interface
@@ -86,3 +88,8 @@ func (r *RetrieverResponseProperties) GetTransport() TransportInterface {
8688
func (r *RetrieverResponseProperties) SetTransport(transportInterface TransportInterface) {
8789
r.Transport = transportInterface
8890
}
91+
92+
// GetExcludeRegexp get the excluded regexp
93+
func (r *RetrieverResponseProperties) GetExcludeRegexp() *regexp.Regexp {
94+
return r.ExcludeRegex
95+
}

docs/e2e/Souin E2E.postman_collection.json

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,40 @@
143143
}
144144
},
145145
"response": []
146+
},
147+
{
148+
"name": "Exclude regex",
149+
"event": [
150+
{
151+
"listen": "test",
152+
"script": {
153+
"exec": [
154+
"utils.baseEndpoint(pm, `${utils.getVar(pm, 'caddy_url')}/test2`, 'cache')"
155+
],
156+
"type": "text/javascript"
157+
}
158+
}
159+
],
160+
"request": {
161+
"method": "GET",
162+
"header": [
163+
{
164+
"key": "Cache-Control",
165+
"value": "",
166+
"type": "text"
167+
}
168+
],
169+
"url": {
170+
"raw": "{{caddy_url}}/test2",
171+
"host": [
172+
"{{caddy_url}}"
173+
],
174+
"path": [
175+
"test2"
176+
]
177+
}
178+
},
179+
"response": []
146180
}
147181
],
148182
"event": [
@@ -289,6 +323,40 @@
289323
}
290324
},
291325
"response": []
326+
},
327+
{
328+
"name": "Exclude regex",
329+
"event": [
330+
{
331+
"listen": "test",
332+
"script": {
333+
"exec": [
334+
"utils.baseEndpoint(pm, `${utils.getVar(pm, 'traefik_url')}/test_exclude_another`, 'cache')"
335+
],
336+
"type": "text/javascript"
337+
}
338+
}
339+
],
340+
"request": {
341+
"method": "GET",
342+
"header": [
343+
{
344+
"key": "Cache-Control",
345+
"value": "",
346+
"type": "text"
347+
}
348+
],
349+
"url": {
350+
"raw": "{{traefik_url}}/test_exclude_another",
351+
"host": [
352+
"{{traefik_url}}"
353+
],
354+
"path": [
355+
"test_exclude_another"
356+
]
357+
}
358+
},
359+
"response": []
292360
}
293361
],
294362
"event": [
@@ -394,7 +462,7 @@
394462
" pm.response.to.not.have.header(\"Age\");",
395463
" });",
396464
" pm.sendRequest(utils.request(baseUrl, cacheControl), function (_, response) {",
397-
" pm.test(`Status code is 200, Cache-Status and Age are ${cacheControl == '' ? '' : 'not '}present`, function () {",
465+
" pm.test(`Status code is 200, Cache-Status and Age are ${cacheControl === '' ? '' : 'not '}present`, function () {",
398466
" const expected = pm.expect(response);",
399467
" expected.to.have.status(200);",
400468
"",

helpers/helpers.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,3 @@ func InitializeRegexp(configurationInstance configurationtypes.AbstractConfigura
1818

1919
return *regexp.MustCompile(u)
2020
}
21-
22-
// PathnameNotInExcludeRegex check if pathname is in parameter regex var
23-
func PathnameNotInExcludeRegex(pathname string, configuration configurationtypes.AbstractConfigurationInterface) bool {
24-
b, _ := regexp.Match(configuration.GetDefaultCache().GetRegex().Exclude, []byte(pathname))
25-
return !b
26-
}

plugins/base.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,19 @@ import (
1414
"go.uber.org/zap/zapcore"
1515
"io/ioutil"
1616
"net/http"
17+
"regexp"
1718
"strings"
1819
"sync"
1920
)
2021

22+
// CustomWriter handles the response and provide the way to cache the value
2123
type CustomWriter struct {
2224
Response *http.Response
2325
http.ResponseWriter
2426
BufPool *sync.Pool
2527
}
2628

29+
// WriteHeader will write the response headers
2730
func (r *CustomWriter) WriteHeader(code int) {
2831
if code == 0 {
2932
return
@@ -32,6 +35,7 @@ func (r *CustomWriter) WriteHeader(code int) {
3235
r.ResponseWriter.WriteHeader(code)
3336
}
3437

38+
// Write will write the response body
3539
func (r *CustomWriter) Write(b []byte) (int, error) {
3640
buf := r.BufPool.Get().(*bytes.Buffer)
3741
buf.Reset()
@@ -45,6 +49,11 @@ func (r *CustomWriter) Write(b []byte) (int, error) {
4549
return r.ResponseWriter.Write(buf.Bytes())
4650
}
4751

52+
// CanHandle detect if the request can be handled by Souin
53+
func CanHandle(r *http.Request, re types.RetrieverResponsePropertiesInterface) bool {
54+
return r.Header.Get("Upgrade") != "websocket" && (re.GetExcludeRegexp() == nil || !re.GetExcludeRegexp().MatchString(r.RequestURI))
55+
}
56+
4857
// DefaultSouinPluginCallback is the default callback for plugins
4958
func DefaultSouinPluginCallback(
5059
res http.ResponseWriter,
@@ -133,6 +142,10 @@ func DefaultSouinPluginInitializerFromConfiguration(c configurationtypes.Abstrac
133142
regexpUrls := helpers.InitializeRegexp(c)
134143
transport := rfc.NewTransport(provider, ykeys.InitializeYKeys(c.GetYkeys()))
135144
c.GetLogger().Debug("Transport initialized.")
145+
var excludedRegexp *regexp.Regexp = nil
146+
if c.GetDefaultCache().GetRegex().Exclude != "" {
147+
excludedRegexp = regexp.MustCompile(c.GetDefaultCache().GetRegex().Exclude)
148+
}
136149

137150
retriever := &types.RetrieverResponseProperties{
138151
MatchedURL: configurationtypes.URL{
@@ -143,6 +156,7 @@ func DefaultSouinPluginInitializerFromConfiguration(c configurationtypes.Abstrac
143156
Configuration: c,
144157
RegexpUrls: regexpUrls,
145158
Transport: transport,
159+
ExcludeRegex: excludedRegexp,
146160
}
147161
retriever.Transport.SetURL(retriever.MatchedURL)
148162
retriever.GetConfiguration().GetLogger().Info("Souin configuration is now loaded.")

plugins/caddy/Caddyfile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
enable true
1010
}
1111
}
12+
regex {
13+
exclude /test2.*
14+
}
1215
headers Content-Type Authorization
1316
log_level debug
1417
ttl 1000s

plugins/caddy/go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@ require (
77
github.com/darkweak/souin v1.5.4
88
go.uber.org/zap v1.19.0
99
)
10+
11+
replace github.com/darkweak/souin v1.5.4 => ../..

plugins/caddy/go.sum

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,8 +233,6 @@ github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7Do
233233
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
234234
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
235235
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964/go.mod h1:Xd9hchkHSWYkEqJwUGisez3G1QY8Ryz0sdWrLPMGjLk=
236-
github.com/darkweak/souin v1.5.4 h1:CVA0u++QioIcFIoo758+04ljjc7vF0xeKMz0EBfGeVQ=
237-
github.com/darkweak/souin v1.5.4/go.mod h1:PESj/hdxxnOwCh6x3YrBrI4iQSgpdM3/Crz5Tbg3hW4=
238236
github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
239237
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
240238
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=

0 commit comments

Comments
 (0)