From 55f7900c1876659f7a2783df42a823496f627af3 Mon Sep 17 00:00:00 2001 From: manisha1997 Date: Fri, 28 Nov 2025 21:20:18 +0530 Subject: [PATCH 1/8] fix: Regional endpoint processing --- src/Twilio/Clients/TwilioRestClient.cs | 28 +++++++++++++++++++++++++- src/Twilio/Twilio.cs | 27 +++++++++++++++++++++++-- 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/src/Twilio/Clients/TwilioRestClient.cs b/src/Twilio/Clients/TwilioRestClient.cs index 55d6871e1..4b270e1a8 100644 --- a/src/Twilio/Clients/TwilioRestClient.cs +++ b/src/Twilio/Clients/TwilioRestClient.cs @@ -4,6 +4,7 @@ using Newtonsoft.Json; using Twilio.Exceptions; using Twilio.AuthStrategies; +using System.Collections.Generic; #if !NET35 using System.Threading.Tasks; @@ -54,6 +55,19 @@ public class TwilioRestClient : ITwilioRestClient private readonly string _password; private readonly AuthStrategy _authstrategy; + private static readonly Dictionary RegionToEdgeMap = new Dictionary + { + { "au1", "sydney" }, + { "br1", "sao-paulo" }, + { "de1", "frankfurt" }, + { "ie1", "dublin" }, + { "jp1", "tokyo" }, + { "jp2", "osaka" }, + { "sg1", "singapore" }, + { "us1", "ashburn" }, + { "us2", "umatilla" } + }; + /// /// Constructor for a TwilioRestClient /// @@ -79,6 +93,9 @@ public TwilioRestClient( AccountSid = accountSid ?? username; HttpClient = httpClient ?? DefaultClient(); + if ((string.IsNullOrEmpty(edge) && !string.IsNullOrEmpty(region)) || (string.IsNullOrEmpty(region) && !string.IsNullOrEmpty(edge))) + Console.WriteLine("Deprecation Warning: For regional processing, DNS is of format product.edge.region.twilio.com;otherwise use product.twilio.com"); + Region = region; Edge = edge; } @@ -111,6 +128,9 @@ public TwilioRestClient( AccountSid = accountSid ?? username; HttpClient = httpClient ?? DefaultClient(); + if ((string.IsNullOrEmpty(edge) && !string.IsNullOrEmpty(region)) || (string.IsNullOrEmpty(region) && !string.IsNullOrEmpty(edge))) + Console.WriteLine("Deprecation Warning: For regional processing, DNS is of format product.edge.region.twilio.com;otherwise use product.twilio.com"); + Region = region; Edge = edge; } @@ -124,6 +144,12 @@ public TwilioRestClient( public Response Request(Request request) { + if (string.IsNullOrEmpty(Edge) && !string.IsNullOrEmpty(Region) && RegionToEdgeMap.TryGetValue(Region, out var edge)) + { + Console.WriteLine("Deprecation Warning: Setting default `edge` for provided `region`"); + Edge = edge; + } + if(_username != null && _password != null){ request.SetAuth(_username, _password); } @@ -248,7 +274,7 @@ private static Response ProcessResponse(Response response) } /// - /// Test if your environment is impacted by a TLS or certificate change + /// Test if your environment is impacted by a TLS or certificate change /// by sending an HTTP request to the test endpoint tls-test.twilio.com:443 /// It's a bit easier to call this method from TwilioClient.ValidateSslCertificate(). /// diff --git a/src/Twilio/Twilio.cs b/src/Twilio/Twilio.cs index 4461ed565..a0ce19507 100644 --- a/src/Twilio/Twilio.cs +++ b/src/Twilio/Twilio.cs @@ -3,6 +3,8 @@ using Twilio.Credential; using Twilio.AuthStrategies; using Twilio.Annotations; +using System.Collections.Generic; +using System; namespace Twilio { @@ -22,6 +24,19 @@ public class TwilioClient private static string _logLevel; private static CredentialProvider _credentialProvider; + private static readonly Dictionary RegionToEdgeMap = new Dictionary + { + { "au1", "sydney" }, + { "br1", "sao-paulo" }, + { "de1", "frankfurt" }, + { "ie1", "dublin" }, + { "jp1", "tokyo" }, + { "jp2", "osaka" }, + { "sg1", "singapore" }, + { "us1", "ashburn" }, + { "us2", "umatilla" } + }; + private TwilioClient() { } /// @@ -218,6 +233,15 @@ public static ITwilioRestClient GetNoAuthRestClient() /// The rest client public static ITwilioRestClient GetRestClient() { + if ((string.IsNullOrEmpty(_edge) && !string.IsNullOrEmpty(_region)) || (string.IsNullOrEmpty(_region) && !string.IsNullOrEmpty(_edge))) + Console.WriteLine("Deprecation Warning: For regional processing, DNS is of format product.edge.region.twilio.com;otherwise use product.twilio.com"); + + if (string.IsNullOrEmpty(_edge) && !string.IsNullOrEmpty(_region) && RegionToEdgeMap.TryGetValue(_region, out var edge)) + { + Console.WriteLine("Deprecation Warning: Setting default `edge` for provided `region`"); + _edge = edge; + } + if (_restClient != null) { return _restClient; @@ -245,7 +269,6 @@ public static ITwilioRestClient GetRestClient() LogLevel = _logLevel }; } - return _restClient; } @@ -292,7 +315,7 @@ public static void InvalidateBasicCreds() } /// - /// Test if your environment is impacted by a TLS or certificate change + /// Test if your environment is impacted by a TLS or certificate change /// by sending an HTTP request to the test endpoint tls-test.twilio.com:443 /// public static void ValidateSslCertificate() From b653759dbe4db28f7486caf887ee785c4910d590 Mon Sep 17 00:00:00 2001 From: manisha1997 Date: Mon, 1 Dec 2025 13:19:00 +0530 Subject: [PATCH 2/8] fix: Regional endpoint processing --- test/Twilio.Test/Clients/TwilioRestClientTest.cs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/Twilio.Test/Clients/TwilioRestClientTest.cs b/test/Twilio.Test/Clients/TwilioRestClientTest.cs index 28cc5361c..b71a3449d 100644 --- a/test/Twilio.Test/Clients/TwilioRestClientTest.cs +++ b/test/Twilio.Test/Clients/TwilioRestClientTest.cs @@ -189,6 +189,22 @@ public async Task RequestAsyncWithUserAgentExtensions() Assert.AreEqual(request.UserAgentExtensions, userAgentExtensions); } + + [Test] + public async Task EdgeWhenRegionIsSet() + { + client.MakeRequestAsync(Arg.Any()).Returns(new Response(HttpStatusCode.OK, "OK")); + Request request = new Request(HttpMethod.Get, "https://verify.twilio.com/"); + string[] userAgentExtensions = new string[] { "twilio-run/2.0.0-test", "flex-plugin/3.4.0" }; + TwilioRestClient twilioClient = new TwilioRestClient("foo", "bar", httpClient: client); + twilioClient.SetRegion("us1"); + twilioClient.UserAgentExtensions = userAgentExtensions; + + await twilioClient.RequestAsync(request); + + Assert.AreEqual(twilioClient.GetEdge(), "ashburn"); + } + #endif } } From df3d5987f050aa34c9cbf446bf3102c4c31e2de2 Mon Sep 17 00:00:00 2001 From: manisha1997 Date: Mon, 1 Dec 2025 13:22:39 +0530 Subject: [PATCH 3/8] fix: Regional endpoint processing --- test/Twilio.Test/Clients/TwilioRestClientTest.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/test/Twilio.Test/Clients/TwilioRestClientTest.cs b/test/Twilio.Test/Clients/TwilioRestClientTest.cs index b71a3449d..6fb69a438 100644 --- a/test/Twilio.Test/Clients/TwilioRestClientTest.cs +++ b/test/Twilio.Test/Clients/TwilioRestClientTest.cs @@ -195,14 +195,13 @@ public async Task EdgeWhenRegionIsSet() { client.MakeRequestAsync(Arg.Any()).Returns(new Response(HttpStatusCode.OK, "OK")); Request request = new Request(HttpMethod.Get, "https://verify.twilio.com/"); - string[] userAgentExtensions = new string[] { "twilio-run/2.0.0-test", "flex-plugin/3.4.0" }; TwilioRestClient twilioClient = new TwilioRestClient("foo", "bar", httpClient: client); - twilioClient.SetRegion("us1"); - twilioClient.UserAgentExtensions = userAgentExtensions; + twilioClient.Region = "us1"; await twilioClient.RequestAsync(request); - Assert.AreEqual(twilioClient.GetEdge(), "ashburn"); + Assert.AreEqual(request.Edge, "ashburn"); + Assert.AreEqual(request.Region, "us1"); } #endif From f90a86af3f3acbfc4d477a91584fbb277792b431 Mon Sep 17 00:00:00 2001 From: manisha1997 Date: Mon, 1 Dec 2025 13:25:03 +0530 Subject: [PATCH 4/8] fix: Regional endpoint processing --- test/Twilio.Test/Clients/TwilioRestClientTest.cs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/test/Twilio.Test/Clients/TwilioRestClientTest.cs b/test/Twilio.Test/Clients/TwilioRestClientTest.cs index 6fb69a438..fea575200 100644 --- a/test/Twilio.Test/Clients/TwilioRestClientTest.cs +++ b/test/Twilio.Test/Clients/TwilioRestClientTest.cs @@ -195,8 +195,7 @@ public async Task EdgeWhenRegionIsSet() { client.MakeRequestAsync(Arg.Any()).Returns(new Response(HttpStatusCode.OK, "OK")); Request request = new Request(HttpMethod.Get, "https://verify.twilio.com/"); - TwilioRestClient twilioClient = new TwilioRestClient("foo", "bar", httpClient: client); - twilioClient.Region = "us1"; + TwilioRestClient twilioClient = new TwilioRestClient("foo", "bar", region: "us1", httpClient: client); await twilioClient.RequestAsync(request); @@ -204,6 +203,19 @@ public async Task EdgeWhenRegionIsSet() Assert.AreEqual(request.Region, "us1"); } + [Test] + public async Task EdgeWhenRegionIsSetAbc() + { + client.MakeRequestAsync(Arg.Any()).Returns(new Response(HttpStatusCode.OK, "OK")); + Request request = new Request(HttpMethod.Get, "https://verify.twilio.com/"); + TwilioRestClient twilioClient = new TwilioRestClient("foo", "bar", region: "abc", httpClient: client); + + await twilioClient.RequestAsync(request); + + Assert.AreEqual(request.Edge, ""); + Assert.AreEqual(request.Region, "abc"); + } + #endif } } From ff267fbe72b4652032250e2e03a819e0e2a7eb67 Mon Sep 17 00:00:00 2001 From: manisha1997 Date: Mon, 1 Dec 2025 13:31:22 +0530 Subject: [PATCH 5/8] fix: Regional endpoint processing --- test/Twilio.Test/Clients/TwilioRestClientTest.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/Twilio.Test/Clients/TwilioRestClientTest.cs b/test/Twilio.Test/Clients/TwilioRestClientTest.cs index fea575200..964b2d35d 100644 --- a/test/Twilio.Test/Clients/TwilioRestClientTest.cs +++ b/test/Twilio.Test/Clients/TwilioRestClientTest.cs @@ -199,8 +199,8 @@ public async Task EdgeWhenRegionIsSet() await twilioClient.RequestAsync(request); - Assert.AreEqual(request.Edge, "ashburn"); - Assert.AreEqual(request.Region, "us1"); + Assert.AreEqual("ashburn", request.Edge); + Assert.AreEqual("us1", request.Region); } [Test] @@ -212,8 +212,8 @@ public async Task EdgeWhenRegionIsSetAbc() await twilioClient.RequestAsync(request); - Assert.AreEqual(request.Edge, ""); - Assert.AreEqual(request.Region, "abc"); + Assert.AreEqual("", request.Edge); + Assert.AreEqual("abc", request.Region); } #endif From ea07a495ec036dc921b3815bce75525eac29ddb4 Mon Sep 17 00:00:00 2001 From: manisha1997 Date: Mon, 1 Dec 2025 16:32:10 +0530 Subject: [PATCH 6/8] fix: Regional endpoint processing --- src/Twilio/Clients/TwilioRestClient.cs | 7 +++---- src/Twilio/Constant/GlobalConstants.cs | 25 +++++++++++++++++++++++++ src/Twilio/Twilio.cs | 16 ++-------------- 3 files changed, 30 insertions(+), 18 deletions(-) create mode 100644 src/Twilio/Constant/GlobalConstants.cs diff --git a/src/Twilio/Clients/TwilioRestClient.cs b/src/Twilio/Clients/TwilioRestClient.cs index 4b270e1a8..bbc273509 100644 --- a/src/Twilio/Clients/TwilioRestClient.cs +++ b/src/Twilio/Clients/TwilioRestClient.cs @@ -55,7 +55,6 @@ public class TwilioRestClient : ITwilioRestClient private readonly string _password; private readonly AuthStrategy _authstrategy; - private static readonly Dictionary RegionToEdgeMap = new Dictionary { { "au1", "sydney" }, { "br1", "sao-paulo" }, @@ -93,7 +92,7 @@ public TwilioRestClient( AccountSid = accountSid ?? username; HttpClient = httpClient ?? DefaultClient(); - if ((string.IsNullOrEmpty(edge) && !string.IsNullOrEmpty(region)) || (string.IsNullOrEmpty(region) && !string.IsNullOrEmpty(edge))) + if (GlobalConstants.IsOnlyOneSet(edge,region)) Console.WriteLine("Deprecation Warning: For regional processing, DNS is of format product.edge.region.twilio.com;otherwise use product.twilio.com"); Region = region; @@ -128,7 +127,7 @@ public TwilioRestClient( AccountSid = accountSid ?? username; HttpClient = httpClient ?? DefaultClient(); - if ((string.IsNullOrEmpty(edge) && !string.IsNullOrEmpty(region)) || (string.IsNullOrEmpty(region) && !string.IsNullOrEmpty(edge))) + if (GlobalConstants.IsOnlyOneSet(edge,region)) Console.WriteLine("Deprecation Warning: For regional processing, DNS is of format product.edge.region.twilio.com;otherwise use product.twilio.com"); Region = region; @@ -144,7 +143,7 @@ public TwilioRestClient( public Response Request(Request request) { - if (string.IsNullOrEmpty(Edge) && !string.IsNullOrEmpty(Region) && RegionToEdgeMap.TryGetValue(Region, out var edge)) + if (string.IsNullOrEmpty(Edge) && !string.IsNullOrEmpty(Region) && GlobalConstants.RegionToEdgeMap.TryGetValue(Region, out var edge)) { Console.WriteLine("Deprecation Warning: Setting default `edge` for provided `region`"); Edge = edge; diff --git a/src/Twilio/Constant/GlobalConstants.cs b/src/Twilio/Constant/GlobalConstants.cs new file mode 100644 index 000000000..1774af422 --- /dev/null +++ b/src/Twilio/Constant/GlobalConstants.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; + +namespace Twilio +{ + public static class GlobalConstants + { + public static readonly Dictionary RegionToEdgeMap = new Dictionary + { + { "au1", "sydney" }, + { "br1", "sao-paulo" }, + { "de1", "frankfurt" }, + { "ie1", "dublin" }, + { "jp1", "tokyo" }, + { "jp2", "osaka" }, + { "sg1", "singapore" }, + { "us1", "ashburn" }, + { "us2", "umatilla" } + }; + public static bool IsOnlyOneSet(string edge, string region) + { + return (string.IsNullOrEmpty(edge) && !string.IsNullOrEmpty(region)) || + (string.IsNullOrEmpty(region) && !string.IsNullOrEmpty(edge)); + } + } +} diff --git a/src/Twilio/Twilio.cs b/src/Twilio/Twilio.cs index a0ce19507..551eb95de 100644 --- a/src/Twilio/Twilio.cs +++ b/src/Twilio/Twilio.cs @@ -24,18 +24,6 @@ public class TwilioClient private static string _logLevel; private static CredentialProvider _credentialProvider; - private static readonly Dictionary RegionToEdgeMap = new Dictionary - { - { "au1", "sydney" }, - { "br1", "sao-paulo" }, - { "de1", "frankfurt" }, - { "ie1", "dublin" }, - { "jp1", "tokyo" }, - { "jp2", "osaka" }, - { "sg1", "singapore" }, - { "us1", "ashburn" }, - { "us2", "umatilla" } - }; private TwilioClient() { } @@ -233,10 +221,10 @@ public static ITwilioRestClient GetNoAuthRestClient() /// The rest client public static ITwilioRestClient GetRestClient() { - if ((string.IsNullOrEmpty(_edge) && !string.IsNullOrEmpty(_region)) || (string.IsNullOrEmpty(_region) && !string.IsNullOrEmpty(_edge))) + if (GlobalConstants.IsOnlyOneSet(_edge,_region)) Console.WriteLine("Deprecation Warning: For regional processing, DNS is of format product.edge.region.twilio.com;otherwise use product.twilio.com"); - if (string.IsNullOrEmpty(_edge) && !string.IsNullOrEmpty(_region) && RegionToEdgeMap.TryGetValue(_region, out var edge)) + if (string.IsNullOrEmpty(_edge) && !string.IsNullOrEmpty(_region) && GlobalConstants.RegionToEdgeMap.TryGetValue(_region, out var edge)) { Console.WriteLine("Deprecation Warning: Setting default `edge` for provided `region`"); _edge = edge; From 98640c890ba71c6afb65233e9556a29b00889d14 Mon Sep 17 00:00:00 2001 From: manisha1997 Date: Mon, 1 Dec 2025 16:33:13 +0530 Subject: [PATCH 7/8] fix: Regional endpoint processing --- src/Twilio/Clients/TwilioRestClient.cs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/Twilio/Clients/TwilioRestClient.cs b/src/Twilio/Clients/TwilioRestClient.cs index bbc273509..34ada8a57 100644 --- a/src/Twilio/Clients/TwilioRestClient.cs +++ b/src/Twilio/Clients/TwilioRestClient.cs @@ -55,18 +55,6 @@ public class TwilioRestClient : ITwilioRestClient private readonly string _password; private readonly AuthStrategy _authstrategy; - { - { "au1", "sydney" }, - { "br1", "sao-paulo" }, - { "de1", "frankfurt" }, - { "ie1", "dublin" }, - { "jp1", "tokyo" }, - { "jp2", "osaka" }, - { "sg1", "singapore" }, - { "us1", "ashburn" }, - { "us2", "umatilla" } - }; - /// /// Constructor for a TwilioRestClient /// From 5848de1f901c927207b082f0f5eb1fa5b0b4c8c8 Mon Sep 17 00:00:00 2001 From: manisha1997 Date: Mon, 1 Dec 2025 18:01:46 +0530 Subject: [PATCH 8/8] fix: Regional endpoint processing --- .../Constant/GlobalConstantsTests.cs | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 test/Twilio.Test/Constant/GlobalConstantsTests.cs diff --git a/test/Twilio.Test/Constant/GlobalConstantsTests.cs b/test/Twilio.Test/Constant/GlobalConstantsTests.cs new file mode 100644 index 000000000..f92ea679e --- /dev/null +++ b/test/Twilio.Test/Constant/GlobalConstantsTests.cs @@ -0,0 +1,44 @@ +using NUnit.Framework; +using Twilio.Constant; +using System.Collections.Generic; + +namespace Twilio.Tests +{ + [TestFixture] + public class GlobalConstantsTests + { + [TestCase(null, null, ExpectedResult = false)] + [TestCase("", "", ExpectedResult = false)] + [TestCase("edge", null, ExpectedResult = true)] + [TestCase(null, "region", ExpectedResult = true)] + [TestCase("edge", "", ExpectedResult = true)] + [TestCase("", "region", ExpectedResult = true)] + [TestCase("edge", "region", ExpectedResult = false)] + public bool IsOnlyOneSet_ReturnsExpected(string edge, string region) + { + return GlobalConstants.IsOnlyOneSet(edge, region); + } + } + + [TestFixture] + public class GlobalConstantsMapTests + { + [Test] + public void RegionToEdgeMap_ContainsExpectedEntries() + { + // Example: adjust key-value pairs to match your actual map + Assert.IsTrue(GlobalConstants.RegionToEdgeMap.ContainsKey("us1")); + Assert.AreEqual("ashburn", GlobalConstants.RegionToEdgeMap["us1"]); + + Assert.IsTrue(GlobalConstants.RegionToEdgeMap.ContainsKey("ie1")); + Assert.AreEqual("dublin", GlobalConstants.RegionToEdgeMap["ie1"]); + } + + [Test] + public void RegionToEdgeMap_DoesNotContainUnexpectedKey() + { + Assert.IsFalse(GlobalConstants.RegionToEdgeMap.ContainsKey("unexpected")); + } + } + +}