Skip to content

Commit 6964c92

Browse files
authored
feat: added https redirection support (#246)
1 parent 5d566d3 commit 6964c92

File tree

11 files changed

+96
-96
lines changed

11 files changed

+96
-96
lines changed

haproxy_manager/link.go

Lines changed: 56 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,6 @@ func (s Manager) DeleteTCPLink(transaction_id string, backend_name string, port
283283
return nil
284284
}
285285

286-
// TODO: Support other http ports except 80 for Redirect Rules
287286
// Add HTTP Redirect Rule
288287
func (s Manager) AddHTTPRedirectRule(transaction_id string, match_domain string, redirect_url string) error {
289288
if strings.TrimSpace(match_domain) == "" {
@@ -302,9 +301,9 @@ func (s Manager) AddHTTPRedirectRule(transaction_id string, match_domain string,
302301
"redir_code": 302,
303302
"redir_type": "location",
304303
"redir_value": redirect_url,
305-
"index": 1,
304+
"index": 0,
306305
"cond": "if",
307-
"cond_test": `{ hdr(host) -i ` + strings.TrimSpace(match_domain) + ` }`,
306+
"cond_test": `{ hdr(host) -i ` + strings.TrimSpace(match_domain) + ` } !letsencrypt-acl`,
308307
}
309308
// Create request bytes
310309
add_http_redirect_rule_request_body_bytes, err := json.Marshal(add_http_redirect_rule_request_body)
@@ -338,9 +337,9 @@ func (s Manager) AddHTTPSRedirectRule(transaction_id string, match_domain string
338337
"redir_code": 302,
339338
"redir_type": "location",
340339
"redir_value": redirect_url,
341-
"index": 1,
340+
"index": 0,
342341
"cond": "if",
343-
"cond_test": `{ hdr(host) -i ` + strings.TrimSpace(match_domain) + ` }`,
342+
"cond_test": `{ hdr(host) -i ` + strings.TrimSpace(match_domain) + ` } !letsencrypt-acl`,
344343
}
345344
// Create request bytes
346345
add_https_redirect_rule_request_body_bytes, err := json.Marshal(add_https_redirect_rule_request_body)
@@ -386,7 +385,7 @@ func (s Manager) DeleteHTTPRedirectRule(transaction_id string, match_domain stri
386385
get_http_redirect_rules := get_http_redirect_rules_res_body_json["data"].([]interface{})
387386
for _, http_redirect_rule := range get_http_redirect_rules {
388387
http_redirect_rule_item := http_redirect_rule.(map[string]interface{})
389-
if http_redirect_rule_item["cond_test"] == `{ hdr(host) -i `+strings.TrimSpace(match_domain)+` }` {
388+
if http_redirect_rule_item["cond_test"] == `{ hdr(host) -i `+strings.TrimSpace(match_domain)+` } !letsencrypt-acl` {
390389
index = int(http_redirect_rule_item["index"].(float64))
391390
break
392391
}
@@ -406,3 +405,54 @@ func (s Manager) DeleteHTTPRedirectRule(transaction_id string, match_domain stri
406405
}
407406
return nil
408407
}
408+
409+
// Delete HTTPS Redirect Rule
410+
func (s Manager) DeleteHTTPSRedirectRule(transaction_id string, match_domain string) error {
411+
if strings.TrimSpace(match_domain) == "" {
412+
return errors.New("match domain is required")
413+
}
414+
// Fetch all HTTPS Redirect Rules
415+
get_https_redirect_rules_request_query_params := QueryParameters{}
416+
get_https_redirect_rules_request_query_params.add("transaction_id", transaction_id)
417+
get_https_redirect_rules_request_query_params.add("parent_name", "fe_https")
418+
get_https_redirect_rules_request_query_params.add("parent_type", "frontend")
419+
get_https_redirect_rules_res, get_https_redirect_rules_err := s.getRequest("/services/haproxy/configuration/http_request_rules", get_https_redirect_rules_request_query_params)
420+
if get_https_redirect_rules_err != nil || !isValidStatusCode(get_https_redirect_rules_res.StatusCode) {
421+
return errors.New("failed to fetch https redirect rules")
422+
}
423+
defer get_https_redirect_rules_res.Body.Close()
424+
get_https_redirect_rules_res_body, get_https_redirect_rules_res_body_err := io.ReadAll(get_https_redirect_rules_res.Body)
425+
if get_https_redirect_rules_res_body_err != nil {
426+
return errors.New("failed to read https redirect rules response body")
427+
}
428+
get_https_redirect_rules_res_body_json := map[string]interface{}{}
429+
get_https_redirect_rules_res_body_json_err := json.Unmarshal(get_https_redirect_rules_res_body, &get_https_redirect_rules_res_body_json)
430+
if get_https_redirect_rules_res_body_json_err != nil {
431+
log.Println(get_https_redirect_rules_res_body_json_err)
432+
return errors.New("failed to unmarshal https redirect rules response body")
433+
}
434+
// Find index of HTTPS Redirect Rule
435+
index := -1
436+
get_https_redirect_rules := get_https_redirect_rules_res_body_json["data"].([]interface{})
437+
for _, https_redirect_rule := range get_https_redirect_rules {
438+
https_redirect_rule_item := https_redirect_rule.(map[string]interface{})
439+
if https_redirect_rule_item["cond_test"] == `{ hdr(host) -i `+strings.TrimSpace(match_domain)+` } !letsencrypt-acl` {
440+
index = int(https_redirect_rule_item["index"].(float64))
441+
break
442+
}
443+
}
444+
// Delete HTTPS Redirect Rule
445+
if index != -1 {
446+
delete_https_redirect_rule_request_query_params := QueryParameters{}
447+
delete_https_redirect_rule_request_query_params.add("transaction_id", transaction_id)
448+
delete_https_redirect_rule_request_query_params.add("parent_name", "fe_https")
449+
delete_https_redirect_rule_request_query_params.add("parent_type", "frontend")
450+
// Send request
451+
delete_https_redirect_rule_res, delete_https_redirect_rule := s.deleteRequest("/services/haproxy/configuration/http_request_rules/"+strconv.Itoa(index), delete_https_redirect_rule_request_query_params)
452+
if delete_https_redirect_rule != nil || !isValidStatusCode(delete_https_redirect_rule_res.StatusCode) {
453+
return errors.New("failed to delete https redirect rule")
454+
}
455+
return nil
456+
}
457+
return nil
458+
}

swiftwave_service/core/ingress_rule.operations.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,13 @@ func (ingressRule *IngressRule) Create(ctx context.Context, db gorm.DB, restrict
8181
return errors.New("there is ingress rule with same port")
8282
}
8383
}
84+
// check if there is no redirect rule with same domain and port
85+
if (ingressRule.Protocol == HTTPProtocol && ingressRule.Port == 80) || ingressRule.Protocol == HTTPSProtocol {
86+
isRedirectRuleExist := db.Where("domain_id = ? AND protocol = ?", ingressRule.DomainID, ingressRule.Protocol).First(&RedirectRule{}).RowsAffected > 0
87+
if isRedirectRuleExist {
88+
return errors.New("there is redirect rule with same domain and port")
89+
}
90+
}
8491

8592
// create record
8693
tx := db.Create(&ingressRule)

swiftwave_service/core/models.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ type IngressRule struct {
6161
type RedirectRule struct {
6262
ID uint `json:"id" gorm:"primaryKey"`
6363
DomainID uint `json:"domainID"`
64-
Port uint `json:"port"`
64+
Protocol ProtocolType `json:"protocol"`
6565
RedirectURL string `json:"redirectURL"`
6666
Status RedirectRuleStatus `json:"status"`
6767
CreatedAt time.Time `json:"createdAt"`

swiftwave_service/core/redirect_rule.oprations.go

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,25 @@ func (redirectRule *RedirectRule) Create(ctx context.Context, db gorm.DB) error
3737
return err
3838
}
3939
// verify if there is no ingress rule with same domain and port
40-
isIngressRuleExist := db.Where("domain_id = ? AND port = ?", redirectRule.DomainID, redirectRule.Port).First(&IngressRule{}).RowsAffected > 0
40+
if redirectRule.Protocol != HTTPProtocol && redirectRule.Protocol != HTTPSProtocol {
41+
return errors.New("invalid protocol")
42+
}
43+
var isIngressRuleExist bool
44+
/*
45+
* For redirect rule with HTTP protocol, port will be anyhow 80
46+
* For redirect rule with HTTPS protocol, port will be anyhow 443
47+
* So, we can check if there is any ingress rule with same domain and port
48+
*/
49+
if redirectRule.Protocol == HTTPProtocol {
50+
isIngressRuleExist = db.Where("domain_id = ? AND protocol = ? AND port = ?", redirectRule.DomainID, redirectRule.Protocol, 80).First(&IngressRule{}).RowsAffected > 0
51+
} else if redirectRule.Protocol == HTTPSProtocol {
52+
isIngressRuleExist = db.Where("domain_id = ? AND protocol = ? AND port = ?", redirectRule.DomainID, redirectRule.Protocol, 443).First(&IngressRule{}).RowsAffected > 0
53+
}
4154
if isIngressRuleExist {
4255
return errors.New("there is ingress rule with same domain and port")
4356
}
44-
// verify if there is no redirect rule with same domain and port
45-
isRedirectRuleExist := db.Where("domain_id = ? AND port = ?", redirectRule.DomainID, redirectRule.Port).First(&RedirectRule{}).RowsAffected > 0
57+
// verify if there is no redirect rule with same domain and protocl
58+
isRedirectRuleExist := db.Where("domain_id = ? AND protocol = ?", redirectRule.DomainID, redirectRule.Protocol).First(&RedirectRule{}).RowsAffected > 0
4659
if isRedirectRuleExist {
4760
return errors.New("there is redirect rule with same domain and port")
4861
}

swiftwave_service/graphql/generated.go

Lines changed: 1 addition & 73 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

swiftwave_service/graphql/graphql_object_mapper.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ func ingressRuleToGraphqlObject(record *core.IngressRule) *model.IngressRule {
271271
func redirectRuleInputToDatabaseObject(record *model.RedirectRuleInput) *core.RedirectRule {
272272
return &core.RedirectRule{
273273
DomainID: record.DomainID,
274-
Port: record.Port,
274+
Protocol: core.ProtocolType(record.Protocol),
275275
RedirectURL: record.RedirectURL,
276276
Status: core.RedirectRuleStatusPending,
277277
CreatedAt: time.Now(),
@@ -284,7 +284,7 @@ func redirectRuleToGraphqlObject(record *core.RedirectRule) *model.RedirectRule
284284
return &model.RedirectRule{
285285
ID: record.ID,
286286
DomainID: record.DomainID,
287-
Port: record.Port,
287+
Protocol: model.ProtocolType(record.Protocol),
288288
RedirectURL: record.RedirectURL,
289289
Status: model.RedirectRuleStatus(record.Status),
290290
CreatedAt: record.CreatedAt,

swiftwave_service/graphql/model/models_gen.go

Lines changed: 0 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

swiftwave_service/graphql/redirect_rule.resolvers.go

Lines changed: 0 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

swiftwave_service/graphql/schema/redirect_rule.graphqls

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ enum RedirectRuleStatus {
88
input RedirectRuleInput {
99
domainId: Uint!
1010
protocol: ProtocolType!
11-
port: Uint!
1211
redirectURL: String!
1312
}
1413

@@ -17,7 +16,6 @@ type RedirectRule {
1716
domainId: Uint!
1817
domain: Domain!
1918
protocol: ProtocolType!
20-
port: Uint!
2119
redirectURL: String!
2220
status: RedirectRuleStatus!
2321
createdAt: Time!

swiftwave_service/worker/process_redirect_rule_apply_request.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,12 @@ func (m Manager) RedirectRuleApply(request RedirectRuleApplyRequest, ctx context
3636
if err != nil {
3737
return err
3838
}
39-
// TODO add support for https and custom tcp port
4039
// add redirect
41-
err = m.ServiceManager.HaproxyManager.AddHTTPRedirectRule(haproxyTransactionId, domain.Name, redirectRule.RedirectURL)
40+
if redirectRule.Protocol == core.HTTPProtocol {
41+
err = m.ServiceManager.HaproxyManager.AddHTTPRedirectRule(haproxyTransactionId, domain.Name, redirectRule.RedirectURL)
42+
} else {
43+
err = m.ServiceManager.HaproxyManager.AddHTTPSRedirectRule(haproxyTransactionId, domain.Name, redirectRule.RedirectURL)
44+
}
4245
if err != nil {
4346
// set status as failed and exit
4447
_ = redirectRule.UpdateStatus(ctx, dbWithoutTx, core.RedirectRuleStatusFailed)

0 commit comments

Comments
 (0)