Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(dart): fix DioRequester.requestUri when HttpRequest.queryParameters is not empty #3349

Open
wants to merge 24 commits into
base: main
Choose a base branch
from

Conversation

techouse
Copy link
Contributor

@techouse techouse commented Jul 10, 2024

🧭 What and Why

The current DioRequester.requestUri method will incorrectly return a data: URI when HttpRequest.queryParameters is not empty

/// Existing code
Uri requestUri(HttpRequest request) {
  Uri uri = Uri(
    scheme: request.host.scheme,
    host: request.host.url,
    port: request.host.port,
    path: request.path,
  );
  if (request.queryParameters.isNotEmpty) {
    return Uri.dataFromString( // <-- this should have been [Uri.parse] and not [Uri.dataFromString]
        "${uri.toString()}?${request.queryParameters.entries.map((e) => "${e.key}=${e.value}").join("&")}");
  }

  return uri;
}

The code provided in the example clients/algoliasearch-client-dart/packages/client_core/example/example.dart

final requester = RetryStrategy.create(
  segment: AgentSegment(value: 'CustomClient'),
  appId: 'latency',
  apiKey: '6be0576ff61c053d5f9a3225e2a90f76',
  defaultHosts: () => [
    Host(url: 'latency-dsn.algolia.net'),
    Host(url: 'latency-1.algolianet.com'),
  ],
);

// Executing a GET request on the '/1/indexes/instant_search' endpoint.
final response = await requester.execute(
  request: ApiRequest(
      method: RequestMethod.get,
      path: '/1/indexes/instant_search',
      queryParams: {'query': 'a', 'hitsPerPage': '5'}),
);

will erroneously return the Uri in String form as

data:,https://latency-dsn.algolia.net/1/indexes/instant_search?query=a&hitsPerPage=5

and therefore fails the example test with the following error message

Unhandled exception:
UnreachableHostsException{errors: [AlgoliaIOException{error: DioException [unknown]: null
Error: Invalid argument(s): No host specified in URI data:,https://latency-dsn.algolia.net/1/indexes/instant_search?query=a&hitsPerPage=5}, AlgoliaIOException{error: DioException [unknown]: null
Error: Invalid argument(s): No host specified in URI data:,https://latency-1.algolianet.com/1/indexes/instant_search?query=a&hitsPerPage=5}]}
#0      RetryStrategy.execute (package:algolia_client_core/src/transport/retry_strategy.dart:71:5)
<asynchronous suspension>
#1      main (file:///Users/techouse/Work/api-clients-automation/clients/algoliasearch-client-dart/packages/client_core/example/example.dart:17:20)
<asynchronous suspension>

Process finished with exit code 255

I have fixed the DioRequester.requestUri method as follows

/// Fixed code
Uri requestUri(HttpRequest request) => Uri(
        scheme: request.host.scheme,
        host: request.host.url,
        port: request.host.port,
        path: request.path,
        query: request.queryParameters.isNotEmpty
            // provide query [String] in the [Uri] constructor
            ? request.queryParameters.entries.map((e) => "${e.key}=${e.value}").join("&")
            : null,
      );

which correctly returns the Uri in String form as

https://latency-dsn.algolia.net/1/indexes/instant_search?query=a&hitsPerPage=5

and correctly completes the example test

{hits: [{name: Amazon - Fire TV Stick with Alexa Voice Remote - Black, description: Enjoy smart access to videos, games and apps with this Amazon Fire TV stick. Its Alexa voice remote lets you deliver hands-free commands when you want to watch television or engage with other applications. With a quad-core processor, 1GB internal memory and 8GB of storage, this portable Amazon Fire TV stick works fast for buffer-free streaming., categories: [TV & Home Theater, Streaming Media Players], hierarchicalCategories: {lvl0: [TV & Home Theater, TV & Home Theater], lvl1: [TV & Home Theater > Streaming Media Players, helloworld]}, type: Streaming media plyr, price: 39.99, price_range: 1 - 50, image: https://cdn-demo.algolia.com/bestbuy-0118/5477500_sb.jpg, url: https://api.bestbuy.com/click/-/5477500/pdp, free_shipping: false, popularity: 21469, rating: 4, objectID: 5477500, _snippetResult: {description: {value: smart <em>a</em>ccess to videos, games <em>a</em>nd <em>a</em>pps with this <em>A</em>mazon, matchLevel: full}}, _highlightResult: {name: {value: <em>A</em>mazon - Fire TV Stick with <em>A</em>lexa Voice Remote - Black, matchLevel: full, fullyHighlighted: false, matchedWords: [a]}, description: {value: Enjoy smart <em>a</em>ccess to videos, games <em>a</em>nd <em>a</em>pps with this <em>A</em>mazon Fire TV stick. Its <em>A</em>lexa voice remote lets you deliver hands-free commands when you want to watch television or engage with other <em>a</em>pplications. With <em>a</em> quad-core processor, 1GB internal memory <em>a</em>nd 8GB of storage, this portable <em>A</em>mazon Fire TV stick works fast for buffer-free streaming., matchLevel: full, fullyHighlighted: false, matchedWords: [a]}, categories: [{value: TV & Home Theater, matchLevel: none, matchedWords: []}, {value: Streaming Media Players, matchLevel: none, matchedWords: []}]}}, {name: Amazon - Echo Dot, description: Deliver your favorite playlist anywhere in your home with the Amazon Echo Dot voice-controlled device. Control most electric devices through voice activation, or schedule a ride with Uber and order a pizza. The Amazon Echo Dot voice-controlled device turns any home into a smart home with the Alexa app on a smartphone or tablet., brand: Amazon, categories: [Smart Home], hierarchicalCategories: {lvl0: Smart Home}, type: Voice assistants, price: 49.99, price_range: 1 - 50, image: https://cdn-demo.algolia.com/bestbuy-0118/5578851_sb.jpg, url: https://api.bestbuy.com/click/-/5578851/pdp, free_shipping: true, rating: 4, popularity: 21466, objectID: 5578851, _snippetResult: {description: {value: <em>a</em> smart home with the <em>A</em>lexa <em>a</em>pp on <em>a</em> smartphone, matchLevel: full}}, _highlightResult: {name: {value: <em>A</em>mazon - Echo Dot, matchLevel: full, fullyHighlighted: false, matchedWords: [a]}, description: {value: Deliver your favorite playlist <em>a</em>nywhere in your home with the <em>A</em>mazon Echo Dot voice-controlled device. Control most electric devices through voice <em>a</em>ctivation, or schedule <em>a</em> ride with Uber <em>a</em>nd order <em>a</em> pizza. The <em>A</em>mazon Echo Dot voice-controlled device turns <em>a</em>ny home into <em>a</em> smart home with the <em>A</em>lexa <em>a</em>pp on <em>a</em> smartphone or tablet., matchLevel: full, fullyHighlighted: false, matchedWords: [a]}, brand: {value: <em>A</em>mazon, matchLevel: full, fullyHighlighted: false, matchedWords: [a]}, categories: [{value: Smart Home, matchLevel: none, matchedWords: []}]}}, {name: Apple - MacBook Air® (Latest Model) - 13.3" Display - Intel Core i5 - 8GB Memory - 128GB Flash Storage - Silver, description: MacBook Air features up to 8GB of memory, a fifth-generation Intel Core processor, Thunderbolt 2, great built-in apps, and all-day battery life.1 Its thin, light, and durable enough to take everywhere you go-and powerful enough to do everything once you get there, better., brand: Apple, categories: [Computers & Tablets, Laptops, All Laptops, MacBooks], hierarchicalCategories: {lvl0: Computers & Tablets, lvl1: Computers & Tablets > Laptops, lvl2: Computers & Tablets > Laptops > All Laptops, lvl3: Computers & Tablets > Laptops > All Laptops > MacBooks}, type: Apple, price: 999.99, price_range: 500 - 2000, image: https://cdn-demo.algolia.com/bestbuy-0118/6443034_sb.jpg, url: https://api.bestbuy.com/click/-/6443034/pdp, free_shipping: true, rating: 4, popularity: 21465, _geoloc: {lat: 40.748817, lng: -73.985428}, objectID: 6443034, _snippetResult: {description: {value: Thunderbolt 2, great built-in <em>a</em>pps, <em>a</em>nd <em>a</em>ll-day battery, matchLevel: full}}, _highlightResult: {name: {value: <em>A</em>pple - MacBook <em>A</em>ir® (Latest Model) - 13.3" Display - Intel Core i5 - 8GB Memory - 128GB Flash Storage - Silver, matchLevel: full, fullyHighlighted: false, matchedWords: [a]}, description: {value: MacBook <em>A</em>ir features up to 8GB of memory, <em>a</em> fifth-generation Intel Core processor, Thunderbolt 2, great built-in <em>a</em>pps, <em>a</em>nd <em>a</em>ll-day battery life.1 Its thin, light, <em>a</em>nd durable enough to take everywhere you go-<em>a</em>nd powerful enough to do everything once you get there, better., matchLevel: full, fullyHighlighted: false, matchedWords: [a]}, brand: {value: <em>A</em>pple, matchLevel: full, fullyHighlighted: false, matchedWords: [a]}, categories: [{value: Computers & Tablets, matchLevel: none, matchedWords: []}, {value: Laptops, matchLevel: none, matchedWords: []}, {value: <em>A</em>ll Laptops, matchLevel: full, fullyHighlighted: false, matchedWords: [a]}, {value: MacBooks, matchLevel: none, matchedWords: []}]}}, {name: Apple - EarPods™ with Remote and Mic - White, description: Control media playback, adjust the volume and answer and end calls on your Apple&#174; iPod&#174;, iPhone&#174; or iPad&#174; with these Apple EarPods&#8482; MD827LL/A, which feature an in-line remote and mic for ease of use., brand: Apple, categories: [Audio, Headphones, All Headphones], hierarchicalCategories: {lvl0: Audio, lvl1: Audio > Headphones, lvl2: Audio > Headphones > All Headphones}, type: Earbud headphones, price: 29.99, price_range: 1 - 50, image: https://cdn-demo.algolia.com/bestbuy-0118/6848136_sb.jpg, url: https://api.bestbuy.com/click/-/6848136/pdp, free_shipping: true, rating: 4, popularity: 21462, objectID: 6848136, _snippetResult: {description: {value: Control media playback, <em>a</em>djust the volume <em>a</em>nd <em>a</em>nswer <em>a</em>nd end, matchLevel: full}}, _highlightResult: {name: {value: <em>A</em>pple - EarPods™ with Remote <em>a</em>nd Mic - White, matchLevel: full, fullyHighlighted: false, matchedWords: [a]}, description: {value: Control media playback, <em>a</em>djust the volume <em>a</em>nd <em>a</em>nswer <em>a</em>nd end calls on your <em>A</em>pple® iPod®, iPhone® or iPad® with these <em>A</em>pple EarPods™ MD827LL/<em>A</em>, which feature <em>a</em>n in-line remote <em>a</em>nd mic for ease of use., matchLevel: full, fullyHighlighted: false, matchedWords: [a]}, brand: {value: <em>A</em>pple, matchLevel: full, fullyHighlighted: false, matchedWords: [a]}, categories: [{value: <em>A</em>udio, matchLevel: full, fullyHighlighted: false, matchedWords: [a]}, {value: Headphones, matchLevel: none, matchedWords: []}, {value: <em>A</em>ll Headphones, matchLevel: full, fullyHighlighted: false, matchedWords: [a]}]}}, {name: Philips - hue A19 Smart LED Light Bulb - White Only, description: Philips hue A19 Smart LED Light Bulb: Get lighting that's as smart as you are. You can easily dim this light bulb and set timers and alarms using your smartphone or tablet. Plus, LED technology offers lasting illumination while using minimal energy., brand: Philips, categories: [Smart Home, Smart Lighting, Smart Light Bulbs], hierarchicalCategories: {lvl0: Smart Home, lvl1: Smart Home > Smart Lighting, lvl2: Smart Home > Smart Lighting > Smart Light Bulbs}, type: Smart lighting, price: 14.99, price_range: 1 - 50, image: https://cdn-demo.algolia.com/bestbuy-0118/4374300_sb.jpg, url: https://api.bestbuy.com/click/-/4374300/pdp, free_shipping: false, rating: 4, popularity: 21461, objectID: 4374300, _snippetResult: {description: {value: Bulb: Get lighting that's <em>a</em>s smart <em>a</em>s you <em>a</em>re, matchLevel: full}}, _highlightResult: {name: {value: Philips - hue <em>A</em>19 Smart LED Light Bulb - White Only, matchLevel: full, fullyHighlighted: false, matchedWords: [a]}, description: {value: Philips hue <em>A</em>19 Smart LED Light Bulb: Get lighting that's <em>a</em>s smart <em>a</em>s you <em>a</em>re. You can easily dim this light bulb <em>a</em>nd set timers <em>a</em>nd <em>a</em>larms using your smartphone or tablet. Plus, LED technology offers lasting illumination while using minimal energy., matchLevel: full, fullyHighlighted: false, matchedWords: [a]}, brand: {value: Philips, matchLevel: none, matchedWords: []}, categories: [{value: Smart Home, matchLevel: none, matchedWords: []}, {value: Smart Lighting, matchLevel: none, matchedWords: []}, {value: Smart Light Bulbs, matchLevel: none, matchedWords: []}]}}], nbHits: 21157, page: 0, nbPages: 200, hitsPerPage: 5, exhaustiveNbHits: false, exhaustiveTypo: true, exhaustive: {nbHits: false, typo: true}, query: a, queryAfterRemoval: a, params: query=a&hitsPerPage=5, renderingContent: {facetOrdering: {facets: {order: [brand, hierarchicalCategories.lvl0, categories, price, free_shipping, rating, type]}, values: {brand: {order: [Apple], sortRemainingBy: count}, categories: {sortRemainingBy: count}, free_shipping: {sortRemainingBy: count}, hierarchicalCategories.lvl0: {sortRemainingBy: alpha}, price: {sortRemainingBy: count}, rating: {sortRemainingBy: count}, type: {sortRemainingBy: count}}}}, extensions: {queryCategorization: {}}, processingTimeMS: 6, processingTimingsMS: {_request: {roundTrip: 17}, extensions: 1, fetch: {scanning: 2, total: 2}, getIdx: {load: {total: 1}, total: 1}, total: 6}, serverTimeMS: 7}

Process finished with exit code 0

Changes included:

  • Fix DioRequester.requestUri method

🧪 Test

Run the example clients/algoliasearch-client-dart/packages/client_core/example/example.dart which should successfully return Algolia hits.

@techouse techouse requested a review from a team as a code owner July 10, 2024 22:15
@techouse techouse requested review from Fluf22 and millotp July 10, 2024 22:15
@techouse techouse changed the title fix(dart): fix DioRequester.requestUri when request.queryParameters is not empty fix(dart): fix DioRequester.requestUri when ApiRequest.queryParameters is not empty Jul 10, 2024
@techouse techouse changed the title fix(dart): fix DioRequester.requestUri when ApiRequest.queryParameters is not empty fix(dart): fix DioRequester.requestUri when HttpRequest.queryParameters is not empty Jul 10, 2024
@techouse
Copy link
Contributor Author

techouse commented Jul 16, 2024

This probably flew under the radar for so long because all the Dart client API calls are done via POST?

CC/ @aallam @shortcuts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant