Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add http-request replace-header feature #21

Merged
merged 2 commits into from
Jan 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 28 additions & 4 deletions apis/config/v1alpha1/backend_types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ var _ = Describe("Backend", Label("type"), func() {
Ω(backend.AddToParser(p)).ShouldNot(HaveOccurred())
Ω(p.String()).Should(ContainSubstring("hash-type consistent djb2 avalanche"))
})

It("should set ssl parameters", func() {
backend := &configv1alpha1.Backend{
ObjectMeta: metav1.ObjectMeta{Name: "foo"},
Expand Down Expand Up @@ -117,7 +116,6 @@ var _ = Describe("Backend", Label("type"), func() {
Ω(backend.AddToParser(p)).ShouldNot(HaveOccurred())
Ω(p.String()).Should(ContainSubstring("ssl alpn h2,http/1.0 ca-file /usr/local/etc/haproxy/test-ca.crt cookie 1c3c2192e2912699ccd31119b162666a inter 5000 verify required verifyhost routername.namespace.svc weight 256"))
})

It("should set option http-request deny", func() {
var notFound int64 = 404
backend := &configv1alpha1.Backend{
Expand All @@ -140,7 +138,34 @@ var _ = Describe("Backend", Label("type"), func() {
Ω(backend.AddToParser(p)).ShouldNot(HaveOccurred())
Ω(p.String()).Should(ContainSubstring("http-request deny deny_status 404 if { var(my-ip) -m ip 127.0.0.0/8 10.0.0.0/8 }\n"))
})

It("should set option http-request replace-path", func() {
backend := &configv1alpha1.Backend{
ObjectMeta: metav1.ObjectMeta{Name: "openshift_default"},
Spec: configv1alpha1.BackendSpec{
BaseSpec: configv1alpha1.BaseSpec{
HTTPRequest: &configv1alpha1.HTTPRequestRules{
ReplacePath: []configv1alpha1.ReplacePath{
{
MatchRegex: "(.*)",
ReplaceFmt: "/foo\\1",
},
{
Rule: configv1alpha1.Rule{
ConditionType: "if",
Condition: "{ url_beg /foo/ }",
},
MatchRegex: "/foo/(.*)",
ReplaceFmt: "/\\1",
},
},
},
},
},
}
Ω(backend.AddToParser(p)).ShouldNot(HaveOccurred())
Ω(p.String()).Should(ContainSubstring("http-request replace-path (.*) /foo\\1\n"))
Ω(p.String()).Should(ContainSubstring("http-request replace-path /foo/(.*) /\\1 if { url_beg /foo/ }\n"))
})
It("should set option http-pretend-keepalive", func() {
backend := &configv1alpha1.Backend{
ObjectMeta: metav1.ObjectMeta{Name: "openshift_default"},
Expand All @@ -153,7 +178,6 @@ var _ = Describe("Backend", Label("type"), func() {
Ω(backend.AddToParser(p)).ShouldNot(HaveOccurred())
Ω(p.String()).Should(ContainSubstring("option http-pretend-keepalive\n"))
})

It("should set option forwardfor", func() {
backend := &configv1alpha1.Backend{
ObjectMeta: metav1.ObjectMeta{Name: "openshift_default"},
Expand Down
26 changes: 25 additions & 1 deletion apis/config/v1alpha1/common_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -729,6 +729,10 @@ type HTTPRequestRules struct {
// Redirect performs an HTTP redirection based on a redirect rule.
// +optional
Redirect []Redirect `json:"redirect,omitempty"`
// ReplacePath matches the value of the path using a regex and completely replaces it with the specified format.
// The replacement does not modify the scheme, the authority and the query-string.
// +optional
ReplacePath []ReplacePath `json:"replacePath,omitempty"`
// Deny stops the evaluation of the rules and immediately rejects the request and emits an HTTP 403 error.
// Optionally the status code specified as an argument to deny_status.
// +optional
Expand Down Expand Up @@ -777,6 +781,17 @@ func (h *HTTPRequestRules) Model() (models.HTTPRequestRules, error) {
})
}

for idx, header := range h.ReplacePath {
model = append(model, &models.HTTPRequestRule{
Type: "replace-path",
Index: ptr.To(int64(idx)),
PathMatch: header.MatchRegex,
PathFmt: header.ReplaceFmt,
Cond: header.ConditionType,
CondTest: header.Condition,
})
}

if h.Deny != nil && h.Deny.Enabled {
model = append(model, &models.HTTPRequestRule{
DenyStatus: h.DenyStatus,
Expand Down Expand Up @@ -869,7 +884,7 @@ type HTTPReturn struct {
}

type HTTPReturnContent struct {
// Type specifies the content-type of the HTTP REsponse.
// Type specifies the content-type of the HTTP response.
Type string `json:"type"`
// ContentFormat defines the format of the Content. Can be one an errorfile or a string.
// +kubebuilder:validation:Enum=default-errorfile;errorfile;errorfiles;file;lf-file;string;lf-string
Expand All @@ -891,6 +906,7 @@ type HTTPPathRule struct {
// Value specifies the path value
Value string `json:"format,omitempty"`
}

type HTTPHeaderValue struct {
// Env variable with the header value
Env *corev1.EnvVar `json:"env,omitempty"`
Expand All @@ -900,6 +916,14 @@ type HTTPHeaderValue struct {
Format *string `json:"format,omitempty"`
}

type ReplacePath struct {
Rule `json:",inline"`
// MatchRegex is a string pattern used to identify the paths that need to be replaced.
MatchRegex string `json:"matchRegex"`
// ReplaceFmt defines the format string used to replace the values that match the pattern.
ReplaceFmt string `json:"replaceFmt"`
}

func (h *HTTPHeaderValue) String() string {
str := ptr.Deref(h.Str, "")
if h.Env != nil {
Expand Down
17 changes: 17 additions & 0 deletions docs/api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,7 @@ _Appears in:_
| `setPath` _[HTTPPathRule](#httppathrule) array_ | SetPath sets request path |
| `addHeader` _[HTTPHeaderRule](#httpheaderrule) array_ | AddHeader appends HTTP header fields |
| `redirect` _[Redirect](#redirect) array_ | Redirect performs an HTTP redirection based on a redirect rule. |
| `replacePath` _[ReplacePath](#replacepath) array_ | ReplacePath matches the value of the path using a regex and completely replaces it with the specified format. The replacement does not modify the scheme, the authority and the query-string. |
| `deny` _[Deny](#deny)_ | Deny stops the evaluation of the rules and immediately rejects the request and emits an HTTP 403 error. Optionally the status code specified as an argument to deny_status. |
| `denyStatus` _[int64](#int64)_ | DenyStatus is the HTTP status code. |
| `return` _[HTTPReturn](#httpreturn)_ | Return stops the evaluation of the rules and immediately returns a response. |
Expand Down Expand Up @@ -649,6 +650,21 @@ _Appears in:_
| `selector` _[LabelSelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.25/#labelselector-v1-meta)_ | LabelSelector to select multiple backends |


#### ReplacePath





_Appears in:_
- [HTTPRequestRules](#httprequestrules)

| Field | Description |
| --- | --- |
| `matchRegex` _string_ | MatchRegex is a string pattern used to identify the paths that need to be replaced. |
| `replaceFmt` _string_ | ReplaceFmt defines the format string used to replace the values that match the pattern. |


#### Resolver


Expand Down Expand Up @@ -696,6 +712,7 @@ _Appears in:_
- [HTTPHeaderRule](#httpheaderrule)
- [HTTPPathRule](#httppathrule)
- [Redirect](#redirect)
- [ReplacePath](#replacepath)
- [TCPRequestRule](#tcprequestrule)


Expand Down
32 changes: 31 additions & 1 deletion helm/haproxy-operator/crds/config.haproxy.com_backends.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,36 @@ spec:
type: string
type: object
type: array
replacePath:
description: ReplacePath matches the value of the path using a
regex and completely replaces it with the specified format.
The replacement does not modify the scheme, the authority and
the query-string.
items:
properties:
condition:
description: Condition is a condition composed of ACLs.
type: string
conditionType:
description: ConditionType specifies the type of the condition
matching ('if' or 'unless')
enum:
- if
- unless
type: string
matchRegex:
description: MatchRegex is a string pattern used to identify
the paths that need to be replaced.
type: string
replaceFmt:
description: ReplaceFmt defines the format string used to
replace the values that match the pattern.
type: string
required:
- matchRegex
- replaceFmt
type: object
type: array
return:
description: Return stops the evaluation of the rules and immediately
returns a response.
Expand All @@ -646,7 +676,7 @@ spec:
type: string
type:
description: Type specifies the content-type of the HTTP
REsponse.
response.
type: string
value:
description: Value specifying the file or the string to
Expand Down
32 changes: 31 additions & 1 deletion helm/haproxy-operator/crds/config.haproxy.com_frontends.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -874,6 +874,36 @@ spec:
type: string
type: object
type: array
replacePath:
description: ReplacePath matches the value of the path using a
regex and completely replaces it with the specified format.
The replacement does not modify the scheme, the authority and
the query-string.
items:
properties:
condition:
description: Condition is a condition composed of ACLs.
type: string
conditionType:
description: ConditionType specifies the type of the condition
matching ('if' or 'unless')
enum:
- if
- unless
type: string
matchRegex:
description: MatchRegex is a string pattern used to identify
the paths that need to be replaced.
type: string
replaceFmt:
description: ReplaceFmt defines the format string used to
replace the values that match the pattern.
type: string
required:
- matchRegex
- replaceFmt
type: object
type: array
return:
description: Return stops the evaluation of the rules and immediately
returns a response.
Expand All @@ -897,7 +927,7 @@ spec:
type: string
type:
description: Type specifies the content-type of the HTTP
REsponse.
response.
type: string
value:
description: Value specifying the file or the string to
Expand Down
32 changes: 31 additions & 1 deletion helm/haproxy-operator/crds/config.haproxy.com_listens.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -981,6 +981,36 @@ spec:
type: string
type: object
type: array
replacePath:
description: ReplacePath matches the value of the path using a
regex and completely replaces it with the specified format.
The replacement does not modify the scheme, the authority and
the query-string.
items:
properties:
condition:
description: Condition is a condition composed of ACLs.
type: string
conditionType:
description: ConditionType specifies the type of the condition
matching ('if' or 'unless')
enum:
- if
- unless
type: string
matchRegex:
description: MatchRegex is a string pattern used to identify
the paths that need to be replaced.
type: string
replaceFmt:
description: ReplaceFmt defines the format string used to
replace the values that match the pattern.
type: string
required:
- matchRegex
- replaceFmt
type: object
type: array
return:
description: Return stops the evaluation of the rules and immediately
returns a response.
Expand All @@ -1004,7 +1034,7 @@ spec:
type: string
type:
description: Type specifies the content-type of the HTTP
REsponse.
response.
type: string
value:
description: Value specifying the file or the string to
Expand Down
Loading