From 464307b843c526fe37c654ced3e72fdffb1e887d Mon Sep 17 00:00:00 2001 From: Shubham Tiwari Date: Wed, 15 Nov 2023 15:52:02 +0530 Subject: [PATCH 1/6] feat: added data residency for eu and global regions --- base_interface.go | 34 ++++++++++++++++++++++++++++++++++ sendgrid.go | 26 ++++++++++++++++++++------ sendgrid_test.go | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+), 6 deletions(-) diff --git a/base_interface.go b/base_interface.go index ae826811..b4775770 100644 --- a/base_interface.go +++ b/base_interface.go @@ -5,6 +5,8 @@ import ( "compress/gzip" "context" "errors" + "fmt" + "log" "net/http" "strconv" "time" @@ -20,11 +22,17 @@ const ( rateLimitSleep = 1100 ) +var allowedRegionsHostMap = map[string]string{ + "eu": "https://api.eu.sendgrid.com", + "global": "https://api.sendgrid.com", +} + type options struct { Auth string Endpoint string Host string Subuser string + Region string } // Client is the Twilio SendGrid Go client @@ -49,12 +57,38 @@ func requestNew(options options) rest.Request { requestHeaders["On-Behalf-Of"] = options.Subuser } + host, err := setDataResidency(options) + if err == nil { + options.Host = host + } else { + fmt.Println(err) + log.Println(err) + } + return rest.Request{ BaseURL: options.baseURL(), Headers: requestHeaders, } } +func setDataResidency(options options) (string, error) { + currentHost := options.Host + defaultHost := allowedRegionsHostMap["global"] + if currentHost != defaultHost { // for testing, the hostname can be different + return currentHost, nil + } + region := options.Region + if region != "" { + regionalHost, isPresent := allowedRegionsHostMap[region] + if isPresent { + return regionalHost, nil + } else { + return defaultHost, errors.New("error: region can only be \"eu\" or \"global\"") + } + } + return defaultHost, nil +} + // Send sends an email through Twilio SendGrid func (cl *Client) Send(email *mail.SGMailV3) (*rest.Response, error) { return cl.SendWithContext(context.Background(), email) diff --git a/sendgrid.go b/sendgrid.go index 7192bec2..fc8a2945 100644 --- a/sendgrid.go +++ b/sendgrid.go @@ -10,18 +10,27 @@ type sendGridOptions struct { Endpoint string Host string Subuser string + Region string } // GetRequest // @return [Request] a default request object -func GetRequest(key, endpoint, host string) rest.Request { - return createSendGridRequest(sendGridOptions{key, endpoint, host, ""}) +func GetRequest(key, endpoint, host string, regionOptional ...string) rest.Request { + region := "" + if len(regionOptional) > 0 { + region = regionOptional[0] + } + return createSendGridRequest(sendGridOptions{key, endpoint, host, "", region}) } // GetRequestSubuser like GetRequest but with On-Behalf of Subuser // @return [Request] a default request object -func GetRequestSubuser(key, endpoint, host, subuser string) rest.Request { - return createSendGridRequest(sendGridOptions{key, endpoint, host, subuser}) +func GetRequestSubuser(key, endpoint, host, subuser string, regionOptional ...string) rest.Request { + region := "" + if len(regionOptional) > 0 { + region = regionOptional[0] + } + return createSendGridRequest(sendGridOptions{key, endpoint, host, subuser, region}) } // createSendGridRequest create Request @@ -32,6 +41,7 @@ func createSendGridRequest(sgOptions sendGridOptions) rest.Request { sgOptions.Endpoint, sgOptions.Host, sgOptions.Subuser, + sgOptions.Region, } if options.Host == "" { @@ -42,8 +52,12 @@ func createSendGridRequest(sgOptions sendGridOptions) rest.Request { } // NewSendClient constructs a new Twilio SendGrid client given an API key -func NewSendClient(key string) *Client { - request := GetRequest(key, "/v3/mail/send", "") +func NewSendClient(key string, regionOptional ...string) *Client { + region := "" + if len(regionOptional) > 0 { + region = regionOptional[0] + } + request := GetRequest(key, "/v3/mail/send", "", region) request.Method = "POST" return &Client{request} } diff --git a/sendgrid_test.go b/sendgrid_test.go index ada4dfe1..22d70511 100644 --- a/sendgrid_test.go +++ b/sendgrid_test.go @@ -1,9 +1,11 @@ package sendgrid import ( + "bytes" "context" "encoding/json" "fmt" + "log" "net/http" "net/http/httptest" "os" @@ -81,6 +83,41 @@ func TestGetRequestSubuser(t *testing.T) { ShouldHaveHeaders(&request, t) } +func Test_test_set_residency_eu(t *testing.T) { + request := GetRequest("API_KEY", "", "", "eu") + assert.Equal(t, "https://api.eu.sendgrid.com", request.BaseURL, "Host not correct as per the region") +} + +func Test_test_set_residency_global(t *testing.T) { + request := GetRequest("API_KEY", "", "https://api.sendgrid.com", "global") + assert.Equal(t, "https://api.sendgrid.com", request.BaseURL, "Host not correct as per the region") +} + +func Test_test_set_residency_override_host(t *testing.T) { + request := GetRequest("API_KEY", "", "https://api.sendgrid.com", "eu") + assert.Equal(t, "https://api.eu.sendgrid.com", request.BaseURL, "Host not correct as per the region") +} + +func Test_test_set_residency_default(t *testing.T) { + request := GetRequest("API_KEY", "", "") + assert.Equal(t, "https://api.sendgrid.com", request.BaseURL, "Host not correct as per the region") +} + +func Test_test_set_residency_incorrect_region(t *testing.T) { + var buffer bytes.Buffer + log.SetOutput(&buffer) + request := GetRequest("API_KEY", "", "", "foo") + + log.SetOutput(new(bytes.Buffer)) + capturedOutput := buffer.String() + + expectedErrorMessage := "error: region can only be \"eu\" or \"global\"" + if !strings.Contains(capturedOutput, expectedErrorMessage) { + t.Errorf("Expected error message '%s' not found on setting invalid region", expectedErrorMessage) + } + assert.Equal(t, "https://api.sendgrid.com", request.BaseURL, "Host not correct as per the region") +} + func getRequest(endpoint string) rest.Request { return GetRequest("SENDGRID_APIKEY", endpoint, "") } From f632e619297ab74f285f714a0c3a8a5604039294 Mon Sep 17 00:00:00 2001 From: Shubham Tiwari Date: Wed, 15 Nov 2023 15:52:02 +0530 Subject: [PATCH 2/6] feat: added data residency for eu and global regions --- base_interface.go | 34 +++++++++++ examples/dataresidency/setRegion.go | 87 +++++++++++++++++++++++++++++ sendgrid.go | 26 +++++++-- sendgrid_test.go | 37 ++++++++++++ 4 files changed, 178 insertions(+), 6 deletions(-) create mode 100644 examples/dataresidency/setRegion.go diff --git a/base_interface.go b/base_interface.go index ae826811..b4775770 100644 --- a/base_interface.go +++ b/base_interface.go @@ -5,6 +5,8 @@ import ( "compress/gzip" "context" "errors" + "fmt" + "log" "net/http" "strconv" "time" @@ -20,11 +22,17 @@ const ( rateLimitSleep = 1100 ) +var allowedRegionsHostMap = map[string]string{ + "eu": "https://api.eu.sendgrid.com", + "global": "https://api.sendgrid.com", +} + type options struct { Auth string Endpoint string Host string Subuser string + Region string } // Client is the Twilio SendGrid Go client @@ -49,12 +57,38 @@ func requestNew(options options) rest.Request { requestHeaders["On-Behalf-Of"] = options.Subuser } + host, err := setDataResidency(options) + if err == nil { + options.Host = host + } else { + fmt.Println(err) + log.Println(err) + } + return rest.Request{ BaseURL: options.baseURL(), Headers: requestHeaders, } } +func setDataResidency(options options) (string, error) { + currentHost := options.Host + defaultHost := allowedRegionsHostMap["global"] + if currentHost != defaultHost { // for testing, the hostname can be different + return currentHost, nil + } + region := options.Region + if region != "" { + regionalHost, isPresent := allowedRegionsHostMap[region] + if isPresent { + return regionalHost, nil + } else { + return defaultHost, errors.New("error: region can only be \"eu\" or \"global\"") + } + } + return defaultHost, nil +} + // Send sends an email through Twilio SendGrid func (cl *Client) Send(email *mail.SGMailV3) (*rest.Response, error) { return cl.SendWithContext(context.Background(), email) diff --git a/examples/dataresidency/setRegion.go b/examples/dataresidency/setRegion.go new file mode 100644 index 00000000..40ee0a34 --- /dev/null +++ b/examples/dataresidency/setRegion.go @@ -0,0 +1,87 @@ +package main + +import ( + "fmt" + "github.com/sendgrid/rest" + "github.com/sendgrid/sendgrid-go/helpers/mail" + "log" + "os" + + "github.com/sendgrid/sendgrid-go" +) + +var SAMPLE_EMAIL = "test@example.com" + +// SetDataResidency : Set region for sendgrid. +func SetDataResidencyGlobal() { + message := buildHelloEmail() + request := buildSendgridObj("global") + request.Body = mail.GetRequestBody(message) + response, err := sendgrid.API(request) + if err != nil { + log.Println(err) + } else { + fmt.Println(response.StatusCode) + fmt.Println(response.Body) + fmt.Println(response.Headers) + } +} + +func SetDataResidencyEu() { + message := buildHelloEmail() + request := buildSendgridObj("eu") + request.Body = mail.GetRequestBody(message) + response, err := sendgrid.API(request) + if err != nil { + log.Println(err) + } else { + fmt.Println(response.StatusCode) + fmt.Println(response.Body) + fmt.Println(response.Headers) + } +} + +func SetDataResidencyDefault() { + message := buildHelloEmail() + request := sendgrid.GetRequest(os.Getenv("SENDGRID_API_KEY"), "/v3/mail/send", "") + request.Method = "POST" + request.Body = mail.GetRequestBody(message) + response, err := sendgrid.API(request) + if err != nil { + log.Println(err) + } else { + fmt.Println(response.StatusCode) + fmt.Println(response.Body) + fmt.Println(response.Headers) + } +} + +func buildHelloEmail() *mail.SGMailV3 { + // Note that when you use this constructor an initial personalization object + // is created for you. It can be accessed via + // mail.personalization.get(0) as it is a List object + + from := mail.NewEmail("test_user", SAMPLE_EMAIL) + subject := "Sending with Twilio SendGrid is Fun" + to := mail.NewEmail("test_user", SAMPLE_EMAIL) + plainTextContent := "and easy to do anywhere, even with Go" + htmlContent := "and easy to do anywhere, even with Go" + message := mail.NewSingleEmail(from, subject, to, plainTextContent, htmlContent) + email := mail.NewEmail("test_user", SAMPLE_EMAIL) + + p := mail.NewPersonalization() + p.AddTos(email) + message.AddPersonalizations(p) + + return message +} + +func buildSendgridObj(region string) rest.Request { + request := sendgrid.GetRequest(os.Getenv("SENDGRID_API_KEY"), "/v3/mail/send", "", region) + request.Method = "POST" + return request +} + +func main() { + // add your function calls here +} diff --git a/sendgrid.go b/sendgrid.go index 7192bec2..fc8a2945 100644 --- a/sendgrid.go +++ b/sendgrid.go @@ -10,18 +10,27 @@ type sendGridOptions struct { Endpoint string Host string Subuser string + Region string } // GetRequest // @return [Request] a default request object -func GetRequest(key, endpoint, host string) rest.Request { - return createSendGridRequest(sendGridOptions{key, endpoint, host, ""}) +func GetRequest(key, endpoint, host string, regionOptional ...string) rest.Request { + region := "" + if len(regionOptional) > 0 { + region = regionOptional[0] + } + return createSendGridRequest(sendGridOptions{key, endpoint, host, "", region}) } // GetRequestSubuser like GetRequest but with On-Behalf of Subuser // @return [Request] a default request object -func GetRequestSubuser(key, endpoint, host, subuser string) rest.Request { - return createSendGridRequest(sendGridOptions{key, endpoint, host, subuser}) +func GetRequestSubuser(key, endpoint, host, subuser string, regionOptional ...string) rest.Request { + region := "" + if len(regionOptional) > 0 { + region = regionOptional[0] + } + return createSendGridRequest(sendGridOptions{key, endpoint, host, subuser, region}) } // createSendGridRequest create Request @@ -32,6 +41,7 @@ func createSendGridRequest(sgOptions sendGridOptions) rest.Request { sgOptions.Endpoint, sgOptions.Host, sgOptions.Subuser, + sgOptions.Region, } if options.Host == "" { @@ -42,8 +52,12 @@ func createSendGridRequest(sgOptions sendGridOptions) rest.Request { } // NewSendClient constructs a new Twilio SendGrid client given an API key -func NewSendClient(key string) *Client { - request := GetRequest(key, "/v3/mail/send", "") +func NewSendClient(key string, regionOptional ...string) *Client { + region := "" + if len(regionOptional) > 0 { + region = regionOptional[0] + } + request := GetRequest(key, "/v3/mail/send", "", region) request.Method = "POST" return &Client{request} } diff --git a/sendgrid_test.go b/sendgrid_test.go index ada4dfe1..22d70511 100644 --- a/sendgrid_test.go +++ b/sendgrid_test.go @@ -1,9 +1,11 @@ package sendgrid import ( + "bytes" "context" "encoding/json" "fmt" + "log" "net/http" "net/http/httptest" "os" @@ -81,6 +83,41 @@ func TestGetRequestSubuser(t *testing.T) { ShouldHaveHeaders(&request, t) } +func Test_test_set_residency_eu(t *testing.T) { + request := GetRequest("API_KEY", "", "", "eu") + assert.Equal(t, "https://api.eu.sendgrid.com", request.BaseURL, "Host not correct as per the region") +} + +func Test_test_set_residency_global(t *testing.T) { + request := GetRequest("API_KEY", "", "https://api.sendgrid.com", "global") + assert.Equal(t, "https://api.sendgrid.com", request.BaseURL, "Host not correct as per the region") +} + +func Test_test_set_residency_override_host(t *testing.T) { + request := GetRequest("API_KEY", "", "https://api.sendgrid.com", "eu") + assert.Equal(t, "https://api.eu.sendgrid.com", request.BaseURL, "Host not correct as per the region") +} + +func Test_test_set_residency_default(t *testing.T) { + request := GetRequest("API_KEY", "", "") + assert.Equal(t, "https://api.sendgrid.com", request.BaseURL, "Host not correct as per the region") +} + +func Test_test_set_residency_incorrect_region(t *testing.T) { + var buffer bytes.Buffer + log.SetOutput(&buffer) + request := GetRequest("API_KEY", "", "", "foo") + + log.SetOutput(new(bytes.Buffer)) + capturedOutput := buffer.String() + + expectedErrorMessage := "error: region can only be \"eu\" or \"global\"" + if !strings.Contains(capturedOutput, expectedErrorMessage) { + t.Errorf("Expected error message '%s' not found on setting invalid region", expectedErrorMessage) + } + assert.Equal(t, "https://api.sendgrid.com", request.BaseURL, "Host not correct as per the region") +} + func getRequest(endpoint string) rest.Request { return GetRequest("SENDGRID_APIKEY", endpoint, "") } From 6bf20e2bbc130ee8859fbc05b06e384b253022e7 Mon Sep 17 00:00:00 2001 From: Shubham Tiwari Date: Fri, 17 Nov 2023 14:28:55 +0530 Subject: [PATCH 3/6] fix: added setters for host and data residency --- base_interface.go | 52 ++++++++++++++++------------- examples/dataresidency/setRegion.go | 47 ++++++++++++++++---------- sendgrid.go | 26 ++++----------- sendgrid_test.go | 42 ++++++++++++++--------- 4 files changed, 90 insertions(+), 77 deletions(-) diff --git a/base_interface.go b/base_interface.go index b4775770..9bf4d1a2 100644 --- a/base_interface.go +++ b/base_interface.go @@ -5,9 +5,8 @@ import ( "compress/gzip" "context" "errors" - "fmt" - "log" "net/http" + "net/url" "strconv" "time" @@ -32,7 +31,6 @@ type options struct { Endpoint string Host string Subuser string - Region string } // Client is the Twilio SendGrid Go client @@ -57,36 +55,42 @@ func requestNew(options options) rest.Request { requestHeaders["On-Behalf-Of"] = options.Subuser } - host, err := setDataResidency(options) - if err == nil { - options.Host = host - } else { - fmt.Println(err) - log.Println(err) - } - return rest.Request{ BaseURL: options.baseURL(), Headers: requestHeaders, } } -func setDataResidency(options options) (string, error) { - currentHost := options.Host - defaultHost := allowedRegionsHostMap["global"] - if currentHost != defaultHost { // for testing, the hostname can be different - return currentHost, nil +func ExtractEndpoint(link string) (string, error) { + parsedURL, err := url.Parse(link) + if err != nil { + return "", err + } + + return parsedURL.Path, nil +} + +func SetHost(request rest.Request, host string) (rest.Request, error) { + endpoint, err := ExtractEndpoint(request.BaseURL) + if err != nil { + return request, err } - region := options.Region - if region != "" { - regionalHost, isPresent := allowedRegionsHostMap[region] - if isPresent { - return regionalHost, nil - } else { - return defaultHost, errors.New("error: region can only be \"eu\" or \"global\"") + + request.BaseURL = host + endpoint + return request, nil +} + +func SetDataResidency(request rest.Request, region string) (rest.Request, error) { + regionalHost, isPresent := allowedRegionsHostMap[region] + if isPresent { + request, err := SetHost(request, regionalHost) + if err != nil { + return request, err } + return request, nil } - return defaultHost, nil + + return request, errors.New("error: region can only be \"eu\" or \"global\"") } // Send sends an email through Twilio SendGrid diff --git a/examples/dataresidency/setRegion.go b/examples/dataresidency/setRegion.go index 40ee0a34..8376c67b 100644 --- a/examples/dataresidency/setRegion.go +++ b/examples/dataresidency/setRegion.go @@ -2,11 +2,12 @@ package main import ( "fmt" - "github.com/sendgrid/rest" - "github.com/sendgrid/sendgrid-go/helpers/mail" "log" "os" + "github.com/sendgrid/rest" + "github.com/sendgrid/sendgrid-go/helpers/mail" + "github.com/sendgrid/sendgrid-go" ) @@ -15,29 +16,37 @@ var SAMPLE_EMAIL = "test@example.com" // SetDataResidency : Set region for sendgrid. func SetDataResidencyGlobal() { message := buildHelloEmail() - request := buildSendgridObj("global") - request.Body = mail.GetRequestBody(message) - response, err := sendgrid.API(request) + request, err := buildSendgridObj("global") if err != nil { log.Println(err) } else { - fmt.Println(response.StatusCode) - fmt.Println(response.Body) - fmt.Println(response.Headers) + request.Body = mail.GetRequestBody(message) + response, err := sendgrid.API(request) + if err != nil { + log.Println(err) + } else { + fmt.Println(response.StatusCode) + fmt.Println(response.Body) + fmt.Println(response.Headers) + } } } func SetDataResidencyEu() { message := buildHelloEmail() - request := buildSendgridObj("eu") - request.Body = mail.GetRequestBody(message) - response, err := sendgrid.API(request) + request, err := buildSendgridObj("eu") if err != nil { log.Println(err) } else { - fmt.Println(response.StatusCode) - fmt.Println(response.Body) - fmt.Println(response.Headers) + request.Body = mail.GetRequestBody(message) + response, err := sendgrid.API(request) + if err != nil { + log.Println(err) + } else { + fmt.Println(response.StatusCode) + fmt.Println(response.Body) + fmt.Println(response.Headers) + } } } @@ -76,10 +85,14 @@ func buildHelloEmail() *mail.SGMailV3 { return message } -func buildSendgridObj(region string) rest.Request { - request := sendgrid.GetRequest(os.Getenv("SENDGRID_API_KEY"), "/v3/mail/send", "", region) +func buildSendgridObj(region string) (rest.Request, error) { + request := sendgrid.GetRequest(os.Getenv("SENDGRID_API_KEY"), "/v3/mail/send", "") request.Method = "POST" - return request + request, err := sendgrid.SetDataResidency(request, region) + if err != nil { + return request, err + } + return request, nil } func main() { diff --git a/sendgrid.go b/sendgrid.go index fc8a2945..7192bec2 100644 --- a/sendgrid.go +++ b/sendgrid.go @@ -10,27 +10,18 @@ type sendGridOptions struct { Endpoint string Host string Subuser string - Region string } // GetRequest // @return [Request] a default request object -func GetRequest(key, endpoint, host string, regionOptional ...string) rest.Request { - region := "" - if len(regionOptional) > 0 { - region = regionOptional[0] - } - return createSendGridRequest(sendGridOptions{key, endpoint, host, "", region}) +func GetRequest(key, endpoint, host string) rest.Request { + return createSendGridRequest(sendGridOptions{key, endpoint, host, ""}) } // GetRequestSubuser like GetRequest but with On-Behalf of Subuser // @return [Request] a default request object -func GetRequestSubuser(key, endpoint, host, subuser string, regionOptional ...string) rest.Request { - region := "" - if len(regionOptional) > 0 { - region = regionOptional[0] - } - return createSendGridRequest(sendGridOptions{key, endpoint, host, subuser, region}) +func GetRequestSubuser(key, endpoint, host, subuser string) rest.Request { + return createSendGridRequest(sendGridOptions{key, endpoint, host, subuser}) } // createSendGridRequest create Request @@ -41,7 +32,6 @@ func createSendGridRequest(sgOptions sendGridOptions) rest.Request { sgOptions.Endpoint, sgOptions.Host, sgOptions.Subuser, - sgOptions.Region, } if options.Host == "" { @@ -52,12 +42,8 @@ func createSendGridRequest(sgOptions sendGridOptions) rest.Request { } // NewSendClient constructs a new Twilio SendGrid client given an API key -func NewSendClient(key string, regionOptional ...string) *Client { - region := "" - if len(regionOptional) > 0 { - region = regionOptional[0] - } - request := GetRequest(key, "/v3/mail/send", "", region) +func NewSendClient(key string) *Client { + request := GetRequest(key, "/v3/mail/send", "") request.Method = "POST" return &Client{request} } diff --git a/sendgrid_test.go b/sendgrid_test.go index 22d70511..a0e2150b 100644 --- a/sendgrid_test.go +++ b/sendgrid_test.go @@ -1,11 +1,9 @@ package sendgrid import ( - "bytes" "context" "encoding/json" "fmt" - "log" "net/http" "net/http/httptest" "os" @@ -84,37 +82,49 @@ func TestGetRequestSubuser(t *testing.T) { } func Test_test_set_residency_eu(t *testing.T) { - request := GetRequest("API_KEY", "", "", "eu") + request := GetRequest("API_KEY", "", "") + request, err := SetDataResidency(request, "eu") + assert.Nil(t, err) assert.Equal(t, "https://api.eu.sendgrid.com", request.BaseURL, "Host not correct as per the region") } func Test_test_set_residency_global(t *testing.T) { - request := GetRequest("API_KEY", "", "https://api.sendgrid.com", "global") + request := GetRequest("API_KEY", "", "https://api.sendgrid.com") + request, err := SetDataResidency(request, "global") + assert.Nil(t, err) assert.Equal(t, "https://api.sendgrid.com", request.BaseURL, "Host not correct as per the region") } func Test_test_set_residency_override_host(t *testing.T) { - request := GetRequest("API_KEY", "", "https://api.sendgrid.com", "eu") + request := GetRequest("API_KEY", "", "https://test.api.com") + request, err := SetDataResidency(request, "eu") + assert.Nil(t, err) assert.Equal(t, "https://api.eu.sendgrid.com", request.BaseURL, "Host not correct as per the region") } -func Test_test_set_residency_default(t *testing.T) { +func Test_test_set_residency_override_data_residency(t *testing.T) { request := GetRequest("API_KEY", "", "") - assert.Equal(t, "https://api.sendgrid.com", request.BaseURL, "Host not correct as per the region") + request, err := SetDataResidency(request, "eu") + assert.Nil(t, err) + request, err = SetHost(request, "https://test.api.com") + assert.Nil(t, err) + assert.Equal(t, "https://test.api.com", request.BaseURL, "Host not correct as per the region") } func Test_test_set_residency_incorrect_region(t *testing.T) { - var buffer bytes.Buffer - log.SetOutput(&buffer) - request := GetRequest("API_KEY", "", "", "foo") + request := GetRequest("API_KEY", "", "") + _, err := SetDataResidency(request, "foo") + assert.NotNil(t, err, "error: region can only be \"eu\" or \"global\"") +} - log.SetOutput(new(bytes.Buffer)) - capturedOutput := buffer.String() +func Test_test_set_residency_null_region(t *testing.T) { + request := GetRequest("API_KEY", "", "") + _, err := SetDataResidency(request, "") + assert.NotNil(t, err, "error: region can only be \"eu\" or \"global\"") +} - expectedErrorMessage := "error: region can only be \"eu\" or \"global\"" - if !strings.Contains(capturedOutput, expectedErrorMessage) { - t.Errorf("Expected error message '%s' not found on setting invalid region", expectedErrorMessage) - } +func Test_test_set_residency_default_region(t *testing.T) { + request := GetRequest("API_KEY", "", "") assert.Equal(t, "https://api.sendgrid.com", request.BaseURL, "Host not correct as per the region") } From db85c0a036b04870e1fb416ed6d3567fd0b78645 Mon Sep 17 00:00:00 2001 From: Shubham Tiwari Date: Mon, 20 Nov 2023 13:52:05 +0530 Subject: [PATCH 4/6] chore: corrected the naming of test cases --- sendgrid_test.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/sendgrid_test.go b/sendgrid_test.go index a0e2150b..365d46e5 100644 --- a/sendgrid_test.go +++ b/sendgrid_test.go @@ -81,28 +81,28 @@ func TestGetRequestSubuser(t *testing.T) { ShouldHaveHeaders(&request, t) } -func Test_test_set_residency_eu(t *testing.T) { +func TestSetDataResidencyEU(t *testing.T) { request := GetRequest("API_KEY", "", "") request, err := SetDataResidency(request, "eu") assert.Nil(t, err) assert.Equal(t, "https://api.eu.sendgrid.com", request.BaseURL, "Host not correct as per the region") } -func Test_test_set_residency_global(t *testing.T) { +func TestSetDataResidencyGlobal(t *testing.T) { request := GetRequest("API_KEY", "", "https://api.sendgrid.com") request, err := SetDataResidency(request, "global") assert.Nil(t, err) assert.Equal(t, "https://api.sendgrid.com", request.BaseURL, "Host not correct as per the region") } -func Test_test_set_residency_override_host(t *testing.T) { +func TestSetDataResidencyOverrideHost(t *testing.T) { request := GetRequest("API_KEY", "", "https://test.api.com") request, err := SetDataResidency(request, "eu") assert.Nil(t, err) assert.Equal(t, "https://api.eu.sendgrid.com", request.BaseURL, "Host not correct as per the region") } -func Test_test_set_residency_override_data_residency(t *testing.T) { +func TestSetDataResidencyOverrideDataResidency(t *testing.T) { request := GetRequest("API_KEY", "", "") request, err := SetDataResidency(request, "eu") assert.Nil(t, err) @@ -111,19 +111,19 @@ func Test_test_set_residency_override_data_residency(t *testing.T) { assert.Equal(t, "https://test.api.com", request.BaseURL, "Host not correct as per the region") } -func Test_test_set_residency_incorrect_region(t *testing.T) { +func TestSetDataResidencyIncorrectRegion(t *testing.T) { request := GetRequest("API_KEY", "", "") _, err := SetDataResidency(request, "foo") assert.NotNil(t, err, "error: region can only be \"eu\" or \"global\"") } -func Test_test_set_residency_null_region(t *testing.T) { +func TestSetDataResidencyNullRegion(t *testing.T) { request := GetRequest("API_KEY", "", "") _, err := SetDataResidency(request, "") assert.NotNil(t, err, "error: region can only be \"eu\" or \"global\"") } -func Test_test_set_residency_default_region(t *testing.T) { +func TestSetDataResidencyDefaultRegion(t *testing.T) { request := GetRequest("API_KEY", "", "") assert.Equal(t, "https://api.sendgrid.com", request.BaseURL, "Host not correct as per the region") } From bbd252b6987aa438c31c2bdc9d6dba3d14913ae5 Mon Sep 17 00:00:00 2001 From: Shubham Tiwari Date: Mon, 20 Nov 2023 13:53:05 +0530 Subject: [PATCH 5/6] chore: added inline documentation for SetDataResidency and SetHost --- base_interface.go | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/base_interface.go b/base_interface.go index 9bf4d1a2..156fcd2d 100644 --- a/base_interface.go +++ b/base_interface.go @@ -61,7 +61,8 @@ func requestNew(options options) rest.Request { } } -func ExtractEndpoint(link string) (string, error) { +// extractEndpoint extracts the endpoint from a baseURL +func extractEndpoint(link string) (string, error) { parsedURL, err := url.Parse(link) if err != nil { return "", err @@ -70,8 +71,10 @@ func ExtractEndpoint(link string) (string, error) { return parsedURL.Path, nil } +// SetHost changes the baseURL of the request with the host passed +// @return [Request] the modified request object func SetHost(request rest.Request, host string) (rest.Request, error) { - endpoint, err := ExtractEndpoint(request.BaseURL) + endpoint, err := extractEndpoint(request.BaseURL) if err != nil { return request, err } @@ -80,17 +83,18 @@ func SetHost(request rest.Request, host string) (rest.Request, error) { return request, nil } +// SetDataResidency modifies the host as per the region +// @return [Request] the modified request object func SetDataResidency(request rest.Request, region string) (rest.Request, error) { - regionalHost, isPresent := allowedRegionsHostMap[region] - if isPresent { - request, err := SetHost(request, regionalHost) - if err != nil { - return request, err - } - return request, nil + regionalHost, present := allowedRegionsHostMap[region] + if !present { + return request, errors.New("error: region can only be \"eu\" or \"global\"") } - - return request, errors.New("error: region can only be \"eu\" or \"global\"") + request, err := SetHost(request, regionalHost) + if err != nil { + return request, err + } + return request, nil } // Send sends an email through Twilio SendGrid From 6de1585c1f317e0637c595faf940af0151030ec5 Mon Sep 17 00:00:00 2001 From: Shubham Tiwari Date: Mon, 20 Nov 2023 14:07:57 +0530 Subject: [PATCH 6/6] chore: added comment for SetDataResidency --- base_interface.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/base_interface.go b/base_interface.go index 156fcd2d..2f4e38c7 100644 --- a/base_interface.go +++ b/base_interface.go @@ -72,6 +72,14 @@ func extractEndpoint(link string) (string, error) { } // SetHost changes the baseURL of the request with the host passed +/* + * This allows support for global and eu regions only. This set will likely expand in the future. + * Global should be the default + * Global region means the message should be sent through: + * HTTP: api.sendgrid.com + * EU region means the message should be sent through: + * HTTP: api.eu.sendgrid.com + */ // @return [Request] the modified request object func SetHost(request rest.Request, host string) (rest.Request, error) { endpoint, err := extractEndpoint(request.BaseURL)