Skip to content

Commit 56867e9

Browse files
authored
Release/0.8.0 (#110)
* Update dependencies * Bump up APIFW version to v0.8.0 * Bump up Go version to 1.21.13 * Fix GraphQL configuration issue * Add DNS cache * Add basic test for DNS LB cache
1 parent 1f769c3 commit 56867e9

30 files changed

+961
-332
lines changed

.github/workflows/binaries.yml

+4-4
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ jobs:
5151
needs:
5252
- draft-release
5353
env:
54-
X_GO_DISTRIBUTION: "https://go.dev/dl/go1.21.12.linux-amd64.tar.gz"
54+
X_GO_DISTRIBUTION: "https://go.dev/dl/go1.21.13.linux-amd64.tar.gz"
5555
strategy:
5656
matrix:
5757
include:
@@ -160,7 +160,7 @@ jobs:
160160
needs:
161161
- draft-release
162162
env:
163-
X_GO_VERSION: "1.21.12"
163+
X_GO_VERSION: "1.21.13"
164164
strategy:
165165
matrix:
166166
include:
@@ -267,11 +267,11 @@ jobs:
267267
include:
268268
- arch: armv6
269269
distro: bullseye
270-
go_distribution: https://go.dev/dl/go1.21.12.linux-armv6l.tar.gz
270+
go_distribution: https://go.dev/dl/go1.21.13.linux-armv6l.tar.gz
271271
artifact: armv6-libc
272272
- arch: aarch64
273273
distro: bullseye
274-
go_distribution: https://go.dev/dl/go1.21.12.linux-arm64.tar.gz
274+
go_distribution: https://go.dev/dl/go1.21.13.linux-arm64.tar.gz
275275
artifact: arm64-libc
276276
- arch: armv6
277277
distro: alpine_latest

Makefile

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
VERSION := 0.7.4
1+
VERSION := 0.8.0
22

33
.DEFAULT_GOAL := build
44

@@ -13,14 +13,16 @@ tidy:
1313
go mod vendor
1414

1515
test:
16-
go test ./... -count=1 -race -cover
16+
go test ./... -count=1 -race -cover -run '^Test[^W]'
17+
go test ./cmd/api-firewall/tests/main_dns_test.go
1718

1819
bench:
1920
GOMAXPROCS=1 go test -v -bench=. -benchtime=1000x -count 5 -benchmem -run BenchmarkWSGraphQL ./cmd/api-firewall/tests
2021
GOMAXPROCS=4 go test -v -bench=. -benchtime=1000x -count 5 -benchmem -run BenchmarkWSGraphQL ./cmd/api-firewall/tests
2122

2223
genmocks:
23-
mockgen -source ./internal/platform/proxy/chainpool.go -destination ./internal/platform/proxy/httppool_mock.go -package proxy
24+
mockgen -source ./internal/platform/proxy/chainpool.go -destination ./internal/platform/proxy/chainpool_mock.go -package proxy
25+
mockgen -source ./internal/platform/proxy/dnscache.go -destination ./internal/platform/proxy/dnscache_mock.go -package proxy
2426
mockgen -source ./internal/platform/storage/storage.go -destination ./internal/platform/storage/storage_mock.go -package storage
2527
mockgen -source ./internal/platform/storage/updater/updater.go -destination ./internal/platform/storage/updater/updater_mock.go -package updater
2628
mockgen -source ./internal/platform/proxy/ws.go -destination ./internal/platform/proxy/ws_mock.go -package proxy

cmd/api-firewall/internal/handlers/proxy/health.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,14 @@ func (h Health) Readiness(ctx *fasthttp.RequestCtx) error {
2121
status := "ok"
2222
statusCode := fasthttp.StatusOK
2323

24-
reverseProxy, err := h.Pool.Get()
24+
reverseProxy, ip, err := h.Pool.Get()
2525
if err != nil {
2626
status = "not ready"
2727
statusCode = fasthttp.StatusInternalServerError
2828
}
2929

3030
if reverseProxy != nil {
31-
if err := h.Pool.Put(reverseProxy); err != nil {
31+
if err := h.Pool.Put(ip, reverseProxy); err != nil {
3232
status = "not ready"
3333
statusCode = fasthttp.StatusInternalServerError
3434
}

cmd/api-firewall/main.go

+17-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"expvar" // Register the expvar handlers
55
"fmt"
66
"mime"
7+
"net"
78
"net/url"
89
"os"
910
"os/signal"
@@ -467,7 +468,7 @@ func runGraphQLMode(logger *logrus.Logger) error {
467468
WriteTimeout: cfg.Server.WriteTimeout,
468469
DialTimeout: cfg.Server.DialTimeout,
469470
}
470-
pool, err := proxy.NewChanPool(host, &options)
471+
pool, err := proxy.NewChanPool(host, &options, nil)
471472
if err != nil {
472473
return errors.Wrap(err, "proxy pool init")
473474
}
@@ -626,6 +627,9 @@ func runGraphQLMode(logger *logrus.Logger) error {
626627
return errors.Wrap(err, "could not stop server gracefully")
627628
}
628629
logger.Infof("%s: %v: Completed shutdown", logPrefix, sig)
630+
631+
// Close proxy pool
632+
pool.Close()
629633
}
630634

631635
return nil
@@ -773,6 +777,16 @@ func runProxyMode(logger *logrus.Logger) error {
773777
initialCap = 1
774778
}
775779

780+
var dnsCacheResolver proxy.DNSCache
781+
782+
// init DNS resolver
783+
if cfg.DNS.Cache {
784+
dnsCacheResolver, err = proxy.NewDNSResolver(cfg.DNS.FetchTimeout, cfg.DNS.LookupTimeout, &net.Resolver{PreferGo: true}, logger)
785+
if err != nil {
786+
return errors.Wrap(err, "DNS cache resolver init")
787+
}
788+
}
789+
776790
options := proxy.Options{
777791
InitialPoolCapacity: initialCap,
778792
ClientPoolCapacity: cfg.Server.ClientPoolCapacity,
@@ -782,8 +796,9 @@ func runProxyMode(logger *logrus.Logger) error {
782796
ReadTimeout: cfg.Server.ReadTimeout,
783797
WriteTimeout: cfg.Server.WriteTimeout,
784798
DialTimeout: cfg.Server.DialTimeout,
799+
DNSConfig: cfg.DNS,
785800
}
786-
pool, err := proxy.NewChanPool(host, &options)
801+
pool, err := proxy.NewChanPool(host, &options, dnsCacheResolver)
787802
if err != nil {
788803
return errors.Wrap(err, "proxy pool init")
789804
}
+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package tests
2+
3+
import (
4+
"context"
5+
"net"
6+
"testing"
7+
"time"
8+
9+
"github.com/foxcpp/go-mockdns"
10+
"github.com/sirupsen/logrus"
11+
"github.com/wallarm/api-firewall/internal/config"
12+
"github.com/wallarm/api-firewall/internal/platform/proxy"
13+
)
14+
15+
func TestWithoutRCCDNSCacheBasic(t *testing.T) {
16+
17+
logger := logrus.New()
18+
logger.SetLevel(logrus.ErrorLevel)
19+
20+
var cfg = config.ProxyMode{
21+
RequestValidation: "BLOCK",
22+
ResponseValidation: "BLOCK",
23+
CustomBlockStatusCode: 403,
24+
AddValidationStatusHeader: false,
25+
ShadowAPI: config.ShadowAPI{
26+
ExcludeList: []int{404, 401},
27+
},
28+
DNS: config.DNS{
29+
Cache: true,
30+
FetchTimeout: 1000 * time.Millisecond,
31+
LookupTimeout: 400 * time.Millisecond,
32+
},
33+
}
34+
35+
srv, _ := mockdns.NewServer(map[string]mockdns.Zone{
36+
"example.org.": {
37+
A: []string{"1.2.3.4", "5.6.7.8"},
38+
},
39+
}, false)
40+
defer srv.Close()
41+
42+
srUpdatedOrder, _ := mockdns.NewServer(map[string]mockdns.Zone{
43+
"example.org.": {
44+
A: []string{"5.6.7.8", "1.2.3.4"},
45+
},
46+
}, false)
47+
defer srUpdatedOrder.Close()
48+
49+
r := &net.Resolver{}
50+
srv.PatchNet(r)
51+
52+
dnsCache, err := proxy.NewDNSResolver(cfg.DNS.FetchTimeout, cfg.DNS.LookupTimeout, r, logger)
53+
if err != nil {
54+
t.Fatal(err)
55+
}
56+
defer dnsCache.Stop()
57+
58+
addr, err := dnsCache.Fetch(context.Background(), "example.org")
59+
if err != nil {
60+
t.Error(err)
61+
}
62+
63+
if addr[0].String() != "1.2.3.4" {
64+
t.Errorf("Incorrect response from local DNS server. Expected: 1.2.3.4 and got %s",
65+
addr[0].String())
66+
}
67+
68+
srUpdatedOrder.PatchNet(r)
69+
70+
time.Sleep(600 * time.Millisecond)
71+
72+
addr, err = dnsCache.Fetch(context.Background(), "example.org")
73+
if err != nil {
74+
t.Error(err)
75+
}
76+
77+
if addr[0].String() != "1.2.3.4" {
78+
t.Errorf("Incorrect response from local DNS server. Expected: 1.2.3.4 and got %s",
79+
addr[0].String())
80+
}
81+
82+
time.Sleep(800 * time.Millisecond)
83+
84+
addr, err = dnsCache.Fetch(context.Background(), "example.org")
85+
if err != nil {
86+
t.Error(err)
87+
}
88+
89+
if addr[0].String() != "5.6.7.8" {
90+
t.Errorf("Incorrect response from local DNS server. Expected: 5.6.7.8 and got %s",
91+
addr[0].String())
92+
}
93+
}

cmd/api-firewall/tests/main_graphql_bench_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ func BenchmarkGraphQL(b *testing.B) {
134134
WriteTimeout: 5 * time.Second,
135135
DialTimeout: 5 * time.Second,
136136
}
137-
pool, err := proxy.NewChanPool(host, &options)
137+
pool, err := proxy.NewChanPool(host, &options, nil)
138138
if err != nil {
139139
b.Fatalf("proxy pool init: %v", err)
140140
}

cmd/api-firewall/tests/main_graphql_test.go

+7-6
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"github.com/sirupsen/logrus/hooks/test"
1919
"github.com/stretchr/testify/assert"
2020
"github.com/valyala/fasthttp"
21+
2122
graphqlHandler "github.com/wallarm/api-firewall/cmd/api-firewall/internal/handlers/graphql"
2223
"github.com/wallarm/api-firewall/internal/config"
2324
"github.com/wallarm/api-firewall/internal/platform/denylist"
@@ -211,9 +212,9 @@ func (s *ServiceGraphQLTests) testGQLSuccess(t *testing.T) {
211212
Request: *req,
212213
}
213214

214-
s.proxy.EXPECT().Get().Return(s.client, nil).Times(1)
215+
s.proxy.EXPECT().Get().Return(s.client, resolvedIP, nil).Times(1)
215216
s.client.EXPECT().Do(gomock.Any(), gomock.Any()).SetArg(1, *resp).Times(1)
216-
s.proxy.EXPECT().Put(s.client).Return(nil).Times(1)
217+
s.proxy.EXPECT().Put(resolvedIP, s.client).Return(nil).Times(1)
217218

218219
handler(&reqCtx)
219220

@@ -384,9 +385,9 @@ func (s *ServiceGraphQLTests) testGQLGETSuccess(t *testing.T) {
384385
Request: *req,
385386
}
386387

387-
s.proxy.EXPECT().Get().Return(s.client, nil).Times(1)
388+
s.proxy.EXPECT().Get().Return(s.client, resolvedIP, nil).Times(1)
388389
s.client.EXPECT().Do(gomock.Any(), gomock.Any()).SetArg(1, *resp).Times(1)
389-
s.proxy.EXPECT().Put(s.client).Return(nil).Times(1)
390+
s.proxy.EXPECT().Put(resolvedIP, s.client).Return(nil).Times(1)
390391

391392
handler(&reqCtx)
392393

@@ -1715,9 +1716,9 @@ func (s *ServiceGraphQLTests) testGQLDuplicateFields(t *testing.T) {
17151716
Request: *req,
17161717
}
17171718

1718-
s.proxy.EXPECT().Get().Return(s.client, nil).AnyTimes()
1719+
s.proxy.EXPECT().Get().Return(s.client, resolvedIP, nil).AnyTimes()
17191720
s.client.EXPECT().Do(gomock.Any(), gomock.Any()).SetArg(1, *resp).AnyTimes()
1720-
s.proxy.EXPECT().Put(s.client).Return(nil).AnyTimes()
1721+
s.proxy.EXPECT().Put(resolvedIP, s.client).Return(nil).AnyTimes()
17211722

17221723
handler(&reqCtx)
17231724

cmd/api-firewall/tests/main_json_test.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -172,9 +172,9 @@ func (s *ServiceTests) testBasicObjJSONFieldValidation(t *testing.T) {
172172
Request: *req,
173173
}
174174

175-
s.proxy.EXPECT().Get().Return(s.client, nil)
175+
s.proxy.EXPECT().Get().Return(s.client, resolvedIP, nil)
176176
s.client.EXPECT().Do(gomock.Any(), gomock.Any()).SetArg(1, *resp)
177-
s.proxy.EXPECT().Put(s.client).Return(nil)
177+
s.proxy.EXPECT().Put(resolvedIP, s.client).Return(nil)
178178

179179
handler(&reqCtx)
180180

@@ -219,9 +219,9 @@ func (s *ServiceTests) testBasicArrJSONFieldValidation(t *testing.T) {
219219
Request: *req,
220220
}
221221

222-
s.proxy.EXPECT().Get().Return(s.client, nil)
222+
s.proxy.EXPECT().Get().Return(s.client, resolvedIP, nil)
223223
s.client.EXPECT().Do(gomock.Any(), gomock.Any()).SetArg(1, *resp)
224-
s.proxy.EXPECT().Put(s.client).Return(nil)
224+
s.proxy.EXPECT().Put(resolvedIP, s.client).Return(nil)
225225

226226
handler(&reqCtx)
227227

0 commit comments

Comments
 (0)