Skip to content

Commit

Permalink
Allow SDK to handle No Content (204) responses
Browse files Browse the repository at this point in the history
Previously, the SDK would throw an exception when trying to parse an empty string.
Now we will return the empty string, if a string response is requested.

If the caller was expecting a deserialized type, an exception will still be raised for no content.
  • Loading branch information
joshuaflanagan committed Jul 22, 2024
1 parent 3b89b48 commit cfb987f
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 2 deletions.
2 changes: 1 addition & 1 deletion ShipEngineSDK.Test/Helpers/MockShipEngineFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public string StubRequest(HttpMethod method, string path, HttpStatusCode status,
{
var requestId = Guid.NewGuid().ToString();
var responseMessage = new HttpResponseMessage(status);
responseMessage.Content = new StringContent(response);
responseMessage.Content = new StringContent(response ?? "");
responseMessage.Headers.Add("x-shipengine-requestid", requestId);
responseMessage.Headers.Add("request-id", requestId);

Expand Down
36 changes: 35 additions & 1 deletion ShipEngineSDK.Test/ShipEngineClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ public async Task SuccessResponseThatCannotBeParsedThrowsExceptionWithUnparsedRe
}

[Fact]
public async Task SuccessResponseWithNullContentThrowsShipEngineExceptionWithUnparsedResponse()
public async Task SuccessResponseWithNullStringContentThrowsShipEngineExceptionWithUnparsedResponse()
{
var config = new Config(apiKey: "test", timeout: TimeSpan.FromSeconds(0.5));
var mockShipEngineFixture = new MockShipEngineFixture(config);
Expand All @@ -189,5 +189,39 @@ public async Task SuccessResponseWithNullContentThrowsShipEngineExceptionWithUnp
Assert.Equal(responseBody, await ex.ResponseMessage.Content.ReadAsStringAsync());
Assert.Equal(requestId, ex.RequestId);
}

[Fact]
public async Task SuccessResponseWhenStringRequestedReturnsUnparsedString()
{
var config = new Config(apiKey: "test", timeout: TimeSpan.FromSeconds(0.5));
var mockShipEngineFixture = new MockShipEngineFixture(config);
var shipengine = mockShipEngineFixture.ShipEngine;

// this scenario is similar to unparseable JSON - except that it is valid JSON
var responseBody = @"The Response";
mockShipEngineFixture.StubRequest(HttpMethod.Delete, "/v1/something", System.Net.HttpStatusCode.OK,
responseBody);
var result = await shipengine.SendHttpRequestAsync<string>(HttpMethod.Delete, "/v1/something", "",
mockShipEngineFixture.HttpClient, config);

Assert.Equal(responseBody, result);
}

[Fact]
public async Task SuccessResponseWithNoContentCanBeReturnedIfStringRequested()
{
var config = new Config(apiKey: "test", timeout: TimeSpan.FromSeconds(0.5));
var mockShipEngineFixture = new MockShipEngineFixture(config);
var shipengine = mockShipEngineFixture.ShipEngine;

// this scenario is similar to unparseable JSON - except that it is valid JSON
string responseBody = null;
mockShipEngineFixture.StubRequest(HttpMethod.Delete, "/v1/something", System.Net.HttpStatusCode.OK,
responseBody);
var result = await shipengine.SendHttpRequestAsync<string>(HttpMethod.Delete, "/v1/something", "",
mockShipEngineFixture.HttpClient, config);

Assert.Null(responseBody);
}
}
}
5 changes: 5 additions & 0 deletions ShipEngineSDK/ShipEngineClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,11 @@ private async Task<T> DeserializedResultOrThrow<T>(HttpResponseMessage response)
}

T? result;
// If the caller asked for a string, return the response as-is. This can be useful for no content responses.
if (typeof(T).IsAssignableFrom(typeof(string)))
{
return (T)(object)(contentString ?? "");
}
try
{
result = JsonSerializer.Deserialize<T>(contentString, JsonSerializerOptions);
Expand Down

0 comments on commit cfb987f

Please sign in to comment.