Skip to content

Commit

Permalink
Support server-side endpoint versioning (DateTime serialization) (#152)
Browse files Browse the repository at this point in the history
  • Loading branch information
nvborisenko authored Dec 16, 2024
1 parent bd715d7 commit 81f933e
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 67 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public ServiceAsyncLaunchResource(HttpClient httpClient, string project) : base(
public async Task<LaunchCreatedResponse> StartAsync(StartLaunchRequest request, CancellationToken cancellationToken)
{
return await PostAsJsonAsync<LaunchCreatedResponse, StartLaunchRequest>(
$"v2/{ProjectName}/launch", request, cancellationToken).ConfigureAwait(false);
$"v2/{ProjectName}/launch", request, "application/x.reportportal.launch.v2+json", cancellationToken).ConfigureAwait(false);
}

public async Task<LaunchFinishedResponse> FinishAsync(string uuid, FinishLaunchRequest request, CancellationToken cancellationToken)
Expand All @@ -28,7 +28,7 @@ public async Task<LaunchFinishedResponse> FinishAsync(string uuid, FinishLaunchR
public async Task<LaunchResponse> MergeAsync(MergeLaunchesRequest request, CancellationToken cancellationToken)
{
return await PostAsJsonAsync<LaunchResponse, MergeLaunchesRequest>(
$"v2/{ProjectName}/launch/merge", request, cancellationToken).ConfigureAwait(false);
$"v2/{ProjectName}/launch/merge", request, "application/x.reportportal.launch.v2+json", cancellationToken).ConfigureAwait(false);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public async Task<LogItemsCreatedResponse> CreateAsync(CreateLogItemRequest[] re
}
}

return await SendHttpRequestAsync<LogItemsCreatedResponse>(HttpMethod.Post, uri, multipartContent, cancellationToken).ConfigureAwait(false);
return await SendHttpRequestAsync<LogItemsCreatedResponse>(HttpMethod.Post, uri, multipartContent, cancellationToken: cancellationToken).ConfigureAwait(false);
}
}
}
Expand Down
122 changes: 62 additions & 60 deletions src/ReportPortal.Client/Resources/ServiceBaseResource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,108 +21,110 @@ public ServiceBaseResource(HttpClient httpClient, string projectName)

protected Task<TResponse> GetAsJsonAsync<TResponse>(string uri, CancellationToken cancellationToken)
{
return SendAsJsonAsync<TResponse, object>(HttpMethod.Get, uri, null, cancellationToken);
return SendAsJsonAsync<TResponse, object>(HttpMethod.Get, uri, null, cancellationToken: cancellationToken);
}

protected Task<TResponse> GetAsJsonAsync<TResponse>(string uri, string accept, CancellationToken cancellationToken)
{
return SendAsJsonAsync<TResponse, object>(HttpMethod.Get, uri, null, accept, cancellationToken);
}

protected Task<TResponse> PostAsJsonAsync<TResponse, TRequest>(
string uri, TRequest request, CancellationToken cancellationToken)
{
return SendAsJsonAsync<TResponse, TRequest>(HttpMethod.Post, uri, request, cancellationToken);
return SendAsJsonAsync<TResponse, TRequest>(HttpMethod.Post, uri, request, cancellationToken: cancellationToken);
}

protected Task<TResponse> PostAsJsonAsync<TResponse, TRequest>(
string uri, TRequest request, string accept, CancellationToken cancellationToken)
{
return SendAsJsonAsync<TResponse, TRequest>(HttpMethod.Post, uri, request, accept, cancellationToken);
}

protected Task<TResponse> PutAsJsonAsync<TResponse, TRequest>(
string uri, TRequest request, CancellationToken cancellationToken)
{
return SendAsJsonAsync<TResponse, TRequest>(HttpMethod.Put, uri, request, cancellationToken);
return SendAsJsonAsync<TResponse, TRequest>(HttpMethod.Put, uri, request, cancellationToken: cancellationToken);
}

protected Task<TResponse> DeleteAsJsonAsync<TResponse>(string uri, CancellationToken cancellationToken)
{
return SendAsJsonAsync<TResponse, object>(HttpMethod.Delete, uri, null, cancellationToken);
return SendAsJsonAsync<TResponse, object>(HttpMethod.Delete, uri, null, cancellationToken: cancellationToken);
}

private async Task<TResponse> SendAsJsonAsync<TResponse, TRequest>(
HttpMethod httpMethod, string uri, TRequest request, CancellationToken cancellationToken)
HttpMethod httpMethod, string uri, TRequest request, string acccept = "application/json", CancellationToken cancellationToken = default)
{
HttpContent httpContent = null;

if (request != null)
{
using (var memoryStream = new MemoryStream())
{
await ModelSerializer.SerializeAsync<TRequest>(request, memoryStream, cancellationToken).ConfigureAwait(false);
memoryStream.Seek(0, SeekOrigin.Begin);
httpContent = new StreamContent(memoryStream);
httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");

return await SendHttpRequestAsync<TResponse>(httpMethod, uri, httpContent, cancellationToken).ConfigureAwait(false);
}
using var memoryStream = new MemoryStream();

await ModelSerializer.SerializeAsync<TRequest>(request, memoryStream, cancellationToken).ConfigureAwait(false);
memoryStream.Seek(0, SeekOrigin.Begin);
httpContent = new StreamContent(memoryStream);
httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");

return await SendHttpRequestAsync<TResponse>(httpMethod, uri, httpContent, acccept, cancellationToken).ConfigureAwait(false);
}
else
{
return await SendHttpRequestAsync<TResponse>(httpMethod, uri, httpContent, cancellationToken).ConfigureAwait(false);
return await SendHttpRequestAsync<TResponse>(httpMethod, uri, httpContent, acccept, cancellationToken).ConfigureAwait(false);
}
}

protected async Task<TResponse> SendHttpRequestAsync<TResponse>(
HttpMethod httpMethod, string uri, HttpContent httpContent, CancellationToken cancellationToken)
HttpMethod httpMethod, string uri, HttpContent httpContent, string accept = "application/json", CancellationToken cancellationToken = default)
{
using (var httpRequest = new HttpRequestMessage(httpMethod, uri))
using var httpRequest = new HttpRequestMessage(httpMethod, uri);

using (httpContent)
{
using (httpContent)
{
httpRequest.Content = httpContent;

using (var response = await HttpClient
.SendAsync(httpRequest, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false))
{
using (var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false))
{
CheckSuccessStatusCode(response, stream);

return await ModelSerializer.DeserializeAsync<TResponse>(stream, cancellationToken).ConfigureAwait(false);
}
}
}
httpRequest.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(accept));
httpRequest.Content = httpContent;

using var response = await HttpClient
.SendAsync(httpRequest, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);

using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);

CheckSuccessStatusCode(response, stream);

return await ModelSerializer.DeserializeAsync<TResponse>(stream, cancellationToken).ConfigureAwait(false);
}
}

protected async Task<byte[]> GetAsBytesAsync(string uri, CancellationToken cancellationToken)
{
using (var httpRequest = new HttpRequestMessage(HttpMethod.Get, uri))
{
using (var response = await HttpClient
.SendAsync(httpRequest, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false))
{
using (var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false))
{
CheckSuccessStatusCode(response, stream);

using (var memoryStream = new MemoryStream())
{
stream.CopyTo(memoryStream);
return memoryStream.ToArray();
}
}
}
}
using var httpRequest = new HttpRequestMessage(HttpMethod.Get, uri);

using var response = await HttpClient
.SendAsync(httpRequest, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);

using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);

CheckSuccessStatusCode(response, stream);

using var memoryStream = new MemoryStream();

stream.CopyTo(memoryStream);
return memoryStream.ToArray();
}

private void CheckSuccessStatusCode(HttpResponseMessage response, Stream stream)
{
if (!response.IsSuccessStatusCode)
{
using (var reader = new StreamReader(stream))
{
string responseBody = reader.ReadToEnd();

throw new ServiceException(
"Response status code does not indicate success.",
response.StatusCode,
response.RequestMessage.RequestUri,
response.RequestMessage.Method,
responseBody);
}
using var reader = new StreamReader(stream);
string responseBody = reader.ReadToEnd();

throw new ServiceException(
"Response status code does not indicate success.",
response.StatusCode,
response.RequestMessage.RequestUri,
response.RequestMessage.Method,
responseBody);
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/ReportPortal.Client/Resources/ServiceLaunchResource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public ServiceLaunchResource(HttpClient httpClient, string project) : base(httpC

public async Task<LaunchResponse> GetAsync(string uuid, CancellationToken cancellationToken)
{
return await GetAsJsonAsync<LaunchResponse>($"v1/{ProjectName}/launch/uuid/{uuid}", cancellationToken).ConfigureAwait(false);
return await GetAsJsonAsync<LaunchResponse>($"v1/{ProjectName}/launch/uuid/{uuid}", "application/x.reportportal.launch.v2+json", cancellationToken).ConfigureAwait(false);
}

public async Task<LaunchResponse> GetAsync(long id, CancellationToken cancellationToken)
Expand Down Expand Up @@ -50,7 +50,7 @@ public async Task<MessageResponse> DeleteAsync(long id, CancellationToken cancel
public async Task<LaunchResponse> MergeAsync(MergeLaunchesRequest request, CancellationToken cancellationToken)
{
return await PostAsJsonAsync<LaunchResponse, MergeLaunchesRequest>(
$"v1/{ProjectName}/launch/merge", request, cancellationToken).ConfigureAwait(false);
$"v1/{ProjectName}/launch/merge", request, "application/x.reportportal.launch.v2+json", cancellationToken).ConfigureAwait(false);
}

public async Task<MessageResponse> UpdateAsync(long id, UpdateLaunchRequest request, CancellationToken cancellationToken)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ public async Task<LogItemsCreatedResponse> CreateAsync(CreateLogItemRequest[] re
}
}

return await SendHttpRequestAsync<LogItemsCreatedResponse>(HttpMethod.Post, uri, multipartContent, cancellationToken).ConfigureAwait(false);
return await SendHttpRequestAsync<LogItemsCreatedResponse>(HttpMethod.Post, uri, multipartContent, cancellationToken: cancellationToken).ConfigureAwait(false);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public async Task<TestItemResponse> GetAsync(long id, CancellationToken cancella

public async Task<TestItemResponse> GetAsync(string uuid, CancellationToken cancellationToken)
{
return await GetAsJsonAsync<TestItemResponse>($"v1/{ProjectName}/item/uuid/{uuid}", cancellationToken).ConfigureAwait(false);
return await GetAsJsonAsync<TestItemResponse>($"v1/{ProjectName}/item/uuid/{uuid}", "application/x.reportportal.test.v2+json", cancellationToken).ConfigureAwait(false);
}

public async Task<TestItemCreatedResponse> StartAsync(StartTestItemRequest request, CancellationToken cancellationToken)
Expand Down

0 comments on commit 81f933e

Please sign in to comment.