diff --git a/src/Resend/IHasRateLimit.cs b/src/Resend/IHasRateLimit.cs new file mode 100644 index 0000000..860090e --- /dev/null +++ b/src/Resend/IHasRateLimit.cs @@ -0,0 +1,7 @@ +namespace Resend +{ + public interface IHasRateLimit + { + ResendRateLimit? Limits { get; } + } +} \ No newline at end of file diff --git a/src/Resend/ResendClient.cs b/src/Resend/ResendClient.cs index 7e5ac0c..7b8f9da 100644 --- a/src/Resend/ResendClient.cs +++ b/src/Resend/ResendClient.cs @@ -470,6 +470,10 @@ private async Task Execute( HttpRequestMessage req, Cancellation if ( err == null ) ex = new ResendException( resp.StatusCode, ErrorType.MissingResponse, "Missing error response" ); + else if ( err.ErrorType == ErrorType.RateLimitExceeded ) + { + ex = new ResendRateLimitExceededException( HttpStatusCode.TooManyRequests, err.Message, rrl ); + } else ex = new ResendException( (HttpStatusCode) err.StatusCode, err.ErrorType, err.Message ); @@ -551,6 +555,10 @@ private async Task> Execute( HttpRequestMessage req, if ( err == null ) ex = new ResendException( resp.StatusCode, ErrorType.MissingResponse, "Missing error response" ); + else if ( err.ErrorType == ErrorType.RateLimitExceeded ) + { + ex = new ResendRateLimitExceededException( HttpStatusCode.TooManyRequests, err.Message, rrl ); + } else ex = new ResendException( (HttpStatusCode) err.StatusCode, err.ErrorType, err.Message ); @@ -625,7 +633,8 @@ private async Task> Execute( HttpRequestMessage req, return new ResendResponse( res, rrl ); } - + /// + /// Rate limit info from the HTTP response headers. /// private ResendRateLimit FromHeaders( HttpResponseHeaders headers ) { diff --git a/src/Resend/ResendClientOptions.cs b/src/Resend/ResendClientOptions.cs index 082c5bf..381ea95 100644 --- a/src/Resend/ResendClientOptions.cs +++ b/src/Resend/ResendClientOptions.cs @@ -1,24 +1,24 @@ -namespace Resend; - -/// -public class ResendClientOptions -{ - /// - /// Base URL for Resend API. - /// - /// - /// Default is `https://api.resend.com`. - /// - public string ApiUrl { get; set; } = "https://api.resend.com"; - - /// - /// API key token. - /// - public string ApiToken { get; set; } = default!; - - /// - /// Whether exceptions should be thrown when the API invocation - /// fails (for whatever reason). - /// - public bool ThrowExceptions { get; set; } = true; -} +namespace Resend; + +/// +public class ResendClientOptions +{ + /// + /// Base URL for Resend API. + /// + /// + /// Default is `https://api.resend.com`. + /// + public string ApiUrl { get; set; } = "https://api.resend.com"; + + /// + /// API key token. + /// + public string ApiToken { get; set; } = default!; + + /// + /// Whether exceptions should be thrown when the API invocation + /// fails (for whatever reason). + /// + public bool ThrowExceptions { get; set; } = true; +} diff --git a/src/Resend/ResendRateLimitExceededException.cs b/src/Resend/ResendRateLimitExceededException.cs new file mode 100644 index 0000000..fd19244 --- /dev/null +++ b/src/Resend/ResendRateLimitExceededException.cs @@ -0,0 +1,32 @@ +using System.Net; + +namespace Resend; + +/// +/// Status code 429. User has hit their rate limit and should wait before resending the request. +/// +public class ResendRateLimitExceededException : ResendException, IHasRateLimit +{ + /// + /// Initializes a new instance of the class. + /// + public ResendRateLimitExceededException( HttpStatusCode? statusCode, string message, ResendRateLimit? rateLimit ) + : base( statusCode, ErrorType.RateLimitExceeded, message ) + { + this.Limits = rateLimit; + } + + /// + /// Initializes a new instance of the class. + /// + public ResendRateLimitExceededException( HttpStatusCode? statusCode, string message, Exception? innerException, ResendRateLimit? rateLimit ) + : base( statusCode, ErrorType.RateLimitExceeded, message, innerException ) + { + this.Limits = rateLimit; + } + + /// + /// Gets the rate limit information from the response headers. + /// + public ResendRateLimit? Limits { get; } +} \ No newline at end of file