12

Goal

I want to pass query params for a GET request using axios. The param value is a variable of type string and has whitespace.

Problem

It seems axios is encoding the param in a format that my backend does not understand. I have done research on axios encoding and it appears axios encodes whitespace to a + and not %20.

Example

Let's say you have this request:

 const whitespace = "white space";
 const encodeWhitespace = encodeURI(whitespace);
 const noSpace = "no";

 axios.get('/api', {
   params: {
     'foo': 'bar',
     'bar': 'hello world',
     'space': whitespace,
     'encode': 'hello%20world', 
     'encoded': encodeWhitespace,
     'simple': noSpace
   }
}

The params foo, bar, encode, simple all work and generate a response with the correct data. The params space, encoded do not generate the correct data. The request is successful with 200 but returns no data.

I created the same request in Postman with the same queries to see if the GET returns the expected result and it does. I added the %20 in Postman and it returns just fine. I added the + in Postman and that returns the expected result as well.

Question

What might be going wrong with the variable implementation? I can't do it without the variable like the bar param because the value is being passed to a function (Redux action). Any ideas or thoughts on this would be helpful. Please comment if more information is needed.

Community
  • 1
  • 1
Bens Steves
  • 2,633
  • 3
  • 17
  • 28

1 Answers1

13

Seems like this is an issue (or the default parameter serialization behavior) of Axios library.

So to overcome this, you have 2 options.

  1. Define your query params in the URL itself
const whitespace = "white space";
axios.get(`/api?space=${whitespace}`);
  1. Write your own paramsSerializer to build the query string.
const whitespace = "white space";
const encodeWhitespace = encodeURI(whitespace);
const noSpace = "no";

axios.get('/api', {
    params: {
        'foo': 'bar',
        'bar': 'hello world',
        'space': whitespace,
        'simple': noSpace
    },
    paramsSerializer: (params) => {
        // Sample implementation of query string building
        let result = '';
        Object.keys(params).forEach(key => {
            result += `${key}=${encodeURIComponent(params[key])}&`;
        });
        return result.substring(0, result.length - 1);
    }
});

Note: The above paramsSerializer can be defined in the global level or Axios instance level as well.

  • Global level
axios.defaults.paramsSerializer = (params) => { /* ... */ };
  • Instance level
let axInstance = axios.create({ paramsSerializer: (params) => { /* ... */ } })
Udith Gunaratna
  • 2,091
  • 1
  • 13
  • 17
  • Thank you for your reply. I tried the first method before (I forgot to put that in my question) and it does not work. I saw your second method on axios' github issues and that method has not worked for me. :( Not sure what a good alternative would be here. The entire app uses axios so this is quite the bummer. – Bens Steves Oct 08 '19 at 10:39
  • I tested both approaches and both of them correctly sent the query params by replacing whitespaces with `%20`. What is the query string sent across when you used the 2nd method? – Udith Gunaratna Oct 08 '19 at 11:34
  • Udith Gunaratna, is the param serializer you provided in your answer complete? I added that directly to the source and it did not work. – Bens Steves Oct 11 '19 at 11:29
  • Note : `substr` has been deprecated, it's better to use `substring`, read the difference here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substring#the_difference_between_substring_and_substr – Fayçal Borsali Dec 16 '21 at 15:58
  • 1
    @FayçalBorsali Thanks, I updated the answer – Udith Gunaratna Dec 17 '21 at 09:16
  • This does not work for me for whatever reason. Any updates? – F.Tepel Feb 20 '23 at 06:47