diff --git a/README.md b/README.md index ddd6c97c5..237cf1f0b 100644 --- a/README.md +++ b/README.md @@ -450,17 +450,20 @@ DateTimeOffset time = await client.TimeAsync(); - It automatically adds necessary auth headers based on the initial auth config and supports pagination. - The following is an example of using the batch publish API based on the [Ably batch publish rest endpoint documentation](https://ably.com/docs/api/rest-api#batch-publish). ```csharp - var jsonPayload = - @"{ - ""channels"" : [ ""channel1"", ""channel2"" ], - ""messages"" : [ + var objectPayload = new + { + channels = new[] { "channel1", "channel2", "channel3", "channel4" }, + messages = new[] + { + new { - ""name"": ""eventName"", - ""data"" : ""message"", + name = "eventName", + data = "foo", } - ] - }"; - var paginatedResponse = await ablyRest.Request(HttpMethod.Post, "/messages", null, JObject.Parse(jsonPayload), null); + } + }; + var jsonPayload = JsonConvert.SerializeObject(objectPayload); + var paginatedResponse = await ablyRest.RequestV2(HttpMethod.Post, "/messages", null, jsonPayload, null); ``` - Follow official [ably rest endpoint doc](https://ably.com/docs/api/rest-api) for more information on other endpoints. diff --git a/src/IO.Ably.Shared/AblyRest.cs b/src/IO.Ably.Shared/AblyRest.cs index 78e5943ff..8abb88d48 100644 --- a/src/IO.Ably.Shared/AblyRest.cs +++ b/src/IO.Ably.Shared/AblyRest.cs @@ -315,15 +315,38 @@ internal async Task HttpPaginatedRequestInternal(Paginate /// http method. /// the path component of the resource URI. /// (optional; may be null): any parameters to send with the request; see API-specific documentation. - /// (optional; may be null): an instance of RequestBody. It will be sent as a json object. + /// (optional; may be null): RequestBody encoded into a JToken. It will be sent as a json object. /// (optional; may be null): any additional headers to send; see API-specific documentation. /// a page of results. + [Obsolete("Use RequestV2 instead")] public async Task Request(string method, string path, Dictionary requestParams = null, JToken body = null, Dictionary headers = null) { var httpMethod = new HttpMethod(method); return await Request(httpMethod, path, requestParams, body, headers); } + /// + /// Make a generic HTTP request against an endpoint representing a collection + /// of some type; this is to provide a forward compatibility path for new APIs. + /// + /// http method. + /// the path component of the resource URI. + /// (optional; may be null): any parameters to send with the request; see API-specific documentation. + /// (optional; may be null): a json string RequestBody. It will be sent as a json object. + /// (optional; may be null): any additional headers to send; see API-specific documentation. + /// a page of results. + public async Task RequestV2(string method, string path, Dictionary requestParams = null, string body = null, Dictionary headers = null) + { + var httpMethod = new HttpMethod(method); + JToken requestBody = null; + if (body != null) + { + requestBody = JToken.Parse(body); + } + + return await Request(httpMethod, path, requestParams, requestBody, headers); + } + /// /// Make a generic HTTP request against an endpoint representing a collection /// of some type; this is to provide a forward compatibility path for new APIs. diff --git a/src/IO.Ably.Tests.Shared/Rest/RequestSandBoxSpecs.cs b/src/IO.Ably.Tests.Shared/Rest/RequestSandBoxSpecs.cs index 8f3088d11..78369caf8 100644 --- a/src/IO.Ably.Tests.Shared/Rest/RequestSandBoxSpecs.cs +++ b/src/IO.Ably.Tests.Shared/Rest/RequestSandBoxSpecs.cs @@ -5,6 +5,7 @@ using System.Net.Http; using System.Threading.Tasks; using FluentAssertions; +using Newtonsoft.Json; using Newtonsoft.Json.Linq; using RichardSzalay.MockHttp; using Xunit; @@ -75,12 +76,12 @@ public async Task Request_ShouldAcceptCorrectHttpVerbs(Protocol protocol) mockHttp.When(new HttpMethod(verb), "https://localhost/*").Respond(HttpStatusCode.OK, "application/json", "{ \"verb\": \"" + verb + "\" }"); client.HttpClient.Client = mockHttp.ToHttpClient(); - var response = await client.Request(verb, "/"); + var response = await client.RequestV2(verb, "/"); response.Success.Should().BeTrue($"'{verb}' verb should be supported "); response.StatusCode.Should().Be(HttpStatusCode.OK); response.Items.First()["verb"].ToString().Should().Be(verb); - var failedResponse = await client.Request("INVALID_HTTP_VERB", "/"); + var failedResponse = await client.RequestV2("INVALID_HTTP_VERB", "/"); failedResponse.Success.Should().BeFalse($"'INVALID_HTTP_VERB' should fail because '{verb}' verb is expected by mock HTTP server."); } } @@ -99,7 +100,7 @@ public async Task Request_SimpleGet(Protocol protocol) var testParams = new Dictionary { { "testParams", "testParamValue" } }; var testHeaders = new Dictionary { { "X-Test-Header", "testHeaderValue" } }; - var paginatedResponse = await client.Request(HttpMethod.Get.Method, _channelPath, testParams, null, testHeaders); + var paginatedResponse = await client.RequestV2(HttpMethod.Get.Method, _channelPath, testParams, null, testHeaders); _lastRequest.Headers.Should().ContainKey("Authorization"); _lastRequest.Headers.Should().ContainKey("X-Test-Header"); @@ -162,7 +163,7 @@ async Task ValidateMessages(string channelName, Action validate) data = "foo", } }; - var paginatedResponse = await client.Request(HttpMethod.Post, "/messages", null, JObject.FromObject(objectPayload), null); + var paginatedResponse = await client.Request(HttpMethod.Post, "/messages", null, JToken.FromObject(objectPayload), null); ValidateResponse(paginatedResponse); @@ -189,7 +190,7 @@ await ValidateMessages(channel, (message, messageIndex) => } ] }"; - paginatedResponse = await client.Request(HttpMethod.Post, "/messages", null, JObject.Parse(jsonPayload), null); + paginatedResponse = await client.RequestV2(HttpMethod.Post.Method, "/messages", null, jsonPayload, null); ValidateResponse(paginatedResponse, 5); @@ -374,7 +375,7 @@ public async Task RequestFails_Non200StatusResponseShouldNotRaiseException(Proto })); client.HttpClient.SetPreferredHost("echo.ably.io/respondwith?status=400"); - var response = await client.Request(HttpMethod.Post.Method, "/"); + var response = await client.RequestV2(HttpMethod.Post.Method, "/"); response.Success.Should().BeFalse(); response.StatusCode.Should().Be(HttpStatusCode.BadRequest);