Skip to content

Commit eb596a9

Browse files
committed
MINOR: switch CORS rules to http-after-response
1 parent c27522e commit eb596a9

File tree

8 files changed

+105
-25
lines changed

8 files changed

+105
-25
lines changed

.aspell.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
mode: commit
2+
min_length: 3
3+
allowed:
4+
- http
5+
- CORS

pkg/annotations/annotations.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ func (a annImpl) Frontend(i *store.Ingress, r *rules.List, m maps.Maps) []Annota
141141
resSetCORS.NewAnnotation("cors-allow-headers"),
142142
resSetCORS.NewAnnotation("cors-max-age"),
143143
resSetCORS.NewAnnotation("cors-allow-credentials"),
144+
resSetCORS.NewAnnotation("cors-respond-to-options"),
144145
}
145146
}
146147

pkg/annotations/ingress/resSetCORS.go

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,11 @@ func (a ResSetCORSAnn) Process(k store.K8s, annotations ...map[string]string) (e
7474
origin = "%[var(txn." + corsVarName + ")]"
7575
}
7676
a.parent.rules.Add(&rules.SetHdr{
77-
HdrName: "Access-Control-Allow-Origin",
78-
HdrFormat: origin,
79-
Response: true,
80-
CondTest: a.parent.acl,
81-
Cond: "if",
77+
HdrName: "Access-Control-Allow-Origin",
78+
HdrFormat: origin,
79+
AfterResponse: true,
80+
CondTest: a.parent.acl,
81+
Cond: "if",
8282
})
8383
case "cors-allow-methods":
8484
if a.parent.acl == "" {
@@ -96,23 +96,23 @@ func (a ResSetCORSAnn) Process(k store.K8s, annotations ...map[string]string) (e
9696
input = "\"" + strings.Join(methods, ", ") + "\""
9797
}
9898
a.parent.rules.Add(&rules.SetHdr{
99-
HdrName: "Access-Control-Allow-Methods",
100-
HdrFormat: input,
101-
Response: true,
102-
CondTest: a.parent.acl,
103-
Cond: "if",
99+
HdrName: "Access-Control-Allow-Methods",
100+
HdrFormat: input,
101+
AfterResponse: true,
102+
CondTest: a.parent.acl,
103+
Cond: "if",
104104
})
105105
case "cors-allow-headers":
106106
if a.parent.acl == "" {
107107
return
108108
}
109109
input = strings.Join(strings.Fields(input), "") // strip spaces
110110
a.parent.rules.Add(rules.SetHdr{
111-
HdrName: "Access-Control-Allow-Headers",
112-
HdrFormat: "\"" + input + "\"",
113-
Response: true,
114-
CondTest: a.parent.acl,
115-
Cond: "if",
111+
HdrName: "Access-Control-Allow-Headers",
112+
HdrFormat: "\"" + input + "\"",
113+
AfterResponse: true,
114+
CondTest: a.parent.acl,
115+
Cond: "if",
116116
})
117117
case "cors-max-age":
118118
if a.parent.acl == "" {
@@ -128,22 +128,29 @@ func (a ResSetCORSAnn) Process(k store.K8s, annotations ...map[string]string) (e
128128
return fmt.Errorf("invalid cors-max-age value %d", maxage)
129129
}
130130
a.parent.rules.Add(&rules.SetHdr{
131-
HdrName: "Access-Control-Max-Age",
132-
HdrFormat: fmt.Sprintf("\"%d\"", maxage),
133-
Response: true,
134-
CondTest: a.parent.acl,
135-
Cond: "if",
131+
HdrName: "Access-Control-Max-Age",
132+
HdrFormat: fmt.Sprintf("\"%d\"", maxage),
133+
AfterResponse: true,
134+
CondTest: a.parent.acl,
135+
Cond: "if",
136136
})
137137
case "cors-allow-credentials":
138138
if a.parent.acl == "" || input != "true" {
139139
return
140140
}
141141
a.parent.rules.Add(&rules.SetHdr{
142-
HdrName: "Access-Control-Allow-Credentials",
143-
HdrFormat: "\"true\"",
144-
Response: true,
145-
CondTest: a.parent.acl,
146-
Cond: "if",
142+
HdrName: "Access-Control-Allow-Credentials",
143+
HdrFormat: "\"true\"",
144+
AfterResponse: true,
145+
CondTest: a.parent.acl,
146+
Cond: "if",
147+
})
148+
case "cors-respond-to-options":
149+
if a.parent.acl == "" || input != "true" {
150+
return
151+
}
152+
a.parent.rules.Add(&rules.ReqReturnStatus{
153+
StatusCode: 204,
147154
})
148155
default:
149156
err = fmt.Errorf("unknown cors annotation '%s'", a.name)

pkg/haproxy/api/api.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ type HAProxyClient interface { //nolint:interfacebloat
7171
FrontendBindDelete(frontend string, bind string) error
7272
FrontendHTTPRequestRuleCreate(frontend string, rule models.HTTPRequestRule, ingressACL string) error
7373
FrontendHTTPResponseRuleCreate(frontend string, rule models.HTTPResponseRule, ingressACL string) error
74+
FrontendHTTPAfterResponseRuleCreate(frontend string, rule models.HTTPAfterResponseRule, ingressACL string) error
7475
FrontendTCPRequestRuleCreate(frontend string, rule models.TCPRequestRule, ingressACL string) error
7576
FrontendRuleDeleteAll(frontend string)
7677
GlobalGetLogTargets() (models.LogTargets, error)

pkg/haproxy/api/frontend.go

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

66
"github.com/haproxytech/client-native/v5/models"
7+
parser "github.com/haproxytech/config-parser/v5"
78
"github.com/haproxytech/config-parser/v5/types"
89
"github.com/haproxytech/kubernetes-ingress/pkg/utils"
910
)
@@ -231,6 +232,12 @@ func (c *clientNative) FrontendRuleDeleteAll(frontend string) {
231232
break
232233
}
233234
}
235+
for {
236+
err := configuration.DeleteHTTPAfterResponseRule(0, "frontend", frontend, c.activeTransaction, 0)
237+
if err != nil {
238+
break
239+
}
240+
}
234241
// No usage of TCPResponseRules yet.
235242
}
236243

@@ -263,3 +270,15 @@ func (c *clientNative) PeerEntryDelete(peerSection, entry string) error {
263270
}
264271
return cfg.DeletePeerEntry(entry, peerSection, c.activeTransaction, 0)
265272
}
273+
274+
func (c *clientNative) FrontendHTTPAfterResponseRuleCreate(frontend string, rule models.HTTPAfterResponseRule, ingressACL string) error {
275+
configuration, err := c.nativeAPI.Configuration()
276+
if err != nil {
277+
return err
278+
}
279+
if ingressACL != "" {
280+
rule.Cond = "if"
281+
rule.CondTest = fmt.Sprintf("%s %s", ingressACL, rule.CondTest)
282+
}
283+
return configuration.CreateHTTPAfterResponseRule(string(parser.Frontends), frontend, &rule, c.activeTransaction, 0)
284+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package rules
2+
3+
import (
4+
"errors"
5+
6+
"github.com/haproxytech/client-native/v5/models"
7+
"github.com/haproxytech/kubernetes-ingress/pkg/haproxy/api"
8+
"github.com/haproxytech/kubernetes-ingress/pkg/utils"
9+
)
10+
11+
//nolint:golint,stylecheck
12+
var MIME_TYPE_TEXT_PLAIN string = "text/plain"
13+
14+
type ReqReturnStatus struct {
15+
StatusCode int64
16+
}
17+
18+
func (r ReqReturnStatus) GetType() Type {
19+
return REQ_RETURN_STATUS
20+
}
21+
22+
func (r ReqReturnStatus) Create(client api.HAProxyClient, frontend *models.Frontend, ingressACL string) error {
23+
if frontend.Mode == "tcp" {
24+
return errors.New("HTTP status cannot be set in TCP mode")
25+
}
26+
httpRule := models.HTTPRequestRule{
27+
Index: utils.PtrInt64(0),
28+
ReturnStatusCode: &r.StatusCode,
29+
Type: "return",
30+
}
31+
ingressACL += " METH_OPTIONS"
32+
return client.FrontendHTTPRequestRuleCreate(frontend.Name, httpRule, ingressACL)
33+
}

pkg/haproxy/rules/setHdr.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ type SetHdr struct {
1616
Cond string
1717
Type Type
1818
Response bool
19+
AfterResponse bool
1920
ForwardedProto bool
2021
}
2122

@@ -55,6 +56,17 @@ func (r SetHdr) Create(client api.HAProxyClient, frontend *models.Frontend, ingr
5556
}
5657
return client.FrontendHTTPResponseRuleCreate(frontend.Name, httpRule, ingressACL)
5758
}
59+
if r.AfterResponse {
60+
httpRule := models.HTTPAfterResponseRule{
61+
Index: utils.PtrInt64(0),
62+
Type: "set-header",
63+
HdrName: r.HdrName,
64+
HdrFormat: r.HdrFormat,
65+
CondTest: r.CondTest,
66+
Cond: r.Cond,
67+
}
68+
return client.FrontendHTTPAfterResponseRuleCreate(frontend.Name, httpRule, ingressACL)
69+
}
5870
// REQ_SET_HEADER
5971
httpRule := models.HTTPRequestRule{
6072
Index: utils.PtrInt64(0),

pkg/haproxy/rules/types.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ const (
2121
REQ_SET_HEADER
2222
REQ_SET_HOST
2323
REQ_PATH_REWRITE
24+
REQ_RETURN_STATUS
2425
RES_SET_HEADER
2526
)
2627

@@ -41,4 +42,5 @@ var constLookup = map[Type]string{
4142
REQ_SET_HOST: "REQ_SET_HOST",
4243
REQ_PATH_REWRITE: "REQ_PATH_REWRITE",
4344
RES_SET_HEADER: "RES_SET_HEADER",
45+
REQ_RETURN_STATUS: "REQ_RETURN_STATUS",
4446
}

0 commit comments

Comments
 (0)