Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
k8s-ingress
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
3
Merge Requests
3
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
uplex-varnish
k8s-ingress
Commits
b113c219
Commit
b113c219
authored
Mar 29, 2019
by
Geoff Simmons
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add the req-disposition field to VarnishConfig.
Ref #24
parent
ddcfac81
Changes
26
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
26 changed files
with
2237 additions
and
73 deletions
+2237
-73
varnishcfg-crd.yaml
deploy/varnishcfg-crd.yaml
+88
-0
alt-builtin.yaml
examples/req-disposition/alt-builtin.yaml
+64
-0
builtin.yaml
examples/req-disposition/builtin.yaml
+75
-0
cacheability.yaml
examples/req-disposition/cacheability.yaml
+79
-0
purge-method.yaml
examples/req-disposition/purge-method.yaml
+64
-0
url-whitelist.yaml
examples/req-disposition/url-whitelist.yaml
+66
-0
go.mod
go.mod
+1
-0
go.sum
go.sum
+2
-0
types.go
pkg/apis/varnishingress/v1alpha1/types.go
+92
-6
ingress.go
pkg/controller/ingress.go
+115
-27
ingress_test.go
pkg/controller/ingress_test.go
+587
-0
varnishconfig.go
pkg/controller/varnishconfig.go
+74
-0
varnishconfig_test.go
pkg/controller/varnishconfig_test.go
+154
-0
recv_disposition.tmpl
pkg/varnish/vcl/recv_disposition.tmpl
+47
-0
recv_disposition_test.go
pkg/varnish/vcl/recv_disposition_test.go
+302
-0
rewrite_test.go
pkg/varnish/vcl/rewrite_test.go
+25
-24
spec.go
pkg/varnish/vcl/spec.go
+120
-2
template.go
pkg/varnish/vcl/template.go
+119
-14
recv_disp_builtin.golden
pkg/varnish/vcl/testdata/recv_disp_builtin.golden
+50
-0
recv_disp_cacheable.golden
pkg/varnish/vcl/testdata/recv_disp_cacheable.golden
+20
-0
recv_disp_connect_pipe.golden
pkg/varnish/vcl/testdata/recv_disp_connect_pipe.golden
+11
-0
recv_disp_method_not_allowed.golden
pkg/varnish/vcl/testdata/recv_disp_method_not_allowed.golden
+22
-0
recv_disp_non_cacheable.golden
pkg/varnish/vcl/testdata/recv_disp_non_cacheable.golden
+19
-0
recv_disp_pipe_on_connect.golden
pkg/varnish/vcl/testdata/recv_disp_pipe_on_connect.golden
+11
-0
recv_disp_purge_method.golden
pkg/varnish/vcl/testdata/recv_disp_purge_method.golden
+11
-0
recv_disp_url_whitelist.golden
pkg/varnish/vcl/testdata/recv_disp_url_whitelist.golden
+19
-0
No files found.
deploy/varnishcfg-crd.yaml
View file @
b113c219
...
...
@@ -278,6 +278,94 @@ spec:
type
:
boolean
word-boundary
:
type
:
boolean
req-disposition
:
type
:
array
minItems
:
1
items
:
type
:
object
required
:
-
conditions
-
disposition
properties
:
conditions
:
type
:
array
minItems
:
1
items
:
type
:
object
required
:
-
comparand
properties
:
comparand
:
type
:
string
pattern
:
"
^req
\\
.(url|method|proto|esi_level|restarts|http
\\
.[a-zA-Z0-9!#$%&'*+.^_`|~-]+)$"
compare
:
enum
:
-
equal
-
not-equal
-
match
-
not-match
-
prefix
-
not-prefix
-
exists
-
not-exists
-
greater
-
greater-equal
-
less
-
less-equal
type
:
string
values
:
type
:
array
minItems
:
1
items
:
type
:
string
count
:
type
:
integer
minimum
:
0
match-flags
:
type
:
object
properties
:
max-mem
:
type
:
integer
min
:
0
anchor
:
type
:
string
enum
:
-
none
-
start
-
both
utf8
:
type
:
boolean
posix-syntax
:
type
:
boolean
longest-match
:
type
:
boolean
literal
:
type
:
boolean
never-capture
:
type
:
boolean
case-sensitive
:
type
:
boolean
perl-classes
:
type
:
boolean
word-boundary
:
type
:
boolean
disposition
:
type
:
object
required
:
-
action
properties
:
action
:
enum
:
-
hash
-
pass
-
pipe
-
purge
-
synth
type
:
string
status
:
type
:
integer
minimum
:
200
maximum
:
599
status
:
acceptedNames
:
kind
:
VarnishConfig
...
...
examples/req-disposition/alt-builtin.yaml
0 → 100644
View file @
b113c219
# Configuration for disposition of client requests that permits cache
# lookups for requests with Cookie or Authorization headers, and
# handles some requests differently from vcl_recv in builtin.vcl.
apiVersion
:
"
ingress.varnish-cache.org/v1alpha1"
kind
:
VarnishConfig
metadata
:
name
:
alt-recv-cfg
spec
:
# The services array is required and must have at least one element.
# Lists the Service names of Varnish services in the same namespace
# to which this config is to be applied.
services
:
-
varnish-ingress
req-disposition
:
-
conditions
:
-
comparand
:
req.http.Host
compare
:
not-exists
-
comparand
:
req.esi_level
count
:
0
-
comparand
:
req.proto
compare
:
prefix
values
:
-
HTTP/1.1
match-flags
:
case-insensitive
:
true
disposition
:
action
:
synth
status
:
400
-
conditions
:
-
comparand
:
req.method
compare
:
equal
values
:
-
CONNECT
disposition
:
action
:
pipe
-
conditions
:
-
comparand
:
req.method
compare
:
not-equal
values
:
-
GET
-
HEAD
-
PUT
-
POST
-
TRACE
-
OPTIONS
-
DELETE
-
PATCH
disposition
:
action
:
synth
status
:
405
-
conditions
:
-
comparand
:
req.method
compare
:
not-equal
values
:
-
GET
-
HEAD
disposition
:
action
:
pass
examples/req-disposition/builtin.yaml
0 → 100644
View file @
b113c219
# Configuration for disposition of client requests that re-implements
# vcl_recv in builtin.vcl.
apiVersion
:
"
ingress.varnish-cache.org/v1alpha1"
kind
:
VarnishConfig
metadata
:
name
:
builtin-recv-cfg
spec
:
# The services array is required and must have at least one element.
# Lists the Service names of Varnish services in the same namespace
# to which this config is to be applied.
services
:
-
varnish-ingress
req-disposition
:
-
conditions
:
-
comparand
:
req.method
compare
:
equal
values
:
-
PRI
disposition
:
action
:
synth
status
:
405
-
conditions
:
-
comparand
:
req.http.Host
compare
:
not-exists
-
comparand
:
req.esi_level
count
:
0
-
comparand
:
req.proto
compare
:
prefix
values
:
-
HTTP/1.1
match-flags
:
case-sensitive
:
false
disposition
:
action
:
synth
status
:
400
-
conditions
:
-
comparand
:
req.method
compare
:
not-equal
values
:
-
GET
-
HEAD
-
PUT
-
POST
-
TRACE
-
OPTIONS
-
DELETE
-
PATCH
disposition
:
action
:
pipe
-
conditions
:
-
comparand
:
req.method
compare
:
not-equal
values
:
-
GET
-
HEAD
disposition
:
action
:
pass
-
conditions
:
-
comparand
:
req.http.Cookie
compare
:
exists
disposition
:
action
:
pass
-
conditions
:
-
comparand
:
req.http.Authorization
compare
:
exists
disposition
:
action
:
pass
examples/req-disposition/cacheability.yaml
0 → 100644
View file @
b113c219
# Configuration for disposition of client requests that permits cache
# lookups for requests with Cookie or Authorization headers, and
# defines URL path patterns for which cache lookups are invoked or
# bypassed.
apiVersion
:
"
ingress.varnish-cache.org/v1alpha1"
kind
:
VarnishConfig
metadata
:
name
:
cacheability-cfg
spec
:
# The services array is required and must have at least one element.
# Lists the Service names of Varnish services in the same namespace
# to which this config is to be applied.
services
:
-
varnish-ingress
req-disposition
:
-
conditions
:
-
comparand
:
req.http.Host
compare
:
not-exists
-
comparand
:
req.esi_level
count
:
0
-
comparand
:
req.proto
compare
:
prefix
values
:
-
HTTP/1.1
match-flags
:
case-insensitive
:
true
disposition
:
action
:
synth
status
:
400
-
conditions
:
-
comparand
:
req.method
compare
:
not-equal
values
:
-
GET
-
HEAD
-
PUT
-
POST
-
TRACE
-
OPTIONS
-
DELETE
-
PATCH
disposition
:
action
:
synth
status
:
405
-
conditions
:
-
comparand
:
req.method
compare
:
not-equal
values
:
-
GET
-
HEAD
disposition
:
action
:
pass
-
conditions
:
-
comparand
:
req.url
compare
:
match
values
:
-
\.png$
-
\.jpe?g$
-
\.css$
-
\.js$
disposition
:
action
:
hash
-
conditions
:
-
comparand
:
req.url
compare
:
prefix
values
:
-
/interactive/
-
/basket/
-
/personal/
-
/dynamic/
disposition
:
action
:
pass
examples/req-disposition/purge-method.yaml
0 → 100644
View file @
b113c219
# Configuration for disposition of client requests that permits cache
# lookups for requests with Cookie or Authorization headers, and
# allows use of the PURGE request method to purge cache objects.
apiVersion
:
"
ingress.varnish-cache.org/v1alpha1"
kind
:
VarnishConfig
metadata
:
name
:
purge-cfg
spec
:
# The services array is required and must have at least one element.
# Lists the Service names of Varnish services in the same namespace
# to which this config is to be applied.
services
:
-
varnish-ingress
req-disposition
:
-
conditions
:
-
comparand
:
req.http.Host
compare
:
not-exists
-
comparand
:
req.esi_level
count
:
0
-
comparand
:
req.proto
compare
:
prefix
values
:
-
HTTP/1.1
match-flags
:
case-insensitive
:
true
disposition
:
action
:
synth
status
:
400
-
conditions
:
-
comparand
:
req.method
compare
:
equal
values
:
-
PURGE
disposition
:
action
:
purge
-
conditions
:
-
comparand
:
req.method
compare
:
not-equal
values
:
-
GET
-
HEAD
-
PUT
-
POST
-
TRACE
-
OPTIONS
-
DELETE
-
PATCH
disposition
:
action
:
synth
status
:
405
-
conditions
:
-
comparand
:
req.method
compare
:
not-equal
values
:
-
GET
-
HEAD
disposition
:
action
:
pass
examples/req-disposition/url-whitelist.yaml
0 → 100644
View file @
b113c219
# Configuration for disposition of client requests that permits cache
# lookups for requests with Cookie or Authorization headers, and
# defines a whitelist for requests based on URL path prefixes.
apiVersion
:
"
ingress.varnish-cache.org/v1alpha1"
kind
:
VarnishConfig
metadata
:
name
:
url-whitelist-cfg
spec
:
# The services array is required and must have at least one element.
# Lists the Service names of Varnish services in the same namespace
# to which this config is to be applied.
services
:
-
varnish-ingress
req-disposition
:
-
conditions
:
-
comparand
:
req.http.Host
compare
:
not-exists
-
comparand
:
req.esi_level
count
:
0
-
comparand
:
req.proto
compare
:
prefix
values
:
-
HTTP/1.1
match-flags
:
case-insensitive
:
true
disposition
:
action
:
synth
status
:
400
-
conditions
:
-
comparand
:
req.method
compare
:
not-equal
values
:
-
GET
-
HEAD
-
PUT
-
POST
-
TRACE
-
OPTIONS
-
DELETE
-
PATCH
disposition
:
action
:
synth
status
:
405
-
conditions
:
-
comparand
:
req.method
compare
:
not-equal
values
:
-
GET
-
HEAD
disposition
:
action
:
pass
-
conditions
:
-
comparand
:
req.url
compare
:
not-prefix
values
:
-
/tea/
-
/coffee/
disposition
:
action
:
synth
status
:
403
go.mod
View file @
b113c219
...
...
@@ -9,6 +9,7 @@ require (
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
github.com/golang/groupcache v0.0.0-20181024230925-c65c006176ff // indirect
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c // indirect
github.com/google/go-cmp v0.2.0
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf // indirect
github.com/googleapis/gnostic v0.2.0 // indirect
github.com/gregjones/httpcache v0.0.0-20181110185634-c63ab54fda8f // indirect
...
...
go.sum
View file @
b113c219
...
...
@@ -32,6 +32,8 @@ github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c h1:964Od4U6p2jUkFxvCydnIczKteheJEzHRToSGK3Bnlw=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf h1:+RRA9JqSOZFfKrOeqr2z77+8R2RKyh8PG66dcu1V0ck=
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
github.com/googleapis/gnostic v0.2.0 h1:l6N3VoaVzTncYYW+9yOz2LJJammFZGBO13sqgEhpy9g=
...
...
pkg/apis/varnishingress/v1alpha1/types.go
View file @
b113c219
...
...
@@ -49,12 +49,13 @@ type VarnishConfig struct {
// VarnishConfigSpec corresponds to the spec section of a
// VarnishConfig Custom Resource.
type
VarnishConfigSpec
struct
{
Services
[]
string
`json:"services,omitempty"`
SelfSharding
*
SelfShardSpec
`json:"self-sharding,omitempty"`
VCL
string
`json:"vcl,omitempty"`
Auth
[]
AuthSpec
`json:"auth,omitempty"`
ACLs
[]
ACLSpec
`json:"acl,omitempty"`
Rewrites
[]
RewriteSpec
`json:"rewrites,omitempty"`
Services
[]
string
`json:"services,omitempty"`
SelfSharding
*
SelfShardSpec
`json:"self-sharding,omitempty"`
VCL
string
`json:"vcl,omitempty"`
Auth
[]
AuthSpec
`json:"auth,omitempty"`
ACLs
[]
ACLSpec
`json:"acl,omitempty"`
Rewrites
[]
RewriteSpec
`json:"rewrites,omitempty"`
ReqDispositions
[]
RequestDispSpec
`json:"req-disposition,omitempty"`
}
// SelfShardSpec specifies self-sharding in a Varnish cluster.
...
...
@@ -333,6 +334,91 @@ type RewriteSpec struct {
Select
SelectType
`json:"select,omitempty"`
}
// ReqCompareType classifies comparison operations performed for the
// Conditions in a request disposition specification.
type
ReqCompareType
string
const
(
// ReqEqual specifies equality -- string equality, numeric
// equality, or membership in a set of fixed strings.
ReqEqual
ReqCompareType
=
"equal"
// ReqNotEqual specifies non-equality.
ReqNotEqual
=
"not-equal"
// ReqMatch specifies a regular expression match.
ReqMatch
=
"match"
// ReqNotMatch specifies a regular expression non-match.
ReqNotMatch
=
"not-match"
// ReqPrefix specifies that a string has a prefix in a set of
// fixed strings.
ReqPrefix
=
"prefix"
// ReqNotPrefix specifies that a string does not have a prefix
// in a set of fixed strings.
ReqNotPrefix
=
"not-prefix"
// Exists specifies that a request header exists.
Exists
=
"exists"
// NotExists specifies that a request header does not exist.
NotExists
=
"not-exists"
// Greater specifies the > relation between a VCL variable
// with a numeric value and a constant.
Greater
=
"greater"
// GreaterEqual specifies the >= relation for a numeric VCL
// variable and a constant.
GreaterEqual
=
"greater-equal"
// Less specifies the < relation for a numeric VCL variable
// and a constant.
Less
=
"less"
// LessEqual specifies the <= relation for a numeric VCL
// variable and a constant.
LessEqual
=
"less-equal"
)
// ReqCondition specifies (one of) the conditions that must be true if
// a client request disposition is to be executed.
type
ReqCondition
struct
{
Values
[]
string
`json:"values,omitempty"`
MatchFlags
*
MatchFlagsType
`json:"match-flags,omitempty"`
Count
*
int64
`json:"count,omitempty"`
Comparand
string
`json:"comparand"`
Compare
ReqCompareType
`json:"compare,omitempty"`
}
// RecvReturn is a name for the disposition of a client request.
// See: https://varnish-cache.org/docs/6.1/reference/states.html
type
RecvReturn
string
const
(
// RecvHash to invoke cache lookup.
RecvHash
RecvReturn
=
"hash"
// RecvPass to bypass cache lookup.
RecvPass
=
"pass"
// RecvPipe for pipe mode -- Varnish passes data between
// client and backend with no further intervention.
RecvPipe
=
"pipe"
// RecvPurge to purge a cache object.
// See: https://varnish-cache.org/docs/6.1/users-guide/purging.html?highlight=purge#http-purging
RecvPurge
=
"purge"
// RecvSynth to generate a synthetic response with a given
// HTTP response status.
RecvSynth
=
"synth"
)
// DispositionSpec specifies the disposition of a client request when
// associated Conditions are met.
//
// Status is the HTTP response status to set when Action is RecvSynth;
// ignored for other values of Action.
type
DispositionSpec
struct
{
Action
RecvReturn
`json:"action"`
Status
*
int64
`json:"status,omitempty"`
}
// RequestDispSpec specifies the disposition of a client request when
// all of the Conditions are met.
type
RequestDispSpec
struct
{
Conditions
[]
ReqCondition
`json:"conditions"`
Disposition
DispositionSpec
`json:"disposition"`
}
// VarnishConfigStatus is the status for a VarnishConfig resource
// type VarnishConfigStatus struct {
// AvailableReplicas int32 `json:"availableReplicas"`
...
...
pkg/controller/ingress.go
View file @
b113c219
...
...
@@ -594,6 +594,37 @@ func (worker *NamespaceWorker) configACL(spec *vcl.Spec,
return
nil
}
func
configMatchFlags
(
flags
vcr_v1alpha1
.
MatchFlagsType
)
vcl
.
MatchFlagsType
{
vclFlags
:=
vcl
.
MatchFlagsType
{
UTF8
:
flags
.
UTF8
,
PosixSyntax
:
flags
.
PosixSyntax
,
LongestMatch
:
flags
.
LongestMatch
,
Literal
:
flags
.
Literal
,
NeverCapture
:
flags
.
NeverCapture
,
PerlClasses
:
flags
.
PerlClasses
,
WordBoundary
:
flags
.
WordBoundary
,
}
if
flags
.
MaxMem
!=
nil
&&
*
flags
.
MaxMem
!=
0
{
vclFlags
.
MaxMem
=
*
flags
.
MaxMem
}
if
flags
.
CaseSensitive
==
nil
{
vclFlags
.
CaseSensitive
=
true
}
else
{
vclFlags
.
CaseSensitive
=
*
flags
.
CaseSensitive
}
switch
flags
.
Anchor
{
case
vcr_v1alpha1
.
None
:
vclFlags
.
Anchor
=
vcl
.
None
case
vcr_v1alpha1
.
Start
:
vclFlags
.
Anchor
=
vcl
.
Start
case
vcr_v1alpha1
.
Both
:
vclFlags
.
Anchor
=
vcl
.
Both
default
:
vclFlags
.
Anchor
=
vcl
.
None
}
return
vclFlags
}
func
(
worker
*
NamespaceWorker
)
configRewrites
(
spec
*
vcl
.
Spec
,
vcfg
*
vcr_v1alpha1
.
VarnishConfig
)
error
{
...
...
@@ -715,40 +746,95 @@ func (worker *NamespaceWorker) configRewrites(spec *vcl.Spec,
}
if
rw
.
MatchFlags
!=
nil
{
vclRw
.
MatchFlags
=
vcl
.
MatchFlagsType
{
UTF8
:
rw
.
MatchFlags
.
UTF8
,
PosixSyntax
:
rw
.
MatchFlags
.
PosixSyntax
,
LongestMatch
:
rw
.
MatchFlags
.
LongestMatch
,
Literal
:
rw
.
MatchFlags
.
Literal
,
NeverCapture
:
rw
.
MatchFlags
.
NeverCapture
,
PerlClasses
:
rw
.
MatchFlags
.
PerlClasses
,
WordBoundary
:
rw
.
MatchFlags
.
WordBoundary
,
}
if
rw
.
MatchFlags
.
MaxMem
!=
nil
&&
*
rw
.
MatchFlags
.
MaxMem
!=
0
{
vclRw
.
MatchFlags
=
configMatchFlags
(
*
rw
.
MatchFlags
)
}
else
{
vclRw
.
MatchFlags
.
CaseSensitive
=
true
}
spec
.
Rewrites
[
i
]
=
vclRw
}
return
nil
}
vclRw
.
MatchFlags
.
MaxMem
=
*
rw
.
MatchFlags
.
MaxMem
func
(
worker
*
NamespaceWorker
)
configReqDisps
(
spec
*
vcl
.
Spec
,
reqDisps
[]
vcr_v1alpha1
.
RequestDispSpec
,
kind
,
namespace
,
name
string
)
{
if
len
(
reqDisps
)
==
0
{
worker
.
log
.
Infof
(
"No request disposition specs found for %s "
+
"%s/%s"
,
kind
,
namespace
,
name
)
return
}
worker
.
log
.
Infof
(
"Configuring request dispositions for %s %s/%s"
,
kind
,
namespace
,
name
)
spec
.
Dispositions
=
make
([]
vcl
.
DispositionSpec
,
len
(
reqDisps
))
for
i
,
disp
:=
range
reqDisps
{
worker
.
log
.
Tracef
(
"ReqDisposition: %+v"
,
disp
)
vclDisp
:=
vcl
.
DispositionSpec
{
Conditions
:
make
([]
vcl
.
Condition
,
len
(
disp
.
Conditions
)),
}
for
j
,
cond
:=
range
disp
.
Conditions
{
vclCond
:=
vcl
.
Condition
{
Comparand
:
cond
.
Comparand
,
}
if
rw
.
MatchFlags
.
CaseSensitive
==
nil
{
vclRw
.
MatchFlags
.
CaseSensitive
=
true
}
else
{
vclRw
.
MatchFlags
.
CaseSensitive
=
*
rw
.
MatchFlags
.
CaseSensitive
if
len
(
cond
.
Values
)
>
0
{
vclCond
.
Values
=
make
([]
string
,
len
(
cond
.
Values
))
copy
(
vclCond
.
Values
,
cond
.
Values
)
}
if
cond
.
Count
!=
nil
{
count
:=
uint
(
*
cond
.
Count
)
vclCond
.
Count
=
&
count
}
switch
rw
.
MatchFlags
.
Anchor
{
case
vcr_v1alpha1
.
None
:
vclRw
.
MatchFlags
.
Anchor
=
vcl
.
None
case
vcr_v1alpha1
.
Start
:
vclRw
.
MatchFlags
.
Anchor
=
vcl
.
Start
case
vcr_v1alpha1
.
Both
:
vclRw
.
MatchFlags
.
Anchor
=
vcl
.
Both
switch
cond
.
Compare
{
case
vcr_v1alpha1
.
ReqEqual
:
vclCond
.
Compare
=
vcl
.
ReqEqual
vclCond
.
Negate
=
false
case
vcr_v1alpha1
.
ReqNotEqual
:
vclCond
.
Compare
=
vcl
.
ReqEqual
vclCond
.
Negate
=
true
case
vcr_v1alpha1
.
ReqMatch
:
vclCond
.
Compare
=
vcl
.
ReqMatch
vclCond
.
Negate
=
false
case
vcr_v1alpha1
.
ReqNotMatch
:
vclCond
.
Compare
=
vcl
.
ReqMatch
vclCond
.
Negate
=
true
case
vcr_v1alpha1
.
ReqPrefix
:
vclCond
.
Compare
=
vcl
.
ReqPrefix
vclCond
.
Negate
=
false
case
vcr_v1alpha1
.
ReqNotPrefix
:
vclCond
.
Compare
=
vcl
.
ReqPrefix
vclCond
.
Negate
=
true
case
vcr_v1alpha1
.
Exists
:
vclCond
.
Compare
=
vcl
.
Exists
vclCond
.
Negate
=
false
case
vcr_v1alpha1
.
NotExists
:
vclCond
.
Compare
=
vcl
.
Exists
vclCond
.
Negate
=
true
case
vcr_v1alpha1
.
Greater
:
vclCond
.
Compare
=
vcl
.
Greater
case
vcr_v1alpha1
.
GreaterEqual
:
vclCond
.
Compare
=
vcl
.
GreaterEqual
case
vcr_v1alpha1
.
Less
:
vclCond
.
Compare
=
vcl
.
Less
case
vcr_v1alpha1
.
LessEqual
:
vclCond
.
Compare
=
vcl
.
LessEqual
default
:
vcl
Rw
.
MatchFlags
.
Anchor
=
vcl
.
None
vcl
Cond
.
Compare
=
vcl
.
ReqEqual
}
if
cond
.
MatchFlags
!=
nil
{
vclCond
.
MatchFlags
=
configMatchFlags
(
*
cond
.
MatchFlags
)
}
else
{
vclCond
.
MatchFlags
.
CaseSensitive
=
true
}
vclDisp
.
Conditions
[
j
]
=
vclCond
}
spec
.
Rewrites
[
i
]
=
vclRw
vclDisp
.
Disposition
.
Action
=
vcl
.
RecvReturn
(
disp
.
Disposition
.
Action
)
if
disp
.
Disposition
.
Action
==
vcr_v1alpha1
.
RecvSynth
{
vclDisp
.
Disposition
.
Status
=
uint16
(
*
disp
.
Disposition
.
Status
)
}
spec
.
Dispositions
[
i
]
=
vclDisp
}
return
nil
}
func
(
worker
*
NamespaceWorker
)
addOrUpdateIng
(
ing
*
extensions
.
Ingress
)
error
{
...
...
@@ -823,6 +909,8 @@ func (worker *NamespaceWorker) addOrUpdateIng(ing *extensions.Ingress) error {
if
err
=
worker
.
configRewrites
(
&
vclSpec
,
vcfg
);
err
!=
nil
{
return
err
}
worker
.
configReqDisps
(
&
vclSpec
,
vcfg
.
Spec
.
ReqDispositions
,
vcfg
.
Kind
,
vcfg
.
Namespace
,
vcfg
.
Name
)
vclSpec
.
VCL
=
vcfg
.
Spec
.
VCL
}
else
{
worker
.
log
.
Infof
(
"Found no VarnishConfigs for Varnish Service "
+
...
...
pkg/controller/ingress_test.go
View file @
b113c219
This diff is collapsed.
Click to expand it.
pkg/controller/varnishconfig.go
View file @
b113c219
...
...
@@ -161,6 +161,77 @@ func validateRewrites(rewrites []vcr_v1alpha1.RewriteSpec) error {
return
nil
}
// XXX validating webhook should do this
func
validateReqDisps
(
reqDisps
[]
vcr_v1alpha1
.
RequestDispSpec
)
error
{
for
_
,
disp
:=
range
reqDisps
{
if
disp
.
Disposition
.
Action
==
vcr_v1alpha1
.
RecvSynth
&&
disp
.
Disposition
.
Status
==
nil
{
return
fmt
.
Errorf
(
"status not set for request "
+
"disposition synth"
)
}
for
_
,
cond
:=
range
disp
.
Conditions
{
if
len
(
cond
.
Values
)
==
0
&&
cond
.
Count
==
nil
&&
cond
.
Compare
!=
vcr_v1alpha1
.
Exists
&&
cond
.
Compare
!=
vcr_v1alpha1
.
NotExists
{
return
fmt
.
Errorf
(
"no values or count set for "
+
"request disposition condition "
+
"(comparand %s)"
,
cond
.
Comparand
)
}
if
len
(
cond
.
Values
)
!=
0
&&
cond
.
Count
!=
nil
{
return
fmt
.
Errorf
(
"both values and count set "
+
"for request disposition condition "
+
"(comparand %s)"
,
cond
.
Comparand
)
}
if
len
(
cond
.
Values
)
>
0
{
switch
cond
.
Compare
{
case
vcr_v1alpha1
.
Greater
,
vcr_v1alpha1
.
GreaterEqual
,
vcr_v1alpha1
.
Less
,
vcr_v1alpha1
.
LessEqual
:
return
fmt
.
Errorf
(
"illegal compare "
+
"(comparand %s, compare %s)"
,
cond
.
Comparand
,
cond
.
Compare
)
}
switch
cond
.
Comparand
{
case
"req.esi_level"
,
"req.restarts"
:
return
fmt
.
Errorf
(
"illegal comparison "
+
"(comparand %s, values %v)"
,
cond
.
Comparand
,
cond
.
Values
)
}
}
if
cond
.
Count
!=
nil
{
switch
cond
.
Compare
{
case
vcr_v1alpha1
.
ReqMatch
,
vcr_v1alpha1
.
ReqNotMatch
,
vcr_v1alpha1
.
ReqPrefix
,
vcr_v1alpha1
.
ReqNotPrefix
,
vcr_v1alpha1
.
Exists
,
vcr_v1alpha1
.
NotExists
:
return
fmt
.
Errorf
(
"illegal compare "
+
"(compare %s, count %d)"
,
cond
.
Compare
,
*
cond
.
Count
)
}
err
:=
false
switch
cond
.
Comparand
{
case
"req.url"
,
"req.method"
,
"req.proto"
:
err
=
true
}
if
strings
.
HasPrefix
(
cond
.
Comparand
,
"req.http"
)
{
err
=
true
}
if
err
{
return
fmt
.
Errorf
(
"illegal comparison "
+
"(comparand %s, count %d)"
,
cond
.
Comparand
,
*
cond
.
Count
)
}
}
}
}
return
nil
}
func
(
worker
*
NamespaceWorker
)
syncVcfg
(
key
string
)
error
{
worker
.
log
.
Infof
(
"Syncing VarnishConfig: %s/%s"
,
worker
.
namespace
,
key
)
vcfg
,
err
:=
worker
.
vcfg
.
Get
(
key
)
...
...
@@ -189,6 +260,9 @@ func (worker *NamespaceWorker) syncVcfg(key string) error {
if
err
=
validateRewrites
(
vcfg
.
Spec
.
Rewrites
);
err
!=
nil
{
return
err
}
if
err
=
validateReqDisps
(
vcfg
.
Spec
.
ReqDispositions
);
err
!=
nil
{
return
err
}
return
worker
.
enqueueIngsForVcfg
(
vcfg
)
}
...
...
pkg/controller/varnishconfig_test.go
0 → 100644
View file @
b113c219
/*
* Copyright (c) 2019 UPLEX Nils Goroll Systemoptimierung
* All rights reserved
*
* Author: Geoffrey Simmons <geoffrey.simmons@uplex.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
package
controller
import
(
"testing"
vcr_v1alpha1
"code.uplex.de/uplex-varnish/k8s-ingress/pkg/apis/varnishingress/v1alpha1"
)
func
TestValidateReqDisps
(
t
*
testing
.
T
)
{
zero
:=
int64
(
0
)
badDispSlice
:=
[][]
vcr_v1alpha1
.
RequestDispSpec
{
{{
Disposition
:
vcr_v1alpha1
.
DispositionSpec
{
Action
:
vcr_v1alpha1
.
RecvSynth
,
},
}},
{{
Disposition
:
vcr_v1alpha1
.
DispositionSpec
{
Action
:
vcr_v1alpha1
.
RecvHash
,
},
Conditions
:
[]
vcr_v1alpha1
.
ReqCondition
{{
Comparand
:
"req.url"
,
Compare
:
vcr_v1alpha1
.
ReqEqual
,
}},
}},
{{
Disposition
:
vcr_v1alpha1
.
DispositionSpec
{
Action
:
vcr_v1alpha1
.
RecvHash
,
},
Conditions
:
[]
vcr_v1alpha1
.
ReqCondition
{{
Comparand
:
"req.url"
,
Compare
:
vcr_v1alpha1
.
ReqEqual
,
Count
:
&
zero
,
Values
:
[]
string
{
"/foo"
},
}},
}},
{{
Disposition
:
vcr_v1alpha1
.
DispositionSpec
{
Action
:
vcr_v1alpha1
.
RecvHash
,
},
Conditions
:
[]
vcr_v1alpha1
.
ReqCondition
{{
Comparand
:
"req.url"
,
Compare
:
vcr_v1alpha1
.
NotExists
,
Count
:
&
zero
,
}},
}},
{{
Disposition
:
vcr_v1alpha1
.
DispositionSpec
{
Action
:
vcr_v1alpha1
.
RecvHash
,
},
Conditions
:
[]
vcr_v1alpha1
.
ReqCondition
{{
Comparand
:
"req.url"
,
Compare
:
vcr_v1alpha1
.
LessEqual
,
Values
:
[]
string
{
"/foo"
},
}},
}},
{{
Disposition
:
vcr_v1alpha1
.
DispositionSpec
{
Action
:
vcr_v1alpha1
.
RecvHash
,
},
Conditions
:
[]
vcr_v1alpha1
.
ReqCondition
{{
Comparand
:
"req.url"
,
Compare
:
vcr_v1alpha1
.
ReqEqual
,
Count
:
&
zero
,
}},
}},
{{
Disposition
:
vcr_v1alpha1
.
DispositionSpec
{
Action
:
vcr_v1alpha1
.
RecvHash
,
},
Conditions
:
[]
vcr_v1alpha1
.
ReqCondition
{{
Comparand
:
"req.http.Host"
,
Compare
:
vcr_v1alpha1
.
ReqEqual
,
Count
:
&
zero
,
}},
}},
{{
Disposition
:
vcr_v1alpha1
.
DispositionSpec
{
Action
:
vcr_v1alpha1
.
RecvHash
,
},
Conditions
:
[]
vcr_v1alpha1
.
ReqCondition
{{
Comparand
:
"req.restarts"
,
Compare
:
vcr_v1alpha1
.
ReqEqual
,
Values
:
[]
string
{
"/foo"
},
}},
}},
}
goodDispSlice
:=
[][]
vcr_v1alpha1
.
RequestDispSpec
{
{{
Disposition
:
vcr_v1alpha1
.
DispositionSpec
{
Action
:
vcr_v1alpha1
.
RecvPass
,
},
Conditions
:
[]
vcr_v1alpha1
.
ReqCondition
{{
Comparand
:
"req.http.Host"
,
Compare
:
vcr_v1alpha1
.
NotExists
,
}},
}},
{{
Disposition
:
vcr_v1alpha1
.
DispositionSpec
{
Action
:
vcr_v1alpha1
.
RecvPass
,
},
Conditions
:
[]
vcr_v1alpha1
.
ReqCondition
{{
Comparand
:
"req.http.Cookie"
,
Compare
:
vcr_v1alpha1
.
Exists
,
}},
}},
}
for
_
,
disps
:=
range
badDispSlice
{
if
err
:=
validateReqDisps
(
disps
);
err
==
nil
{
t
.
Errorf
(
"validateReqDisps(%+v) expected error got=nil"
,
disps
)
}
else
if
testing
.
Verbose
()
{
t
.
Logf
(
"validateReqDisps(%+v) returned as expected: %v"
,
disps
,
err
)
}
}
for
_
,
disps
:=
range
goodDispSlice
{
if
err
:=
validateReqDisps
(
disps
);
err
!=
nil
{
t
.
Errorf
(
"validateReqDisps(%+v) expected no error "
+
"got='%+v'"
,
disps
,
err
)
}
}
}
pkg/varnish/vcl/recv_disposition.tmpl
0 → 100644
View file @
b113c219
import re2;
import selector;
{{range $didx, $d := .Dispositions -}}
{{range $cidx, $c := .Conditions -}}
{{if reqNeedsMatcher $c -}}
sub vcl_init {
new {{reqObj $didx $cidx}} = {{reqVMOD $c}}.set({{reqFlags $c}});
{{- range $val := $c.Values}}
{{reqObj $didx $cidx}}.add("{{$val}}");
{{- end}}
{{- if reqNeedsCompile $c}}
{{reqObj $didx $cidx}}.compile();
{{- end}}
}
{{end -}}
{{- end}}
{{- end}}
sub vcl_recv {
{{- range $didx, $d := .Dispositions}}
if (
{{- range $cidx, $cond := .Conditions}}
{{- if ne $cidx 0}} &&
{{end}}
{{- if $cond.Negate}}! {{end}}
{{- if reqNeedsMatcher $cond}}
{{- reqObj $didx $cidx}}.{{reqMatch $cond}}({{$cond.Comparand}})
{{- else if exists $cond.Compare}}
{{- $cond.Comparand}}
{{- else}}
{{- $cond.Comparand}} {{reqCmpRelation $cond}} {{value $cond}}
{{- end}}
{{- end -}}
) {
return (
{{- with .Disposition}}
{{- if eq .Action "synth"}}synth({{.Status}})
{{- else}}{{.Action}}
{{- end}}
{{- end -}}
);
}
{{- end}}
return (hash);
}
pkg/varnish/vcl/recv_disposition_test.go
0 → 100644
View file @
b113c219
/*
* Copyright (c) 2019 UPLEX Nils Goroll Systemoptimierung
* All rights reserved
*
* Author: Geoffrey Simmons <geoffrey.simmons@uplex.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
package
vcl
import
"testing"
var
zero
uint
var
builtinRecvSpec
=
Spec
{
Dispositions
:
[]
DispositionSpec
{
{
Conditions
:
[]
Condition
{{
Comparand
:
"req.method"
,
Compare
:
ReqEqual
,
Values
:
[]
string
{
"PRI"
},
}},
Disposition
:
DispositionType
{
Action
:
RecvSynth
,
Status
:
405
,
},
},
{
Conditions
:
[]
Condition
{
{
Comparand
:
"req.http.Host"
,
Compare
:
Exists
,
Negate
:
true
,
},
{
Comparand
:
"req.esi_level"
,
Compare
:
ReqEqual
,
Count
:
&
zero
,
},
{
Comparand
:
"req.proto"
,
Compare
:
ReqPrefix
,
Values
:
[]
string
{
"HTTP/1.1"
},
MatchFlags
:
MatchFlagsType
{
CaseSensitive
:
false
,
},
},
},
Disposition
:
DispositionType
{
Action
:
RecvSynth
,
Status
:
400
,
},
},
{
Conditions
:
[]
Condition
{{
Comparand
:
"req.method"
,
Compare
:
ReqEqual
,
Negate
:
true
,
Values
:
[]
string
{
"GET"
,
"HEAD"
,
"PUT"
,
"POST"
,
"TRACE"
,
"OPTIONS"
,
"DELETE"
,
},
MatchFlags
:
MatchFlagsType
{
CaseSensitive
:
true
,
},
}},
Disposition
:
DispositionType
{
Action
:
RecvPipe
,
},
},
{
Conditions
:
[]
Condition
{{
Comparand
:
"req.method"
,
Compare
:
ReqEqual
,
Negate
:
true
,
Values
:
[]
string
{
"GET"
,
"HEAD"
,
},
MatchFlags
:
MatchFlagsType
{
CaseSensitive
:
true
,
},
}},
Disposition
:
DispositionType
{
Action
:
RecvPass
,
},
},
{
Conditions
:
[]
Condition
{{
Comparand
:
"req.http.Cookie"
,
Compare
:
Exists
,
}},
Disposition
:
DispositionType
{
Action
:
RecvPass
,
},
},
{
Conditions
:
[]
Condition
{{
Comparand
:
"req.http.Authorization"
,
Compare
:
Exists
,
}},
Disposition
:
DispositionType
{
Action
:
RecvPass
,
},
},
},
}
func
TestReqDispBuiltinRecv
(
t
*
testing
.
T
)
{
gold
:=
"recv_disp_builtin.golden"
testTemplate
(
t
,
reqDispTmpl
,
builtinRecvSpec
,
gold
)
}
var
pipeOnConnectSpec
=
Spec
{
Dispositions
:
[]
DispositionSpec
{{
Conditions
:
[]
Condition
{{
Comparand
:
"req.method"
,
Compare
:
ReqEqual
,
Values
:
[]
string
{
"CONNECT"
},
}},
Disposition
:
DispositionType
{
Action
:
RecvPipe
,
},
}},
}
func
TestReqDispPipeOnConnect
(
t
*
testing
.
T
)
{
gold
:=
"recv_disp_pipe_on_connect.golden"
testTemplate
(
t
,
reqDispTmpl
,
pipeOnConnectSpec
,
gold
)
}
var
methodNotAllowedSpec
=
Spec
{
Dispositions
:
[]
DispositionSpec
{{
Conditions
:
[]
Condition
{{
Comparand
:
"req.method"
,
Compare
:
ReqEqual
,
Negate
:
true
,
Values
:
[]
string
{
"GET"
,
"HEAD"
,
"PUT"
,
"POST"
,
"TRACE"
,
"OPTIONS"
,
"DELETE"
,
},
MatchFlags
:
MatchFlagsType
{
CaseSensitive
:
true
,
},
}},
Disposition
:
DispositionType
{
Action
:
RecvSynth
,
Status
:
405
,
},
}},
}
func
TestReqDispMethodNotAllowed
(
t
*
testing
.
T
)
{
gold
:=
"recv_disp_method_not_allowed.golden"
testTemplate
(
t
,
reqDispTmpl
,
methodNotAllowedSpec
,
gold
)
}
var
urlWhitelistSpec
=
Spec
{
Dispositions
:
[]
DispositionSpec
{{
Conditions
:
[]
Condition
{{
Comparand
:
"req.url"
,
Compare
:
ReqPrefix
,
Negate
:
true
,
Values
:
[]
string
{
"/foo"
,
"/bar"
,
"/baz"
,
"/quux"
,
},
MatchFlags
:
MatchFlagsType
{
CaseSensitive
:
true
,
},
}},
Disposition
:
DispositionType
{
Action
:
RecvSynth
,
Status
:
403
,
},
}},
}
func
TestReqDispURLWhitelist
(
t
*
testing
.
T
)
{
gold
:=
"recv_disp_url_whitelist.golden"
testTemplate
(
t
,
reqDispTmpl
,
urlWhitelistSpec
,
gold
)
}
var
purgeMethodSpec
=
Spec
{
Dispositions
:
[]
DispositionSpec
{{
Conditions
:
[]
Condition
{{
Comparand
:
"req.method"
,
Compare
:
ReqEqual
,
Values
:
[]
string
{
"PURGE"
},
}},
Disposition
:
DispositionType
{
Action
:
RecvPurge
,
},
}},
}
func
TestReqDispPurgeMethod
(
t
*
testing
.
T
)
{
gold
:=
"recv_disp_purge_method.golden"
testTemplate
(
t
,
reqDispTmpl
,
purgeMethodSpec
,
gold
)
}
var
cacheableSpec
=
Spec
{
Dispositions
:
[]
DispositionSpec
{{
Conditions
:
[]
Condition
{{
Comparand
:
"req.url"
,
Compare
:
ReqMatch
,
Values
:
[]
string
{
`\.png$`
,
`\.jpe?g$`
,
`\.css$`
,
`\.js$`
,
},
MatchFlags
:
MatchFlagsType
{
CaseSensitive
:
true
,
},
}},
Disposition
:
DispositionType
{
Action
:
RecvHash
,
},
}},
}
func
TestReqDispCacheable
(
t
*
testing
.
T
)
{
gold
:=
"recv_disp_cacheable.golden"
testTemplate
(
t
,
reqDispTmpl
,
cacheableSpec
,
gold
)
}
var
nonCacheableSpec
=
Spec
{
Dispositions
:
[]
DispositionSpec
{{
Conditions
:
[]
Condition
{{
Comparand
:
"req.url"
,
Compare
:
ReqPrefix
,
Values
:
[]
string
{
"/interactive/"
,
"/basket/"
,
"/personal"
,
"/dynamic/"
,
},
MatchFlags
:
MatchFlagsType
{
CaseSensitive
:
true
,
},
}},
Disposition
:
DispositionType
{
Action
:
RecvPass
,
},
}},
}
func
TestReqDispNonCacheable
(
t
*
testing
.
T
)
{
gold
:=
"recv_disp_non_cacheable.golden"
testTemplate
(
t
,
reqDispTmpl
,
nonCacheableSpec
,
gold
)
}
// Code boilerplate for writing the golden file.
// import ioutils
// func TestRewriteXXX(t *testing.T) {
// gold := "rewrite_XXX.golden"
// var buf bytes.Buffer
// if err := rewriteTmpl.Execute(&buf, spec); err != nil {
// t.Fatal("Execute():", err)
// }
// if err := ioutil.WriteFile("testdata/"+gold, buf.Bytes(), 0644); err != nil {
// t.Fatal("WriteFile():", err)
// }
// if testing.Verbose() {
// t.Logf("Generated: %s", buf.String())
// }
// }
pkg/varnish/vcl/rewrite_test.go
View file @
b113c219
...
...
@@ -32,12 +32,13 @@ import (
"bytes"
"io/ioutil"
"testing"
"text/template"
)
func
testTemplate
(
t
*
testing
.
T
,
spec
Spec
,
gold
string
)
{
func
testTemplate
(
t
*
testing
.
T
,
tmpl
*
template
.
Template
,
spec
Spec
,
gold
string
)
{
var
buf
bytes
.
Buffer
if
err
:=
rewriteT
mpl
.
Execute
(
&
buf
,
spec
);
err
!=
nil
{
if
err
:=
t
mpl
.
Execute
(
&
buf
,
spec
);
err
!=
nil
{
t
.
Fatal
(
"Execute():"
,
err
)
}
...
...
@@ -68,7 +69,7 @@ var replaceFromStringTest = Spec{
func
TestReplaceFromString
(
t
*
testing
.
T
)
{
gold
:=
"rewrite_replace_from_string.golden"
testTemplate
(
t
,
replaceFromStringTest
,
gold
)
testTemplate
(
t
,
re
writeTmpl
,
re
placeFromStringTest
,
gold
)
}
var
replaceFromSourceTest
=
Spec
{
...
...
@@ -84,7 +85,7 @@ var replaceFromSourceTest = Spec{
func
TestReplaceFromSource
(
t
*
testing
.
T
)
{
gold
:=
"rewrite_replace_from_source.golden"
testTemplate
(
t
,
replaceFromSourceTest
,
gold
)
testTemplate
(
t
,
re
writeTmpl
,
re
placeFromSourceTest
,
gold
)
}
var
replaceFromRewriteTest
=
Spec
{
...
...
@@ -111,7 +112,7 @@ var replaceFromRewriteTest = Spec{
func
TestReplaceFromRewrite
(
t
*
testing
.
T
)
{
gold
:=
"rewrite_replace_from_rewrite.golden"
testTemplate
(
t
,
replaceFromRewriteTest
,
gold
)
testTemplate
(
t
,
re
writeTmpl
,
re
placeFromRewriteTest
,
gold
)
}
var
rewriteSubTest
=
Spec
{
...
...
@@ -139,7 +140,7 @@ var rewriteSubTest = Spec{
func
TestRewriteSub
(
t
*
testing
.
T
)
{
gold
:=
"rewrite_sub.golden"
testTemplate
(
t
,
rewriteSubTest
,
gold
)
testTemplate
(
t
,
rewrite
Tmpl
,
rewrite
SubTest
,
gold
)
}
var
rewriteAppendTest
=
Spec
{
...
...
@@ -158,7 +159,7 @@ var rewriteAppendTest = Spec{
func
TestRewriteAppend
(
t
*
testing
.
T
)
{
gold
:=
"rewrite_append.golden"
testTemplate
(
t
,
rewriteAppendTest
,
gold
)
testTemplate
(
t
,
rewrite
Tmpl
,
rewrite
AppendTest
,
gold
)
}
var
rewritePrependTest
=
Spec
{
...
...
@@ -177,7 +178,7 @@ var rewritePrependTest = Spec{
func
TestRewritePrepend
(
t
*
testing
.
T
)
{
gold
:=
"rewrite_prepend.golden"
testTemplate
(
t
,
rewritePrependTest
,
gold
)
testTemplate
(
t
,
rewrite
Tmpl
,
rewrite
PrependTest
,
gold
)
}
var
rewriteDeleteTest
=
Spec
{
...
...
@@ -193,7 +194,7 @@ var rewriteDeleteTest = Spec{
func
TestRewriteDelete
(
t
*
testing
.
T
)
{
gold
:=
"rewrite_delete.golden"
testTemplate
(
t
,
rewriteDeleteTest
,
gold
)
testTemplate
(
t
,
rewrite
Tmpl
,
rewrite
DeleteTest
,
gold
)
}
var
conditionalDeleteTest
=
Spec
{
...
...
@@ -216,7 +217,7 @@ var conditionalDeleteTest = Spec{
func
TestConditionalDelete
(
t
*
testing
.
T
)
{
gold
:=
"rewrite_conditional_delete.golden"
testTemplate
(
t
,
conditionalDeleteTest
,
gold
)
testTemplate
(
t
,
rewriteTmpl
,
conditionalDeleteTest
,
gold
)
}
var
rewriteExtractTest
=
Spec
{
...
...
@@ -237,7 +238,7 @@ var rewriteExtractTest = Spec{
func
TestRewriteExtract
(
t
*
testing
.
T
)
{
gold
:=
"rewrite_extract.golden"
testTemplate
(
t
,
rewriteExtractTest
,
gold
)
testTemplate
(
t
,
rewrite
Tmpl
,
rewrite
ExtractTest
,
gold
)
}
var
rewriteFixedPrefixTest
=
Spec
{
...
...
@@ -264,7 +265,7 @@ var rewriteFixedPrefixTest = Spec{
func
TestRewriteFixedPrefix
(
t
*
testing
.
T
)
{
gold
:=
"rewrite_fixed_prefix.golden"
testTemplate
(
t
,
rewriteFixedPrefixTest
,
gold
)
testTemplate
(
t
,
rewrite
Tmpl
,
rewrite
FixedPrefixTest
,
gold
)
}
var
rewriteFixedEqualTest
=
Spec
{
...
...
@@ -291,7 +292,7 @@ var rewriteFixedEqualTest = Spec{
func
TestRewriteFixedEqual
(
t
*
testing
.
T
)
{
gold
:=
"rewrite_fixed_equal.golden"
testTemplate
(
t
,
rewriteFixedEqualTest
,
gold
)
testTemplate
(
t
,
rewrite
Tmpl
,
rewrite
FixedEqualTest
,
gold
)
}
var
rewriteFixedSuballTest
=
Spec
{
...
...
@@ -318,7 +319,7 @@ var rewriteFixedSuballTest = Spec{
func
TestRewriteFixedSuball
(
t
*
testing
.
T
)
{
gold
:=
"rewrite_fixed_suball.golden"
testTemplate
(
t
,
rewriteFixedSuballTest
,
gold
)
testTemplate
(
t
,
rewrite
Tmpl
,
rewrite
FixedSuballTest
,
gold
)
}
var
rewritePrefixRegex
=
Spec
{
...
...
@@ -347,7 +348,7 @@ var rewritePrefixRegex = Spec{
func
TestRewritePrefixRegex
(
t
*
testing
.
T
)
{
gold
:=
"rewrite_prefix_regex.golden"
testTemplate
(
t
,
rewritePrefixRegex
,
gold
)
testTemplate
(
t
,
rewrite
Tmpl
,
rewrite
PrefixRegex
,
gold
)
}
var
rewritePrependIfExists
=
Spec
{
...
...
@@ -370,7 +371,7 @@ var rewritePrependIfExists = Spec{
func
TestRewritePrependIfExists
(
t
*
testing
.
T
)
{
gold
:=
"rewrite_prepend_if_exists.golden"
testTemplate
(
t
,
rewritePrependIfExists
,
gold
)
testTemplate
(
t
,
rewrite
Tmpl
,
rewrite
PrependIfExists
,
gold
)
}
var
rewriteExtractCookie
=
Spec
{
...
...
@@ -391,7 +392,7 @@ var rewriteExtractCookie = Spec{
func
TestExtractCookie
(
t
*
testing
.
T
)
{
gold
:=
"rewrite_extract_cookie.golden"
testTemplate
(
t
,
rewriteExtractCookie
,
gold
)
testTemplate
(
t
,
rewrite
Tmpl
,
rewrite
ExtractCookie
,
gold
)
}
var
rewriteXCacheHdr
=
Spec
{
...
...
@@ -442,7 +443,7 @@ var rewriteXCacheHdr = Spec{
func
TestXCacheHdr
(
t
*
testing
.
T
)
{
gold
:=
"rewrite_x_cache_hdr.golden"
testTemplate
(
t
,
rewriteXCacheHdr
,
gold
)
testTemplate
(
t
,
rewrite
Tmpl
,
rewrite
XCacheHdr
,
gold
)
}
var
rewriteAppendFromSrcTest
=
Spec
{
...
...
@@ -455,7 +456,7 @@ var rewriteAppendFromSrcTest = Spec{
func
TestRewriteAppendFromSrcTest
(
t
*
testing
.
T
)
{
gold
:=
"rewrite_append_from_src.golden"
testTemplate
(
t
,
rewriteAppendFromSrcTest
,
gold
)
testTemplate
(
t
,
rewrite
Tmpl
,
rewrite
AppendFromSrcTest
,
gold
)
}
var
rewriteAppendRule
=
Spec
{
...
...
@@ -475,7 +476,7 @@ var rewriteAppendRule = Spec{
func
TestRewriteAppendRule
(
t
*
testing
.
T
)
{
gold
:=
"rewrite_append_rule.golden"
testTemplate
(
t
,
rewriteAppendRule
,
gold
)
testTemplate
(
t
,
rewrite
Tmpl
,
rewrite
AppendRule
,
gold
)
}
var
rewritePrependHdr
=
Spec
{
...
...
@@ -491,7 +492,7 @@ var rewritePrependHdr = Spec{
func
TestRewritePrependHdr
(
t
*
testing
.
T
)
{
gold
:=
"rewrite_prepend_hdr.golden"
testTemplate
(
t
,
rewritePrependHdr
,
gold
)
testTemplate
(
t
,
rewrite
Tmpl
,
rewrite
PrependHdr
,
gold
)
}
var
rewriteSelectFirst
=
Spec
{
...
...
@@ -526,7 +527,7 @@ var rewriteSelectFirst = Spec{
func
TestRewriteSelectFirst
(
t
*
testing
.
T
)
{
gold
:=
"rewrite_select_first.golden"
testTemplate
(
t
,
rewriteSelectFirst
,
gold
)
testTemplate
(
t
,
rewrite
Tmpl
,
rewrite
SelectFirst
,
gold
)
}
var
rewriteSelectPermutations
=
Spec
{
...
...
@@ -614,7 +615,7 @@ var rewriteSelectPermutations = Spec{
func
TestRewriteSelectPermutations
(
t
*
testing
.
T
)
{
gold
:=
"rewrite_select_permute.golden"
testTemplate
(
t
,
rewriteSelectPermutations
,
gold
)
testTemplate
(
t
,
rewrite
Tmpl
,
rewrite
SelectPermutations
,
gold
)
}
var
rewriteSelectOperations
=
Spec
{
...
...
@@ -691,7 +692,7 @@ var rewriteSelectOperations = Spec{
func
TestRewriteSelectOperations
(
t
*
testing
.
T
)
{
gold
:=
"rewrite_select_ops.golden"
testTemplate
(
t
,
rewriteSelectOperations
,
gold
)
testTemplate
(
t
,
rewrite
Tmpl
,
rewrite
SelectOperations
,
gold
)
}
// Test the use case that Auth should be executed, but the
...
...
pkg/varnish/vcl/spec.go
View file @
b113c219
...
...
@@ -651,6 +651,113 @@ func (a byVCLSub) Len() int { return len(a) }
func
(
a
byVCLSub
)
Swap
(
i
,
j
int
)
{
a
[
i
],
a
[
j
]
=
a
[
j
],
a
[
i
]
}
func
(
a
byVCLSub
)
Less
(
i
,
j
int
)
bool
{
return
a
[
i
]
.
VCLSub
<
a
[
j
]
.
VCLSub
}
// ReqCompareType classifies comparison operations performed for the
// Conditions in a request disposition specification. The relation may
// be negated, if the Negate field in Condition is true.
type
ReqCompareType
uint8
const
(
// ReqEqual specifies equality -- string equality, numeric
// equality, or membership in a set of fixed strings.
ReqEqual
ReqCompareType
=
iota
// ReqMatch specifies a regular expression match.
ReqMatch
// ReqPrefix specifies that a string has a prefix in a set of
// fixed strings.
ReqPrefix
// Exists specifies that a request header exists.
Exists
// Greater specifies the > relation between a VCL variable
// with a numeric value and a constant.
Greater
// GreaterEqual specifies the >= relation for a numeric VCL
// variable and a constant.
GreaterEqual
// Less specifies the < relation for a numeric VCL variable
// and a constant.
Less
// LessEqual specifies the <= relation for a numeric VCL
// variable and a constant.
LessEqual
)
// Condition specifies (one of) the conditions that must be true if a
// client request disposition is to be executed.
type
Condition
struct
{
Values
[]
string
MatchFlags
MatchFlagsType
Count
*
uint
Comparand
string
Compare
ReqCompareType
Negate
bool
}
// RecvReturn is a name for the disposition of a client request.
// See: https://varnish-cache.org/docs/6.1/reference/states.html
type
RecvReturn
string
const
(
// RecvHash to invoke cache lookup.
RecvHash
RecvReturn
=
"hash"
// RecvPass to bypass cache lookup.
RecvPass
=
"pass"
// RecvPipe for pipe mode -- Varnish passes data between
// client and backend with no further intervention.
RecvPipe
=
"pipe"
// RecvPurge to purge a cache object.
// See: https://varnish-cache.org/docs/6.1/users-guide/purging.html?highlight=purge#http-purging
RecvPurge
=
"purge"
// RecvSynth to generate a synthetic response with a given
// HTTP response status.
RecvSynth
=
"synth"
)
// DispositionType specifies the disposition of a client request when
// associated Conditions are met.
//
// Status is the HTTP response status to set when Action is RecvSynth;
// ignored for other values of Action.
type
DispositionType
struct
{
Action
RecvReturn
Status
uint16
}
// DispositionSpec specifies the disposition of a client request when
// all of the Conditions are met.
type
DispositionSpec
struct
{
Conditions
[]
Condition
Disposition
DispositionType
}
func
(
reqDisp
DispositionSpec
)
hash
(
hash
hash
.
Hash
)
{
for
_
,
cond
:=
range
reqDisp
.
Conditions
{
for
_
,
val
:=
range
cond
.
Values
{
hash
.
Write
([]
byte
(
val
))
}
cond
.
MatchFlags
.
hash
(
hash
)
if
cond
.
Count
!=
nil
{
countBytes
:=
make
([]
byte
,
8
)
binary
.
BigEndian
.
PutUint64
(
countBytes
,
uint64
(
*
cond
.
Count
))
hash
.
Write
(
countBytes
)
}
hash
.
Write
([]
byte
(
cond
.
Comparand
))
hash
.
Write
([]
byte
{
byte
(
cond
.
Compare
)})
if
cond
.
Negate
{
hash
.
Write
([]
byte
{
1
})
}
else
{
hash
.
Write
([]
byte
{
0
})
}
}
hash
.
Write
([]
byte
(
reqDisp
.
Disposition
.
Action
))
if
reqDisp
.
Disposition
.
Action
==
RecvSynth
{
statusBytes
:=
make
([]
byte
,
2
)
binary
.
BigEndian
.
PutUint16
(
statusBytes
,
uint16
(
reqDisp
.
Disposition
.
Status
))
hash
.
Write
(
statusBytes
)
}
}
// Spec is the specification for a VCL configuration derived from
// Ingresses and VarnishConfig Custom Resources. This abstracts the
// VCL to be loaded by all instances of a Varnish Service.
...
...
@@ -677,8 +784,9 @@ type Spec struct {
// ACLs is a list of specifications for whitelisting or
// blacklisting IPs with access control lists, derived from
// VarnishConfig.Spec.ACLs.
ACLs
[]
ACL
Rewrites
[]
Rewrite
ACLs
[]
ACL
Rewrites
[]
Rewrite
Dispositions
[]
DispositionSpec
}
// DeepHash computes a alphanumerically encoded hash value from a Spec
...
...
@@ -712,6 +820,9 @@ func (spec Spec) DeepHash() string {
for
_
,
rw
:=
range
spec
.
Rewrites
{
rw
.
hash
(
hash
)
}
for
_
,
reqDisp
:=
range
spec
.
Dispositions
{
reqDisp
.
hash
(
hash
)
}
h
:=
new
(
big
.
Int
)
h
.
SetBytes
(
hash
.
Sum
(
nil
))
return
h
.
Text
(
62
)
...
...
@@ -731,6 +842,7 @@ func (spec Spec) Canonical() Spec {
Auths
:
make
([]
Auth
,
len
(
spec
.
Auths
)),
ACLs
:
make
([]
ACL
,
len
(
spec
.
ACLs
)),
Rewrites
:
make
([]
Rewrite
,
len
(
spec
.
Rewrites
)),
Dispositions
:
make
([]
DispositionSpec
,
len
(
spec
.
Dispositions
)),
}
copy
(
canon
.
DefaultService
.
Addresses
,
spec
.
DefaultService
.
Addresses
)
sort
.
Stable
(
byIPPort
(
canon
.
DefaultService
.
Addresses
))
...
...
@@ -762,5 +874,11 @@ func (spec Spec) Canonical() Spec {
}
copy
(
canon
.
Rewrites
,
spec
.
Rewrites
)
sort
.
Stable
(
byVCLSub
(
canon
.
Rewrites
))
copy
(
canon
.
Dispositions
,
spec
.
Dispositions
)
for
_
,
disp
:=
range
canon
.
Dispositions
{
for
_
,
cond
:=
range
disp
.
Conditions
{
sort
.
Strings
(
cond
.
Values
)
}
}
return
canon
}
pkg/varnish/vcl/template.go
View file @
b113c219
...
...
@@ -55,6 +55,11 @@ var fMap = template.FuncMap{
"rewrMatch"
:
func
(
rewr
Rewrite
)
string
{
return
rewrMatch
(
rewr
)
},
"rewrOp"
:
func
(
rewr
Rewrite
)
string
{
return
rewrOp
(
rewr
)
},
"rewrSelect"
:
func
(
rewr
Rewrite
)
string
{
return
rewrSelect
(
rewr
)
},
"reqVMOD"
:
func
(
cond
Condition
)
string
{
return
reqVMOD
(
cond
)
},
"reqMatch"
:
func
(
cond
Condition
)
string
{
return
reqMatch
(
cond
)
},
"value"
:
func
(
cond
Condition
)
string
{
return
reqValue
(
cond
)
},
"reqFlags"
:
func
(
cond
Condition
)
string
{
return
reqFlags
(
cond
)
},
"exists"
:
func
(
cmp
ReqCompareType
)
bool
{
return
cmp
==
Exists
},
"aclCmp"
:
func
(
comparand
string
)
string
{
return
aclCmp
(
comparand
)
},
...
...
@@ -131,6 +136,18 @@ var fMap = template.FuncMap{
"needsSelectEnum"
:
func
(
rewr
Rewrite
)
bool
{
return
rewr
.
Select
!=
Unique
},
"reqObj"
:
func
(
didx
,
cidx
int
)
string
{
return
fmt
.
Sprintf
(
"vk8s_reqdisp_%d_%d"
,
didx
,
cidx
)
},
"reqNeedsMatcher"
:
func
(
cond
Condition
)
bool
{
return
reqNeedsMatcher
(
cond
)
},
"reqNeedsCompile"
:
func
(
cond
Condition
)
bool
{
return
reqNeedsCompile
(
cond
)
},
"reqCmpRelation"
:
func
(
cond
Condition
)
string
{
return
reqCmpRelation
(
cond
)
},
}
const
(
...
...
@@ -139,6 +156,7 @@ const (
authTmplSrc
=
"auth.tmpl"
aclTmplSrc
=
"acl.tmpl"
rewriteTmplSrc
=
"rewrite.tmpl"
reqDispTmplSrc
=
"recv_disposition.tmpl"
// maxSymLen is a workaround for Varnish issue #2880
// https://github.com/varnishcache/varnish-cache/issues/2880
...
...
@@ -152,6 +170,7 @@ var (
authTmpl
*
template
.
Template
aclTmpl
*
template
.
Template
rewriteTmpl
*
template
.
Template
reqDispTmpl
*
template
.
Template
vclIllegal
=
regexp
.
MustCompile
(
"[^[:word:]-]+"
)
)
...
...
@@ -163,6 +182,7 @@ func InitTemplates(tmplDir string) error {
authTmplPath
:=
path
.
Join
(
tmplDir
,
authTmplSrc
)
aclTmplPath
:=
path
.
Join
(
tmplDir
,
aclTmplSrc
)
rewriteTmplPath
:=
path
.
Join
(
tmplDir
,
rewriteTmplSrc
)
reqDispTmplPath
:=
path
.
Join
(
tmplDir
,
reqDispTmplSrc
)
ingressTmpl
,
err
=
template
.
New
(
ingTmplSrc
)
.
Funcs
(
fMap
)
.
ParseFiles
(
ingTmplPath
)
...
...
@@ -189,6 +209,11 @@ func InitTemplates(tmplDir string) error {
if
err
!=
nil
{
return
err
}
reqDispTmpl
,
err
=
template
.
New
(
reqDispTmplSrc
)
.
Funcs
(
fMap
)
.
ParseFiles
(
reqDispTmplPath
)
if
err
!=
nil
{
return
err
}
return
nil
}
...
...
@@ -227,6 +252,11 @@ func (spec Spec) GetSrc() (string, error) {
return
""
,
err
}
}
if
len
(
spec
.
Dispositions
)
>
0
{
if
err
:=
reqDispTmpl
.
Execute
(
&
buf
,
spec
);
err
!=
nil
{
return
""
,
err
}
}
if
spec
.
VCL
!=
""
{
buf
.
WriteString
(
spec
.
VCL
)
}
...
...
@@ -318,6 +348,26 @@ func cmpRelation(cmp CompareType) string {
}
}
func
reqCmpRelation
(
cond
Condition
)
string
{
switch
cond
.
Compare
{
case
ReqEqual
:
if
cond
.
Negate
{
return
"!="
}
return
"=="
case
Greater
:
return
">"
case
GreaterEqual
:
return
">="
case
Less
:
return
"<"
case
LessEqual
:
return
"<="
default
:
return
"__INVALID_COMPARISON_TYPE__"
}
}
func
dirType
(
svc
Service
)
string
{
if
svc
.
Director
==
nil
{
return
RoundRobin
.
String
()
...
...
@@ -338,6 +388,19 @@ func needsMatcher(rewr Rewrite) bool {
}
}
func
reqNeedsMatcher
(
cond
Condition
)
bool
{
switch
cond
.
Compare
{
case
ReqMatch
,
ReqPrefix
:
return
true
case
Exists
,
Greater
,
GreaterEqual
,
Less
,
LessEqual
:
return
false
}
if
cond
.
Count
!=
nil
||
len
(
cond
.
Values
)
==
1
{
return
false
}
return
true
}
func
rewrName
(
i
int
)
string
{
return
fmt
.
Sprintf
(
"vk8s_rewrite_%d"
,
i
)
}
...
...
@@ -349,51 +412,59 @@ func rewrVMOD(rewr Rewrite) string {
return
"selector"
}
func
rewrFlags
(
rewr
Rewrit
e
)
string
{
if
rewr
.
Compare
!=
RewriteMatch
{
if
!
rewr
.
MatchFlags
.
CaseSensitive
{
func
matcherFlags
(
isSelector
bool
,
flagSpec
MatchFlagsTyp
e
)
string
{
if
isSelector
{
if
!
flagSpec
.
CaseSensitive
{
return
"case_sensitive=false"
}
return
""
}
var
flags
[]
string
if
rewr
.
MatchFlags
.
MaxMem
!=
0
&&
rewr
.
MatchFlags
.
MaxMem
!=
8388608
{
maxMem
:=
fmt
.
Sprintf
(
"max_mem=%d"
,
rewr
.
MatchFlags
.
MaxMem
)
if
flagSpec
.
MaxMem
!=
0
&&
flagSpec
.
MaxMem
!=
8388608
{
maxMem
:=
fmt
.
Sprintf
(
"max_mem=%d"
,
flagSpec
.
MaxMem
)
flags
=
append
(
flags
,
maxMem
)
}
if
rewr
.
MatchFlags
.
Anchor
!=
None
{
switch
rewr
.
MatchFlags
.
Anchor
{
if
flagSpec
.
Anchor
!=
None
{
switch
flagSpec
.
Anchor
{
case
Start
:
flags
=
append
(
flags
,
"anchor=start"
)
case
Both
:
flags
=
append
(
flags
,
"anchor=both"
)
}
}
if
rewr
.
MatchFlags
.
UTF8
{
if
flagSpec
.
UTF8
{
flags
=
append
(
flags
,
"utf8=true"
)
}
if
rewr
.
MatchFlags
.
PosixSyntax
{
if
flagSpec
.
PosixSyntax
{
flags
=
append
(
flags
,
"posix_syntax=true"
)
}
if
rewr
.
MatchFlags
.
LongestMatch
{
if
flagSpec
.
LongestMatch
{
flags
=
append
(
flags
,
"longest_match=true"
)
}
if
rewr
.
MatchFlags
.
Literal
{
if
flagSpec
.
Literal
{
flags
=
append
(
flags
,
"literal=true"
)
}
if
!
rewr
.
MatchFlags
.
CaseSensitive
{
if
!
flagSpec
.
CaseSensitive
{
flags
=
append
(
flags
,
"case_sensitive=false"
)
}
if
rewr
.
MatchFlags
.
PerlClasses
{
if
flagSpec
.
PerlClasses
{
flags
=
append
(
flags
,
"perl_classes=true"
)
}
if
rewr
.
MatchFlags
.
WordBoundary
{
if
flagSpec
.
WordBoundary
{
flags
=
append
(
flags
,
"word_boundary=true"
)
}
return
strings
.
Join
(
flags
,
","
)
}
func
rewrFlags
(
rewr
Rewrite
)
string
{
return
matcherFlags
(
rewr
.
Compare
!=
RewriteMatch
,
rewr
.
MatchFlags
)
}
func
reqFlags
(
cond
Condition
)
string
{
return
matcherFlags
(
cond
.
Compare
!=
ReqMatch
,
cond
.
MatchFlags
)
}
func
needsSave
(
rewr
Rewrite
)
bool
{
if
rewr
.
Compare
!=
RewriteMatch
{
return
false
...
...
@@ -410,6 +481,10 @@ func needsCompile(rewr Rewrite) bool {
return
rewr
.
Compare
==
RewriteMatch
}
func
reqNeedsCompile
(
cond
Condition
)
bool
{
return
cond
.
Compare
==
ReqMatch
}
func
rewrSub
(
rewr
Rewrite
)
string
{
if
rewr
.
VCLSub
==
Unspecified
{
if
strings
.
HasPrefix
(
rewr
.
Target
,
"resp"
)
||
...
...
@@ -478,6 +553,7 @@ func rewrOperand2(rewr Rewrite, i int) string {
return
rewr
.
Source
}
// XXX DRY
func
rewrMatch
(
rewr
Rewrite
)
string
{
switch
rewr
.
Compare
{
case
RewriteMatch
,
RewriteEqual
:
...
...
@@ -489,6 +565,17 @@ func rewrMatch(rewr Rewrite) string {
}
}
func
reqMatch
(
cond
Condition
)
string
{
switch
cond
.
Compare
{
case
ReqMatch
,
ReqEqual
:
return
"match"
case
ReqPrefix
:
return
"hasprefix"
default
:
return
"__INVALID_MATCH_OPERATION__"
}
}
func
rewrOp
(
rewr
Rewrite
)
string
{
switch
rewr
.
Method
{
case
Sub
:
...
...
@@ -504,3 +591,21 @@ func rewrOp(rewr Rewrite) string {
return
"__INVALID_REWRITE_OPERAION__"
}
}
func
reqVMOD
(
cond
Condition
)
string
{
switch
cond
.
Compare
{
case
ReqEqual
,
ReqPrefix
:
return
"selector"
case
ReqMatch
:
return
"re2"
default
:
return
"__INVALID_COMPARISON_FOR_VMOD__"
}
}
func
reqValue
(
cond
Condition
)
string
{
if
cond
.
Count
!=
nil
{
return
fmt
.
Sprintf
(
"%d"
,
*
cond
.
Count
)
}
return
`"`
+
cond
.
Values
[
0
]
+
`"`
}
pkg/varnish/vcl/testdata/recv_disp_builtin.golden
0 → 100644
View file @
b113c219
import re2;
import selector;
sub vcl_init {
new vk8s_reqdisp_1_2 = selector.set(case_sensitive=false);
vk8s_reqdisp_1_2.add("HTTP/1.1");
}
sub vcl_init {
new vk8s_reqdisp_2_0 = selector.set();
vk8s_reqdisp_2_0.add("GET");
vk8s_reqdisp_2_0.add("HEAD");
vk8s_reqdisp_2_0.add("PUT");
vk8s_reqdisp_2_0.add("POST");
vk8s_reqdisp_2_0.add("TRACE");
vk8s_reqdisp_2_0.add("OPTIONS");
vk8s_reqdisp_2_0.add("DELETE");
}
sub vcl_init {
new vk8s_reqdisp_3_0 = selector.set();
vk8s_reqdisp_3_0.add("GET");
vk8s_reqdisp_3_0.add("HEAD");
}
sub vcl_recv {
if (req.method == "PRI") {
return (synth(405));
}
if (! req.http.Host &&
req.esi_level == 0 &&
vk8s_reqdisp_1_2.hasprefix(req.proto)) {
return (synth(400));
}
if (! vk8s_reqdisp_2_0.match(req.method)) {
return (pipe);
}
if (! vk8s_reqdisp_3_0.match(req.method)) {
return (pass);
}
if (req.http.Cookie) {
return (pass);
}
if (req.http.Authorization) {
return (pass);
}
return (hash);
}
pkg/varnish/vcl/testdata/recv_disp_cacheable.golden
0 → 100644
View file @
b113c219
import re2;
import selector;
sub vcl_init {
new vk8s_reqdisp_0_0 = re2.set();
vk8s_reqdisp_0_0.add("\.png$");
vk8s_reqdisp_0_0.add("\.jpe?g$");
vk8s_reqdisp_0_0.add("\.css$");
vk8s_reqdisp_0_0.add("\.js$");
vk8s_reqdisp_0_0.compile();
}
sub vcl_recv {
if (vk8s_reqdisp_0_0.match(req.url)) {
return (hash);
}
return (hash);
}
pkg/varnish/vcl/testdata/recv_disp_connect_pipe.golden
0 → 100644
View file @
b113c219
import re2;
import selector;
sub vcl_recv {
if (req.method == "CONNECT") {
return (pipe);
}
return (hash);
}
pkg/varnish/vcl/testdata/recv_disp_method_not_allowed.golden
0 → 100644
View file @
b113c219
import re2;
import selector;
sub vcl_init {
new vk8s_reqdisp_0_0 = selector.set();
vk8s_reqdisp_0_0.add("GET");
vk8s_reqdisp_0_0.add("HEAD");
vk8s_reqdisp_0_0.add("PUT");
vk8s_reqdisp_0_0.add("POST");
vk8s_reqdisp_0_0.add("TRACE");
vk8s_reqdisp_0_0.add("OPTIONS");
vk8s_reqdisp_0_0.add("DELETE");
}
sub vcl_recv {
if (! vk8s_reqdisp_0_0.match(req.method)) {
return (synth(405));
}
return (hash);
}
pkg/varnish/vcl/testdata/recv_disp_non_cacheable.golden
0 → 100644
View file @
b113c219
import re2;
import selector;
sub vcl_init {
new vk8s_reqdisp_0_0 = selector.set();
vk8s_reqdisp_0_0.add("/interactive/");
vk8s_reqdisp_0_0.add("/basket/");
vk8s_reqdisp_0_0.add("/personal");
vk8s_reqdisp_0_0.add("/dynamic/");
}
sub vcl_recv {
if (vk8s_reqdisp_0_0.hasprefix(req.url)) {
return (pass);
}
return (hash);
}
pkg/varnish/vcl/testdata/recv_disp_pipe_on_connect.golden
0 → 100644
View file @
b113c219
import re2;
import selector;
sub vcl_recv {
if (req.method == "CONNECT") {
return (pipe);
}
return (hash);
}
pkg/varnish/vcl/testdata/recv_disp_purge_method.golden
0 → 100644
View file @
b113c219
import re2;
import selector;
sub vcl_recv {
if (req.method == "PURGE") {
return (purge);
}
return (hash);
}
pkg/varnish/vcl/testdata/recv_disp_url_whitelist.golden
0 → 100644
View file @
b113c219
import re2;
import selector;
sub vcl_init {
new vk8s_reqdisp_0_0 = selector.set();
vk8s_reqdisp_0_0.add("/foo");
vk8s_reqdisp_0_0.add("/bar");
vk8s_reqdisp_0_0.add("/baz");
vk8s_reqdisp_0_0.add("/quux");
}
sub vcl_recv {
if (! vk8s_reqdisp_0_0.hasprefix(req.url)) {
return (synth(403));
}
return (hash);
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment