Why is req.query always empty? - reactjs

I'm trying to make a POST request to Express, but whenever I do, I can't access req.query. It's always empty.
The POST request works in Postman, but I can't get it to work in React.
I am wondering if whatever axios is sending over is not readable by the Express middleware. I'm new to Express, so I'm sure I'm missing something basic. Thanks for reading!
From my React file:
tryPost = () => {
axios.post('/login', {
firstName: 'Tom',
lastName: 'Rains'
});
}
From my Express file:
app.post('/login', (req, res) => {
console.log('test'); //prints test
console.log(req.query); //prints as {}
})

req.query refers to query string parameters, in your example you POST a JSON formatted body, no query string parameters are sent hence req.query is empty.
Depending on what way you intend to POST the data, if you want to pass it as query string data then you need to do:
axios.post('/login?firstName=Tom&lastName=Rains');
And then your code would work as is. However, If you want to POST the data as a body (like your example), then there is an additional change that needs applied in your express app i.e.
app.use(express.json())
This will ensure the JSON body gets parsed, then you can access the data via req.body from your route.
Note - Make sure this is configured before you setup your routes

Related

How to secure client http calls to the backend?

I am trying to figure out what is the best way to prevent random people access/make requests to the server.
Currently, everyone that have the url and the endpoint can easily make requests and I believe it's kind of security breach.
I am using Express.js that hosting static build of React.js
Here is an example of a call:
// Client:
async function getData(id){
try {
const res = await axios.get(`${backendDomain}/data/${id}`)
const data = res.data
return data
} catch (error) {
...
}
}
// Server:
app.get('/data/:id', function(req, res) {
...logic
res.send(data);
});
I tried adding to the Client "x-api-key" header and pass an api key that only I have and add a middleware that will check the api and see if it passed currectly from the client. But obviously it is not a good solution because you can see the key on "Network" section while inspecting.
What can I do?
Looking for the best way to prevent random people accessing the data

Getting json data from url

How do I get a JSON response from URL?
In my case, the URL is https://api.mathjs.org/v4/?expr=2*2 JSON response and then whenever someone types !test it sends the json/data from the URL.
Here is some sample code using node-fetch, I cant guarantee it will work well
const fetch = require('node-fetch')
(async () => {
const response = await fetch(`https://api.mathjs.org/v4/?expr=${encodeURIComponent(2*2)}`).then(r => r.text())
console.log(response)
})()
this logs 4.
this is a sample code as i said,
you would have to modify it to your needs, i used a iife as fetch method returns a promise
you can do:
<message>.channel.send(`the result is ${response}`)
as a example adapted from the above given code
ps: rather than using a api for math you could use mathjs package (which your using, just its the api version)
Edited: forgot of encodeURIComponent in fetch request url, or you will get a Only absolute URLs are supported error
You don't need JSON just to get the value of the query parameter from the URL. If you just need to get the number you can try it with URLSearchParams:
console.log(window.location.search); //output: '?expr=2*2'
var params = new URLSearchParams('?expr=2*2');
console.log(params.has('expr')); //output: 'true';
console.log(params.get('expr')); //output: '2*2';
you get the value from params.get('expr'));

JSON.stringify in response option of cy.route is not working

I'm currently writing tests on Cypress for an application writen in react and using redux and redux-saga. For one of my tests, I'm trying to stub a request and returning a response that the code is expecting to be an 'stringified' array by JSON so it can be parsed later.
I've tried to specify a response in the cy.route() command using JSON.stringify([desiredResponse]) but that is not working, response keeps being kind of parsed by Cypress or some other middleware before getting to the saga.
I've also tried to intercept the response in the onResponse option but seems to me like that's being executed once the response was delivered (not sure about this, made a couple of vague tests only)
// This is how my cy.route() config looks like
cy.route({
method: 'POST',
url: 'someUrl',
response: JSON.stringify([myResponse]),
});
And in my saga:
// I call the url via axios and immediately after I try to parse it
try {
const parsed = JSON.parse(response.data);
} catch (err) {
const parsed = [];
}
I would expect my response in the saga to be something like: "[myResponse]" but I got the raw array instead
Out of curiosity: have you tried avoiding to wrap [myResponse] into JSON.stringify()?
Something like
cy.route({
method: 'POST',
url: 'someUrl',
response: [myResponse],
});
Anyway: in my app, with your exact situation, my only difference with your code is that I leverage the Cypress fixtures .
Could you share a simple GitHub repo with your simplified code?

Reactjs/JS - Confused about the object/ what is being created

I have just switched over from studying Java to studying Javascript and I am trying to learn React and Redux right now. I am having some confusion with how some objects seem to be created in this tutorial I have been following on YouTube. This tut has so far just covered logging in and signing into a webpage.
api.js
import axios from "axios";
export default {
user: {
login: credentials =>
axios.post("/api/auth", { credentials }).then(res => res.data.user),
signup: user =>
axios.post("/api/users", { user }).then(res => res.data.user),
confirm: token =>
axios.post("/api/auth/confirmation", { token }).then(res => res.data.user)
}
};
This is what I am understanding from this code currently:
axios is imported so that various HTTP requests can be made. A user object is created that contains an array of 3 objects (functions?) : login, signup and confirm. In login object, an arrow function is used to pass credentials as the parameter into the axios object's post function. A promise is then called where the response data is passed into ??? which returns a res.data.user object.
I don't understand what the res.data.user object is, why is it described in such form with the dot separation instead of just something like responseDataObject?
This next piece of code is the 'action' part of the app (Redux) where the api.js is imported. Here 2 of the functions are exported into a new function which is called depending on the state of the user.... I don't think the other parts are relevant to talk about because I understand that programming logic. What I don't understand is how and why the res.data.object is returned like that. Where is the data part coming from? Is that arbitrarily described?
I am clearing missing something here, I've been watching some videos to try to understand what's going on but I think it might be a simple reason best described here.
There are a few terminologies you are using or understanding incorrectly. I think it is important to understand them before dive too deep into React.
First, Object:
An object has key/value pairs.
{
fruit: "apple"
}
that contains an array of 3 objects (functions?)
This would be incorrect. Since array's syntax is []. What you were describing is element or member or key.
Next part is about the promise in Javascript. You have this code. axios.post("/api/auth", { credentials }).then(res => res.data.user), This is basically saying once you call the api with that url, some data will come back(we stored in res). But the res is an object in this case.
If you console log res, you will get an object like this:
{
...
key1: "something",
key2: "something else",
data: {
...
user: { //some info about the user}
...
},
...
}
What you want is the data inside of res, more specifically you want the user's value. So to access it, you want to use res.data.user.
Hopefully, this answers some of your questions, but there is a lot to talk about. You should read more on js's object.
https://www.w3schools.com/js/js_objects.asp
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
Welcome to JS world :)
A user object is created that contains an array of 3 objects
(functions?)
Yep it's just 3 simple functions
A promise is then called where the response data is passed into ???
which returns a res.data.user object.
Promise is resolved (then function called) when server response status 2** and inside then res is just simple object witch is come from server (status, headers, response body), here is docs describing what res contains: https://www.npmjs.com/package/axios#response-schema
So inside res.data - client assumed that server responds with user object which contains some user data (example server returns json {user: {id: 1, name: 'Hary'}})
I don't understand what the res.data.user object is, why is it
described in such form with the dot separation instead of just
something like responseDataObject?
You just accessing object properties (example res = {data: {user: {id: 1, name: 'Hary'}}})
So this code .then(res => res.data.user) just an simple helper to return user and not whole response from server, here how you can use it user.login({login: 'cool_user', password: 'qwerty'}).then(user => console.log(user.id)) so if I assumed that sever retunrs this data you got into console user id after success login
One thing not covered in the other posts is this syntax:
export default {
// ...
};
This exports an object from the api.js file. This object is not assigned to a variable or given a name here. Instead, you do that when you import:
import api from 'api.js';
Now in the file with this import, the name api refers to the object exported from api.js. So you can do things like api.user.login(credentials) to call one of the functions defined iniside this object.

Restangular POST data not being read by Django

I've done a lot of searching and nothing seems to fully address this. I've created a REST API that has a resource to send a message. The path is /api/v1/conversation/{type}/{id}/message. Placing a POST call to that URI will create a message for the given conversation.
Everything works great if I just use $.post('/api/v1/conversation/sample/sample/message', {message: "All your base are belong to us"});
However, I'd like to use Restangular, and for some reason, it is sending the POST data in a way that I have to work with request.body instead of request.POST.get('message'). This is terribly inconvenient if I have to do this with every single server side API.
Here's my Restangular code:
conversation = Restangular.one('conversation', scope.type).one(scope.type_id);
conversation.post('message', {message: "All your base..."})
To clarify, it is POSTing to the correct URI, it just is sending the post data as a payload instead of as form data. How can I configure it to send the post as form data?
Edit:
As a side note, I was able to mitigate this issue by creating a utility function:
def api_fetch_post(request):
post = request.POST
if not post:
try:
post = json.loads(request.body.decode(encoding='UTF-8'))
except:
pass
return post
This way I can accept either type of POST data. Regardless, is there a way to send form data with Restangular?
Yes, there is.
var formData = new FormData();
formData.append('message', $scope.message);
// Or use the form element and have formData = new FormData(formElement).
Restangular.one('conversation', $scope.type).one($scope.type_id)
.withHttpConfig({transformRequest: angular.identity})
.post(formData, null, {'Content-Type': undefined})
.then(function(response){
// Do something with response.
});

Resources