0

I'm using a 3rd party API and passing a query like so to the end of the url:

?query="status:2 OR status:3"

When I do the Get request in postman this works

In angular I am trying to get the api call to work however I am not sure how.

I have tried this

q = 'query="'+ encodeURI(filterQuery)+'"';
let url = `${this.apiUrl}/api/?${q}`;
return this.httpClient.get<Item[]>(url, this.httpOptions);

this qives a bad request, i think it is performing some extra encoding on the double quotes looks like this in chrome

   ?query=%22status:2%20OR%20status:3%22

EDIT:

I suspect thhe httpclient is doing the encoding. It does not work with this either:

let url = `${this.apiUrl}/api/?query="status:2 OR status:3"`;
return this.httpClient.get<Item[]>(url, this.httpOptions);

Also from the api docs:

The query must be URL encoded

Query string must be enclosed between a pair of double quotes and can have up to 512 characters

raklos
  • 28,027
  • 60
  • 183
  • 301
  • will this work? `q = 'query=\"'+ encodeURI(filterQuery)+'\"';` – naveen Sep 15 '22 at 15:02
  • @naveen no that didn't work – raklos Sep 15 '22 at 15:07
  • 1
    It would appear that the 3rd party API is not standards compliant. Double quotes should be encoded as %22 in the URL and the API should decode the url - see https://stackoverflow.com/a/7109208/592958 for more info. – phuzi Sep 15 '22 at 15:17
  • Does it work if you use `?query=%22status:2%20OR%20status:3%22` directly in postman instead of `?query="status:2 OR status:3"`? Based on that you could figure out if the API has the problem or if `this.httpClient.get` e.g. does some additional encoding. – t.niese Sep 15 '22 at 15:25
  • @t.niese interestingly yes, that works in postman too – raklos Sep 15 '22 at 15:28
  • Ok, you then are using `this.httpClient.get` wrong. I don't use angular, but based on the [documentation](https://angular.io/guide/http#requesting-data-from-a-server), the parameters have to be passed to `options`. Could you try if this works (you may need to change it a bit if the typescript compiler complains) ```this.httpClient.get(`${this.apiUrl}/api/`, {...this.httpOptions, params: {query:'"status:2 OR status:3"'}})``` – t.niese Sep 15 '22 at 15:33

1 Answers1

0

With the angular HTTP client, you actually don't need to construct the URL yourselves (and if you did, I would suggest you use the URLSearchParameters API, again, not doing it yourself, but since you're using angular, forget about that lol). As explained here, you can simply pass the params in the options, and it will construct the query for you.

In your case, that would be:

return this.http.get<Item[]>(
    `${this.apiUrl}/api/`,
    { params: { query: filterQuery }},
);

Also, no query=%22status:2%20OR%20status:3%22 is correct, as it results in the correct string when you run it through decodeURIComponent:

console.log(decodeURIComponent("query=%22status:2%20OR%20status:3%22"));

I would first suggest you try to remove the extra / at the end of your path (I'm currently not up to speed if the specifications allow that or not, but it seems uncommon).

"/api/?query="status:2 OR status:3"
     ^
     | This here

According to: https://www.rfc-editor.org/rfc/rfc3986#section-6.2.3

Normalization should not remove delimiters when their associated component is empty unless licensed to do so by the scheme specification. For example, the URI "http://example.com/?" cannot be assumed to be equivalent to any of the examples above.

If MY interpretation of this is correct, the trailing slash will (potentially) result in an empty entry in the path component, which (potentially) causes different behavior.

And if that doesn't work, you should probably tell the "third party", that their API is not working .

If you want to further debug it, I would suggest copying the URL, that is not working, from the "Network" tab of your browser's debugging tools. Then put that into

fetch(<your url here>)
    .then(r => r.json())
    // or .then(r => r.text()) depending on what data is expected
    .then(console.log);

and modify the URL until it works. If that works, you can adjust your angular code, so it gives you the matching output.

Elias
  • 3,592
  • 2
  • 19
  • 42
  • 1
    Based on the [RFC-3986](https://datatracker.ietf.org/doc/html/rfc3986#section-6.2.4) `/api/` and `/api` can point to different resources. In practice, they are most of the time treated as equivalent. Which one to use depends on what the API suggests to use. Sometimes one redirects to the other so hopefully, the URL that is suggested by the API is the one that is not redirecting. – t.niese Sep 15 '22 at 16:13
  • @t.niese yes, as suggested by section https://datatracker.ietf.org/doc/html/rfc3986#section-6.2.4, but I found that (exact wording / description) could lead to more confusing rather than being helpful for the answer. – Elias Sep 15 '22 at 16:15
  • 1
    Yes you are right I linked the correct one **6.2.4 Protocol-Based Normalization** , but you are referencing the `6.2.3` in your answer, I got confused due to that. `6.2.3` has nothing to do with what I'm talking about. – t.niese Sep 15 '22 at 16:24
  • 1
    `If MY interpretation of this is correct, the trailing slash will (potentially) result in an empty fragment, which (potentially) causes different behavior.` a fragment of an URL is the part starting at `#` and the presence or absence of a fragment does not change an HTTP request because the fragment won't be sent with a request. – t.niese Sep 15 '22 at 16:27
  • 1
    `Normalization should not remove delimiters when their associated component is empty` that refers to the [syntax components](https://www.rfc-editor.org/rfc/rfc3986#section-3) of the URL (`scheme`, `authority `, `path`, `query` , `fragment`), So if you have `scheme://authority?` you should not remove `?` because the query component is empty. But that statement sees the `path` as one component. – t.niese Sep 15 '22 at 16:32
  • `fragment of an URL is the part starting at #` ah, yes I confused "fragment" with "component". – Elias Sep 15 '22 at 16:37
  • Specifically, the parts separated by `/` in the path component (as in modern APIs, it's not uncommon that those are not actual directory paths, so could cause problems when the expected value was to be an id, for example). – Elias Sep 15 '22 at 16:39
  • @t.niese I got confused because there are many words here that one might use interchangeably, especially if English is not their first language. Sorry! – Elias Sep 15 '22 at 16:41
  • Also if English is your first language (it isn't mine either), they could be used interchangeably outside of an RFC. But RFCs clearly define what terms mean by first introducing what they mean before they are used or referencing their definition at their first occurrence if the definition appears later in the document. – t.niese Sep 15 '22 at 16:48
  • `as in modern APIs, it's not uncommon that those are not actual directory paths, so could cause problems when the expected value was to be an id` ok, but how does this change anything? Again, base on the specs `/api/` and `/api` can point to different resources (that is what you say with that comment and what I said in my first comment). Both URL are valid, so you need to check the documentation which of those is the correct one. – t.niese Sep 15 '22 at 17:14