What's the difference between req.params and req.query?

Question

What’s the difference between req.params and req.query?

Answer

they are both important parts of the request received in our route, let’s remember that the request arrives in our callback function as an object, ie.:

app.get('/', (req,res,next)=>{...});
/*             ^
               |____ this parameter will receive an object argument, 
as a matter of fact, req and res are received as objects from 
the get method, and next is a function that will allow us to 
move to the next request or action.

With that in mind, the request object has been created with key/value pairs of which two are quite important.

  • One is params: it is an object inside the request object, and it only contains any parameters passed to the route, for example,
    from the route: /lor/creatures/:name if we were to make a request /lor/creatures/gollum gollum is the name parameter and so we could find it in the object as: req.params.name which equals to gollum or
 { //req object
  params: {
    name: 'gollum'
  },
...
}
  • The other is query: it is also an object but it contains only the keys and values related to the query on the request route, for example,
    from the route: /lor/creatures/hobbit?familyname=Baggins&home=Shire we get two query parameters, familyname and home and so our object would look like:
{ //req object
  params: {
    name: 'hobbit'
  },
  query: {
    familyname: 'Baggins',
    home: 'Shire'
  }
...
}

this way we can get each as req.query.familyname which is Baggins and req.query.home which is Shire.

Both are closely related but they are not the same at all, params are parameters set for the route, query are values resembling variable assignment that provide extra information on what is being required for the route and it will always start with a ? on the URL, inherently they are both string values that express extrapolates into objects and key/value pairs from the req object.

In the last example we see that the params name contains hobbit and the query has two relevant values, the familyname which is Baggins and the home which is the Shire. since we can use dot notation on those objects to access these values, we can compare and manipulate data with them to send the necessary response.

Something to keep in mind is that we won’t always have values in this two objects but they will always be part of the request object, for example, a request to the root route /, will give us empty objects for both:

req.params // is {}
//and
req.query // is also {}
3 Likes

In exercise 6, we see the following code:

app.put('/currencies/:name/countries', (req, res, next) => {
  const currencyName = req.params.name;
  const countries = req.query;
  currencies[currencyName] = countries;
  res.send(currencies[currencyName]);
});

I was thinking that the req.params would contain the countries because there isn’t a question mark to indicate the query object. But it seems that the req.query has the value of countries. I am just wondering how to know if the req.params or req.query will have the information that was passed in.

1 Like

From my understanding of routes, req.query is not a part of the route path, they only contain new information to be added (POST) or updates to an existing data (PUT). So req.params only points to the specific resource an action (CRUD) should be carried out on.

I have a question about exercise 6 as well:

“Write a route to handle PUT requests to /currencies/:name/countries .
The :name param represents the currency name in the currencies object. The updated array of countries that use this currency will be sent in a query.
This route handler should replace the countries array of the correct single-currency object with an updated array from the query. It should send the updated array as a response.”

const currencies = {
diram: {
countries: [‘UAE’, ‘Morocco’]
};

app.put(’/currencies/:name/countries’, (req, res, next) => {
const currencyName = req.params.name;
const countries = req.query;
currencies[currencyName] = countries;
res.send(currencies[currencyName]);
});

The instructions say that this code will return a new array of cities that are put to the currency name param, but I don’t understand how. It looks like res.send(currencies[currencyName]) would return the currency object with a list of currency names, e.g “currency[diram]”?

Seems like it would make more sense if it was res.send(currencyName[countries]) and it returned something like “diram[countryname, countryname, countryname]”. Maybe I’m taking the variable names too literally, but I can’t get it straight in my head.

8 Likes

Same Question for me

Unclear instructions. It says that the route

should send the updated array as a response.

What it doesn’t say is that you have to send the ‘currency’ object, then it’ll pass.

This is my version that passed:

app.put('/currencies/:name/countries', (req, res, next) => {
  const currency = req.params.name;
  if(currencies.hasOwnProperty(currency)) {
    currencies[currency].countries = req.query.countries;
    res.send(currencies[currency]);
  } else {
    res.status(404).send('Not found');
  }
});

It kind of makes sense if you think about it. Response returns the same type of object as the one that arrived in Request. But this is not a general rule and so the instructions should be clearer.

@spencerm93 @amingholamisani40714
I think the issue comes from how this is tested because if you pass a query to the route

The req.query object would normally be :

{
country_1 : Ghana,
country_2: Malaysia
}

Thus the way the solution code is implemented would not actually work.

However, if you check the test.js in the folder for this exercise, you’d see a portion of code that looks like:

describe(‘’, function() {
it(‘’, function(done) {
process.env.PORT = 8000;
const appModule = rewire(‘…/app.js’);
const app = appModule.get(‘app’);
const currencies = appModule.get(‘currencies’);
const currencyName = Object.keys(currencies).pop();
let updateTestObject = {
> countries: [‘test’, ‘test’],
> };
> request(app)
> .put(/currencies/${currencyName}/countries)
> .query(updateTestObject)
.then((response) => {…

What this means is that in this exercise in the code that tests yours they already set
req.query = { **
** countries: [Ghana, Malaysia]

** }**
The equivalent url for this query is:
**

/currencies/diram/countries?countries=[Ghana,Malaysia]

**
It doesn’t look like what you’re used to but it works, tried it on my browser.

now we have the currecy name from req.params.name and an object with a countries key with a value of an array containing the new countries from req.query which we can choose to save in a variable countries
so to reassign the item in our currencies object we do:

currencies[currencyName] = countries

OR

> currencies[currencyName][countries] = req.query.countries

I hope this makes sense now.

1 Like

Yeah, this is a very bad example that can easily confuse people, especially new learners.

Thanks for this post. So just for my own sanity, how should this put request be done in a real scenario (i’m testing it on Postman and it doesn’t work)?

I haven’t used postman before, but the general thing in api is ensuring the front end request and the back end handling the request know how they want to communicate. Eg As an analogy, if the front end is going to send dollars, the back end handling the request should be accepting dollars and not euros.

So if you want to send request with query strings from the front end , ensure your route can extract the query strings.
Although when sending sensitive data like password, social security numbers and pins it is preferable to send them in the body of the request, then use something like “req.body” to access it at the back end which can be extracted using req.query .

For a shopping site where users can user a search bar, using query strings color=red would do no harm

Hope that helps, else can you be more specific about the problem you’re experiencing ?

Thanks for the info. I got there with it in the end, i rewrote it all with square bracket syntax, simplified it slightly and it passed. The whole codecademy express module has been tricky, it’s not particularly well written and i think there’s a fair few people getting frustrated with it. It’s all good practice in the end

Alright , You’re Welcome