Code/SBServer/SBServer.cs
using Sandbox;
using System;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
namespace SandbankDatabase;
public static class SBServer
{
private static JsonSerializerOptions _jsonOptions = new()
{
PropertyNameCaseInsensitive = true
};
/// <summary>
/// Calls an endpoint that returns data. The response is serialised as the given type T.
/// <br/><br/>
/// dataObject is an optional data class for the request that will be serialised into JSON.
/// </summary>
public static async Task<T> CallEndpoint<T>( string endpointName, object dataObject = null ) where T : class
{
var json = dataObject != null ? JsonSerializer.Serialize( dataObject ) : null;
var requestContent = BuildRequestContent( endpointName, json );
var response = await SendRequest( requestContent );
HandleResponseType( endpointName, response );
return await ProcessDataResponse<T>( response, endpointName );
}
/// <summary>
/// Calls an endpoint that does not return data.
/// <br/><br/>
/// dataObject is an optional data class for the request that will be serialised into JSON.
/// </summary>
public static async Task CallEndpoint( string endpointName, object dataObject = null )
{
var json = dataObject != null ? JsonSerializer.Serialize( dataObject ) : null;
var requestContent = BuildRequestContent( endpointName, json );
var response = await SendRequest( requestContent );
HandleResponseType( endpointName, response );
}
private static async Task<HttpResponseMessage> SendRequest( StringContent requestContent )
{
return await Http.RequestAsync( "https://sandbankdatabase.com/endpoint", "POST", requestContent );
}
private static StringContent BuildRequestContent( string endpointName, string jsonData )
{
jsonData ??= "null";
var message = "{" +
"\"userID\":\"" + ConfigController.SBSERVER_USER_ID + "\"," +
"\"publicKey\":\"" + ConfigController.SBSERVER_PUBLIC_KEY + "\"," +
"\"endpoint\":\"" + endpointName + "\"," +
"\"data\":" + jsonData + "" +
"}";
return new StringContent( message, Encoding.UTF8, "application/json" );
}
private async static Task<T> ProcessDataResponse<T>( HttpResponseMessage response, string endpointName ) where T : class
{
if ( !response.IsSuccessStatusCode )
return null;
var responseData = await response.Content.ReadAsStringAsync();
try
{
return JsonSerializer.Deserialize<T>( responseData, _jsonOptions );
}
catch ( Exception e )
{
throw new SandbankException( $"Sandbank Server: failed deserialising JSON response from server for endpoint " +
$"{endpointName} - either your response type is wrong or there is a bug on the server: {e.Message} " +
$"... {e.InnerException}");
}
}
private static void HandleResponseType( string endpointName, HttpResponseMessage response )
{
if ( ConfigController.ON_ENDPOINT_ERROR_BEHAVIOUR == OnEndpointErrorBehaviour.DoNothing )
return;
if ( response.IsSuccessStatusCode )
return;
else if ( response.StatusCode == System.Net.HttpStatusCode.TooManyRequests )
Logging.Warn( $"failed calling endpoint {endpointName} - you have reached your rate limit" );
else if ( response.StatusCode == System.Net.HttpStatusCode.InternalServerError )
Logging.Warn( $"failed calling endpoint {endpointName} - internal server error (this is a bug)" );
else if ( response.StatusCode == System.Net.HttpStatusCode.Forbidden )
Logging.Warn( $"failed calling endpoint {endpointName} - forbidden (are your credentials correct?)" );
else if ( response.StatusCode == System.Net.HttpStatusCode.BadRequest )
Logging.Warn( $"failed calling endpoint {endpointName} - bad request (is your endpoint/request correct?)" );
else
Logging.Warn( $"failed calling endpoint {endpointName} - there was an unknown error (response code {response.StatusCode})" );
}
}