22

I am using Axios with NodeJs and trying to pass path parameters in axios.get() method. For example, if URL is url = '/fetch/{date}', I want to replace {date} with the actual date while calling axios.get(url).

I went through the source code on Github and StackOverflow, but couldn't find any method.

Is it possible to keep URLs with parameters as a placeholder and replace them while actually calling the get method of Axios?

Saheb
  • 1,392
  • 3
  • 13
  • 33

7 Answers7

10

Axios doesn't have this feature and it looks like the team don't want to add it.

With credit to previous responders for inspiration, to me this seems like the solution closest to what you (and me) are looking for:

1 - Where you want to store all your URLs and their parameters, define them as functions which use a template string to return the composed URL:

export var fetchDateUrl = (date) => `/fetch/${date}`;

If you need any type-specific formatting of the value being concatenated into the URL, this function is a good place to do it.

2 - Where you want to make the request, call the function with the correct parameters:

import { fetchDateUrl } from 'my-urls';
axios.get(fetchDateUrl(someDateVariable))...;

Another variation, if you really like the idea of naming the parameters at the call site, you can define the URL function to destructure an object like this:

var fetchDateUrl = ({date}) => `/fetch/${date}`;

which you'd then use like this:

axios.get(fetchDateUrl({date: someDateVariable}));
Graham Lea
  • 5,797
  • 3
  • 40
  • 55
  • This is potentially dangerous because it leaves open an opportunity for a URL injection attack, i.e. someone could include a tricky snippet in the `date` variable to hit a different endpoint than the programmer intended. – paulkernfeld Oct 21 '21 at 19:18
  • @paulkernfeld I think your comment could have been more helpful rather than critical. Perhaps something like: "People should be careful, when concatenating user data into URLs, that they validate the data first to avoid an injection attack." Instead, it looks like you're just trying to scare people away from this because you think it's unsafe, but I'm pretty sure there's no way to do get a variable into a URL path without concatenating strings. Happy to be corrected if you know a way. – Graham Lea Nov 04 '21 at 12:21
  • On the topic of this being "dangerous": If the server-side security is implemented correctly, deliberate manipulation of URLs on the client should be a very minor concern. One of the most important rules of web security is: don't trust the client. People can and do manipulate URLs any time they want just by changing what's in the address bar. We should exercise caution in everything we do, but I think the risk impact for this particular scenario is trivial. – Graham Lea Nov 04 '21 at 12:40
9

I think using axios interceptors is better to do this :

//create your instance
const instanceAxios = axios.create({
  baseUrl: 'http://localhost:3001'
]);

instanceAxios.interceptors.request.use(config => {
    if (!config.url) {
        return config;
    }

    const currentUrl = new URL(config.url, config.baseURL);
    // parse pathName to implement variables
    Object.entries(config.urlParams || {}).forEach(([
        k,
        v,
    ]) => {
        currentUrl.pathname = currentUrl.pathname.replace(`:${k}`, encodeURIComponent(v));
    });

    const authPart = currentUrl.username && currentUrl.password ? `${currentUrl.username}:${currentUrl.password}` : '';
    return {
        ...config,
        baseURL: `${currentUrl.protocol}//${authPart}${currentUrl.host}`,
        url: currentUrl.pathname,
    };
});


// use like : 
instanceAxios.get('/issues/:uuid', {
   urlParams : {
       uuid: '123456789'
   }
})

For typescript users, you will need to add this, in one of your .d.ts

declare module 'axios' {
    interface AxiosRequestConfig {
        urlParams?: Record<string, string>;
    }
}

( this is a POC, not really tested, doesn't hesitate if you see something wrong )

thib3113
  • 564
  • 7
  • 19
  • 1
    If you're going to use this approach, I'd suggest calling them `pathVars` rather than `urlParams`, because URL parameters are already a thing and the term path variable is used for these substitutions in other tools (Spring, at least). – Graham Lea Apr 12 '20 at 02:43
  • 1
    @GrahamLea in fact, I use the same naming as express https://expressjs.com/fr/4x/api.html#req . Express call it `params`, and `params` are already used for the querystring in axios ... As a node developper, urlParams seems more logic than pathVars ... I need some more feedback for this ... – thib3113 Apr 12 '20 at 12:53
8

Use template strings

    url = `/fetch/${date}`

Or just tag it on

    url = '/fetch/'+ date
sharkdawg
  • 958
  • 1
  • 8
  • 20
  • 1
    I want to keep all the API URLs in a constant file, using template strings will need `date` variable to be defined in the scope. Don't want to use `'/fetch/' + date`, as it would not be very clear to the person reading API URLs in the constant file what is the complete API URL. – Saheb Feb 12 '18 at 17:45
  • If you want something to be clear for someone reading your URLs in a constant file then use comments. Adding a placeholder makes no sense – sharkdawg Feb 12 '18 at 18:11
  • 3
    This is potentially dangerous because it leaves open an opportunity for a URL injection attack, i.e. someone could include a tricky snippet in the `date` variable to hit a different endpoint than the programmer intended. – paulkernfeld Oct 21 '21 at 19:18
3

You can use template strings ie:

let sellerId = 317737

function getSellerAnalyticsTotals() {
    return axios.get(`http://localhost:8000/api/v1/seller/${sellerId}/analytics`);
}
1

Given some API /fetch/${date} you likely want to wrap your axios call in a function.

const fetchData = (date) => axios.get(`/fetch/${date}`);

fetchData(dateObject.toFormat('yyyy-mm-dd'))
  .then(result => { ... });

This requires the calling code to format date correctly however. You can avoid this by using a DateTime library that handles date string parsing and do the format enforcement in the function.

const fetchData = (date) => axios.get(`/fetch/${date.toFormat('yyyy-mm-dd')}`);

fetchData(dateObject)
  .then(result => { ... });
Drew Reese
  • 165,259
  • 14
  • 153
  • 181
0

you can do like this:

    getProduct = (id) => axios.get(`product/${id}`);
sajad abbasi
  • 1,988
  • 2
  • 22
  • 43
  • Your approach will not append the id to the url(pass it as url param), instead it will append it to request query params resulting in a request like: `/product?id=12345` – Jerome Jun 03 '21 at 14:31
  • @Jerome Hi, I've edied my answer, thanks! – sajad abbasi Jun 04 '21 at 16:42
-3

I always do it like this:

const res = await axios.get('https://localhost:3000/get', { params: { myParam: 123 } });

I find this to be much clearer than template strings.

More explanation here

Jochem
  • 31
  • 6
  • These are query params, which will produce the path "https://localhost:3000/?myParam=123". "Path params" created using the above answers will produce the correct result, as some APIs explicitly require a specific string (eg. a date) in the path itself such as "https://thirdpartyapi.com/". – Brendan May 13 '22 at 21:44