Skip to content

Commit

Permalink
Merge #489
Browse files Browse the repository at this point in the history
489: Reduce code duplication r=brunoocasali a=kashifsoofi

# Pull Request

## Related issue
Fixes #371

## What does this PR do?
- Update ToQueryString method to check for null object
- Add optional uri parameter, if passed prefix query string with it

## PR checklist
Please check if your PR fulfills the following requirements:
- [x] Does this PR fix an existing issue, or have you listed the changes applied in the PR description (and why they are needed)?
- [x] Have you read the contributing guidelines?
- [x] Have you made sure that the title is accurate and descriptive of the changes?

Thank you so much for contributing to Meilisearch!


Co-authored-by: Kashif Soofi <[email protected]>
  • Loading branch information
meili-bors[bot] and kashifsoofi committed Oct 18, 2023
2 parents fe94471 + cb165a6 commit 946a4c3
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 59 deletions.
59 changes: 37 additions & 22 deletions src/Meilisearch/Extensions/ObjectExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,43 +29,58 @@ internal static IDictionary<string, string> AsDictionary(this object source, Bin
/// </summary>
/// <param name="source">Object to transform.</param>
/// <param name="bindingAttr">Binding flags.</param>
/// <param name="uri">Uri to prepend before query string.</param>
/// <returns>Returns an url encoded query string.</returns>
internal static string ToQueryString(this object source, BindingFlags bindingAttr = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance)
internal static string ToQueryString(this object source, BindingFlags bindingAttr = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance, string uri = "")
{
var values = new List<string>();
foreach (var field in source.GetType().GetProperties(bindingAttr))
if (source != null)
{
var value = field.GetValue(source, null);
var key = Uri.EscapeDataString(char.ToLowerInvariant(field.Name[0]) + field.Name.Substring(1));

if (value != null)
foreach (var field in source.GetType().GetProperties(bindingAttr))
{
var type = value.GetType();
var value = field.GetValue(source, null);
var key = Uri.EscapeDataString(char.ToLowerInvariant(field.Name[0]) + field.Name.Substring(1));

if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>))
if (value != null)
{
var itemType = type.GetGenericArguments()[0];
if (itemType == typeof(string))
var type = value.GetType();

if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>))
{
values.Add(key + "=" + string.Join(",", (List<string>)value));
var itemType = type.GetGenericArguments()[0];
if (itemType == typeof(string))
{
values.Add(key + "=" + string.Join(",", (List<string>)value));
}
else if (itemType == typeof(int))
{
values.Add(key + "=" + string.Join(",", (List<int>)value));
}
}
else if (itemType == typeof(int))
else if (value is DateTime)
{
values.Add(key + "=" + string.Join(",", (List<int>)value));
values.Add(key + "=" + Uri.EscapeDataString(((DateTime)value).ToString("yyyy-MM-dd'T'HH:mm:ss.fffzzz")));
}
else
{
values.Add(key + "=" + Uri.EscapeDataString(value.ToString()));
}
}
else if (value is DateTime)
{
values.Add(key + "=" + Uri.EscapeDataString(((DateTime)value).ToString("yyyy-MM-dd'T'HH:mm:ss.fffzzz")));
}
else
{
values.Add(key + "=" + Uri.EscapeDataString(value.ToString()));
}
}
}

return string.Join("&", values);
var queryString = string.Join("&", values);
if (string.IsNullOrWhiteSpace(uri))
{
return queryString;
}

if (string.IsNullOrEmpty(queryString))
{
return uri;
}

return $"{uri}?{queryString}";
}
}
}
6 changes: 1 addition & 5 deletions src/Meilisearch/Index.Documents.cs
Original file line number Diff line number Diff line change
Expand Up @@ -406,11 +406,7 @@ public async Task<ResourceResults<IEnumerable<T>>> GetDocumentsAsync<T>(Document
}
else
{
var uri = $"indexes/{Uid}/documents";
if (query != null)
{
uri = $"{uri}?{query.ToQueryString()}";
}
var uri = query.ToQueryString(uri: $"indexes/{Uid}/documents");

return await _http
.GetFromJsonAsync<ResourceResults<IEnumerable<T>>>(uri, cancellationToken: cancellationToken)
Expand Down
18 changes: 3 additions & 15 deletions src/Meilisearch/MeilisearchClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -147,11 +147,7 @@ public async Task<TaskInfo> DeleteIndexAsync(string uid, CancellationToken cance
/// <returns>An IEnumerable of indexes in JsonElement format.</returns>
public async Task<JsonDocument> GetAllRawIndexesAsync(IndexesQuery query = default, CancellationToken cancellationToken = default)
{
var uri = $"indexes";
if (query != null)
{
uri = $"{uri}?{query.ToQueryString()}";
}
var uri = query.ToQueryString(uri: "indexes");
var response = await _http.GetAsync(uri, cancellationToken).ConfigureAwait(false);

var content = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
Expand All @@ -166,11 +162,7 @@ public async Task<JsonDocument> GetAllRawIndexesAsync(IndexesQuery query = defau
/// <returns>Return Enumerable of Index.</returns>
public async Task<ResourceResults<IEnumerable<Index>>> GetAllIndexesAsync(IndexesQuery query = default, CancellationToken cancellationToken = default)
{
var uri = $"indexes";
if (query != null)
{
uri = $"{uri}?{query.ToQueryString()}";
}
var uri = query.ToQueryString(uri: "indexes");
var response = await _http.GetAsync(uri, cancellationToken).ConfigureAwait(false);

var content = await response.Content.ReadFromJsonAsync<ResourceResults<IEnumerable<Index>>>(cancellationToken: cancellationToken).ConfigureAwait(false);
Expand Down Expand Up @@ -305,11 +297,7 @@ public async Task<TaskInfo> CreateDumpAsync(CancellationToken cancellationToken
/// <returns>Returns a list of the API keys.</returns>
public async Task<ResourceResults<IEnumerable<Key>>> GetKeysAsync(KeysQuery query = default, CancellationToken cancellationToken = default)
{
var uri = $"keys";
if (query != null)
{
uri = $"{uri}?{query.ToQueryString()}";
}
var uri = query.ToQueryString(uri: "keys");
return await _http.GetFromJsonAsync<ResourceResults<IEnumerable<Key>>>(uri, cancellationToken: cancellationToken)
.ConfigureAwait(false);
}
Expand Down
18 changes: 3 additions & 15 deletions src/Meilisearch/TaskEndpoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,7 @@ public class TaskEndpoint
/// <returns>Returns a list of the tasks.</returns>
public async Task<TasksResults<IEnumerable<TaskResource>>> GetTasksAsync(TasksQuery query = default, CancellationToken cancellationToken = default)
{
var uri = $"tasks";
if (query != null)
{
uri = $"{uri}?{query.ToQueryString()}";
}
var uri = query.ToQueryString(uri: "tasks");
return await _http.GetFromJsonAsync<TasksResults<IEnumerable<TaskResource>>>(uri, cancellationToken: cancellationToken)
.ConfigureAwait(false);
}
Expand All @@ -43,11 +39,7 @@ public async Task<TasksResults<IEnumerable<TaskResource>>> GetTasksAsync(TasksQu
/// <returns>Returns a list of the tasks.</returns>
public async Task<TaskInfo> CancelTasksAsync(CancelTasksQuery query, CancellationToken cancellationToken = default)
{
var uri = "tasks/cancel";
if (query != null)
{
uri = $"{uri}?{query.ToQueryString()}";
}
var uri = query.ToQueryString(uri: "tasks/cancel");

var response = await _http.PostAsync(uri, null, cancellationToken: cancellationToken).ConfigureAwait(false);

Expand All @@ -62,11 +54,7 @@ public async Task<TaskInfo> CancelTasksAsync(CancelTasksQuery query, Cancellatio
/// <returns>Returns a list of the tasks.</returns>
public async Task<TaskInfo> DeleteTasksAsync(DeleteTasksQuery query, CancellationToken cancellationToken = default)
{
var uri = "tasks";
if (query != null)
{
uri = $"{uri}?{query.ToQueryString()}";
}
var uri = query.ToQueryString(uri: "tasks");

var response = await _http.DeleteAsync(uri, cancellationToken).ConfigureAwait(false);

Expand Down
50 changes: 48 additions & 2 deletions tests/Meilisearch.Tests/ObjectExtensionsTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;

using Meilisearch.Extensions;
using Meilisearch.QueryParameters;
Expand All @@ -16,6 +17,7 @@ public class FakeQuery
public string FakeString { get; set; }
public int? FakeInteger { get; set; }
public List<string> FakeStringList { get; set; }
public string Path { get; set; }
}

public class ObjectExtensionsTests
Expand Down Expand Up @@ -56,7 +58,51 @@ public void QueryStringsAreEqualsForPrimaryKey(string key)
var o = new { primaryKey = key };

var expected = QueryHelpers.AddQueryString(uri, o.AsDictionary());
var actual = $"{uri}?{o.ToQueryString()}";
var actual = o.ToQueryString(uri: uri);
Assert.Equal(expected, actual);
}

[Theory]
[InlineData("simple")]
public void QueryStringOnlyQueryStringParameters(string key)
{
var o = new { primaryKey = key };

var expected = "primaryKey=simple";
var actual = o.ToQueryString();
Assert.Equal(expected, actual);
}

[Theory]
[InlineData("simple")]
public void QueryStringPrependsUri(string key)
{
var uri = "indexes/myindex/documents";
var o = new { primaryKey = key };

var expected = QueryHelpers.AddQueryString(uri, o.AsDictionary());
var actual = o.ToQueryString(uri: uri);
Assert.Equal(expected, actual);
}

[Fact]
public void QueryStringReturnsEmptyForNullObject()
{
object o = null;

var expected = "";
var actual = o.ToQueryString();
Assert.Equal(expected, actual);
}

[Fact]
public void QueryStringReturnsUriForNullObject()
{
var uri = "indexes/myindex/documents";
object o = null;

var expected = uri;
var actual = o.ToQueryString(uri: uri);
Assert.Equal(expected, actual);
}

Expand All @@ -75,7 +121,7 @@ public void QueryStringsWithListAreEqualsForDocumentsQuery(int? offset, int? lim
{
var uri = "indexes/myindex/documents";
var dq = new DocumentsQuery { Offset = offset, Limit = limit, Fields = fields != null ? new List<string>(fields) : null };
var actualQuery = $"{uri}?{dq.ToQueryString()}";
var actualQuery = dq.ToQueryString(uri: uri);

Assert.NotEmpty(actualQuery);
Assert.NotNull(actualQuery);
Expand Down

0 comments on commit 946a4c3

Please sign in to comment.