Page cover image

HTTP(S) - RestSharp

We love and use RestSharp throughout the project. It's the best possible way of interesting with any modern API. It provides an easy to use method to call, execute, and parse data back into structured classes.

With Perigee, we've integrated the RestSharp package directly as a dependency, and we've written a few Extension methods to further integrate it into our system.

First Call with RestSharp

Here's a demo of using RestSharp to call out to Postman-Echo, and retrieve your IP address.

The steps are as follows:

  1. Create a RestClient, which usually contains the baseAddress of the endpoint you're going to be connecting to (https://postman-echo.com)

  2. Create a RestRequest, this contains information about the specific request being made.

    1. The Uri (/ip)

    2. The verb (POST/GET/PATCH)

    3. If you are adding body data, or query parameters (see demo usage for adding body, or using the other helper methods)

  3. Call Execute().

PerigeeApplication.ApplicationNoInit("HTTP", (c) => {

    //Declare a client, assign the timeout to 10 seconds
    using var client = new RestClient(new RestClientOptions("https://postman-echo.com") { MaxTimeout = 10000 });
    
    //Create a request
    var req = new RestRequest("/ip", Method.Get);
    
    //Execute
    var rsp = client.Execute<postmanEchoIP>(req);

    if (rsp.IsSuccessful)
        c.GetLogger<Program>().LogInformation("Response [{code}]: {ip}", (int)rsp.StatusCode, rsp.Data?.ip ?? "");
    else
        c.GetLogger<Program>().LogInformation("Response [{code}]: {content}", (int)rsp.StatusCode, rsp.Content);

});

public class postmanEchoIP { public string ip { get; set; } }

Log:

[15:11:51 INF]() Response [200]: 100.200.0.123

Authentication

This is an identical pattern to above, only this time we've added an authenticator, and changed the request uri.

PerigeeApplication.ApplicationNoInit("HTTP", (c) => {

    //Declare a client, assign the timeout to 10 seconds
    var rco = new RestClientOptions("https://postman-echo.com")
    {
        MaxTimeout = 10000,

        //Use a basic authenticator
        Authenticator = new RestSharp.Authenticators.HttpBasicAuthenticator("postman", "password")
    };

    using var client = new RestClient(rco);

    //Create a request
    var req = new RestRequest("/basic-auth", Method.Get);

    //Execute
    var rsp = client.Execute(req);

    //Log
    c.GetLogger<Program>().LogInformation("Response [{code}]: {content}", (int)rsp.StatusCode, rsp.Content);

});

Log:

[15:14:02 INF]() Response [200]: {
  "authenticated": true
}

Authentication with Perigee Credentials

This performs the same HTTPS request, only this time, we're using Perigee's Credential Store to manage, refresh, and obtain tokens. This gives a lot of flexibility on how to retrieve and maintain an active token state.

  1. Part of the "secret sauce" here is that any time a credential is about to expire (within a few minutes), a preemptive request is sent to the registered refresh action to renew the token before it's expired.

    1. This prevents an expired token from being sent to the API downstream

    2. This prevents the need for complicated patterns when an error occurs due to expired tokens

  2. These credentials are automatically persisted to disk, and reloaded on application start. This is explained in more detail in the Custom Refresh Logic section.

    1. Some authentication sources will rate limit your authentication requests, this is another method to use to prevent this issue from occurring.

PerigeeApplication.ApplicationNoInit("HTTP", (c) => {

    //Register a refresh with the name "RestSharpToken"
    CredentialStore.RegisterRefresh("RestSharpToken", (o) => {

        //Add any logic you need to here, including:
        // 1. Pulling configuration values (like so: c.GetValue<string>("AppSettings:AuthToken") )
        // 2. Executing other authorization requests to obtain a token
        // 3. Reaching out to another library
        // 4. etc

        //In this example we use a basic authentication header, many modern authentication API's now use a Bearer token:
        //      new RestSharp.Authenticators.JwtAuthenticator("eyJ.........");

        return new RestSharpCredentialStoreItem(new RestSharp.Authenticators.HttpBasicAuthenticator("postman", "password"), Expiration: DateTimeOffset.Now.AddSeconds(3600));
    });

    //Declare a client, assign the timeout to 10 seconds
    var rco = new RestClientOptions("https://postman-echo.com")
    {
        MaxTimeout = 10000,

        //Use a Credential Authenticator instead...
        Authenticator = new CredentialAuthenticator("RestSharpToken")
    };

    using var client = new RestClient(rco);

    //Create a request
    var req = new RestRequest("/basic-auth", Method.Get);

    //Execute
    var rsp = client.Execute(req);

    //Log
    c.GetLogger<Program>().LogInformation("Response [{code}]: {content}", (int)rsp.StatusCode, rsp.Content);

});

Log:

[15:16:26 INF]() Response [200]: {
  "authenticated": true
}

Extensions

There are a few notable extensions added by Perigee:

Execute Retry

This method has quite a few overloads you can call, but all of them do the same thing:

  1. Retry a request if the method failed to connect, or if it timed out.

  2. If the third party API suddenly revoked your current API credentials AND you are using a CredentialAuthenticator, it will fire the renewal for a new token before attempting another retry

//Execute a retry a total of 2 times (1 original attempt, 1 retry)
var rsp = client.ExecuteRetry<postmanEchoIP>(req, 2);

IsTimeout

If the request timed out, this is an easy Boolean to check so you can proceed with other options.

//Check if a timeout occured
bool isTimeout = rsp.IsTimeout();

Last updated