Skip to content

Commit

Permalink
Merge pull request #21 from six-group/http-replace-path
Browse files Browse the repository at this point in the history
Add http-request replace-header feature
  • Loading branch information
snorwin committed Jan 10, 2024
2 parents c378e87 + 155a788 commit 3abd317
Show file tree
Hide file tree
Showing 7 changed files with 322 additions and 66 deletions.
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

0 comments on commit 3abd317

Please sign in to comment.