Get data from HTTP GET request - javascript

I'm sending an HTTP GET request from the client to my server. On the server, I can't access the data that is passed with the GET request. It works for POST requests but the value is not received in the get request.
The client is Vue.js, and the Server is Express.js in Node.js. The code looks like this.
Client:
var response = await axios.get('/endpoint',{ key: 'value' });
Server:
router.get('/endpoint', async (req,res) => {
console.log(req.body); // empty
console.log(req.query); // empty
console.log(req.params); // empty
});
I've set up my body-parser above. It looks like below
const bodyparser = require('body-parser');
app.use( bodyparser.json() );
How do I access the {key: 'value'} object that is sent from the client in my server.

GET requests do not have bodies

With Axios you can path query params to GET call in 2 different ways:
By putting them into the endpoint path
await axios.get('/endpoint?key=value&key2=value2');
Add them to the config argument in params property object as key-value
await axios.get('/endpoint', { params: {key: 'value', key2: 'value2' }});
Your confusion absolutely makes sense, you try to use same way to pass param for get and post methods, but in Axios these methods have different number of arguments: post(url, data, config), get(url, config)
Let's return to your example:
var response = await axios.get('/endpoint',{ key: 'value' });
So now you can see that { key: 'value' } object that you pass as a second argument is request config and isn't a data.
You can learn more about request config params here - https://github.com/axios/axios#request-config

I believe the problem is that you want to access body by
console.log('req.body');
instead of
console.log(req.body);
Also, as pointed above, GET doesn't have body.

Related

FormData() append - Receive only empty objects

I started a new project and had never issues to append data to FormData and sending it to the backend. Currently, I receive only empty objects in the backend. What am I missing here?
this.first_name is not empty if I console.log it. That's not the problem here.
async createAgent() {
const data = new FormData()
data.append('first_name', this.first_name)
// data.append('last_name', this.last_name)
// data.append('phone', this.phone)
// data.append('email', this.email)
// data.append('languages', this.checkedLanguage)
// data.append('image', this.selectedFile)
try {
const post = await this.$axios.$post('/api/create-agent', data)
}
Node.js
exports.createAgent = async (req, res) => {
console.log(req.body.first_name);
console.log(req.body);
};
Console Output
undefined
{}
index.js (Node.js)
const app = express();
app.use(morgan("dev"));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
According to body-parser's docs:
This does not handle multipart bodies, due to their complex and typically large nature.
which in your screenshot, on the Request Headers part, is stated.
Solutions in your example are:
just send a JSON payload (parsed by bodyParser.json())
set Content-Type to application/x-www-form-urlencoded (parsed by bodyParser.urlencoded())
use the recommended modules for multipart body in the docs:
Docs: https://github.com/expressjs/body-parser/tree/1.20.0#readme
To send a JSON payload with axios which you are using in the OP, do:
axios.post({
first_name: "This is a JSON property"
})
or
$axios.$post()
which IF you're using nuxt/axios, is a convenient function that will return the response body instead of the whole response.
Docs: https://axios.nuxtjs.org/usage#-shortcuts

Parse sendBeacon data in Express

I'm trying to start logging my own WebVitals. The simple use-case in their example docs looks like this:
function sendToAnalytics(metric) {
// Replace with whatever serialization method you prefer.
// Note: JSON.stringify will likely include more data than you need.
const body = JSON.stringify(metric);
// Use `navigator.sendBeacon()` if available, falling back to `fetch()`.
(navigator.sendBeacon && navigator.sendBeacon('/analytics', body)) ||
fetch('/analytics', {body, method: 'POST', keepalive: true});
}
That all seems simple enough. Here's my actual implementation:
function sendToLog(metric) {
// Replace with whatever serialization method you prefer.
// Note: JSON.stringify will likely include more data than you need.
const body = JSON.stringify(metric);
console.log(`Sending body ${body}`);
// Use `navigator.sendBeacon()` if available, falling back to `fetch()`.
// (navigator.sendBeacon && navigator.sendBeacon('https://localho st:9292/api/log', body)) ||
fetch('https://localhost:9292/api/log', {body: body, method: 'POST', headers: { 'Content-Type': 'application/json' }, keepalive: true});
}
I had to modify the fetch to include the "body" property name and add headers to get it to work, but that is now working. However, if I uncomment the navigator.sendBeacon line, I just get {} for the body.
I'm using NodeJS and Express on the backend. My starting point was this:
const app = express();
app.use(
express.json({
// We need the raw body to verify webhook signatures.
// Let's compute it only when hitting the Stripe webhook endpoint.
verify: function (req, res, buf) {
if (req.originalUrl.startsWith(API_PREFIX + '/webhook')) {
req.rawBody = buf.toString();
}
},
})
);
app.use(cors());
// Expose an endpoint for client logging.
app.post(API_PREFIX + '/log', async (req, res) => {
const message = req.body;
console.log('Got message');
console.dir(message, { depth: null });
logger.info(message);
res.sendStatus(200);
});
There's this similar question, where the accepted answer suggests that adding body-parser and app.use(bodyParser.raw()) should do the trick, and then in the comments there's discussion of using bodyParser.json()) instead.
I've tried both of those:
import bodyParser from 'body-parser';
...
//app.use(bodyParser.raw());
//app.use(bodyParser.json());
app.use(
express.json({
// We need the raw body to verify webhook signatures.
// Let's compute it only when hitting the Stripe webhook endpoint.
verify: function (req, res, buf) {
if (req.originalUrl.startsWith(API_PREFIX + '/webhook')) {
req.rawBody = buf.toString();
}
},
})
);
app.use(cors());
(i.e., uncommenting either of the two lines at the beginning), and in all 3 cases I still get an empty body when sendBeacon is used.
The Express documentation says,
[express.json] is a built-in middleware function in Express. It
parses incoming requests with JSON payloads and is based on
body-parser....A new body object containing the parsed data is
populated on the request object after the middleware (i.e. req.body),
or an empty object ({}) if there was no body to parse, the
Content-Type was not matched, or an error occurred.
So, a) I guess I shouldn't need the body-parser, since express.json is just doing that anyhow; and b) I'm hitting one of those three conditions (there's no body to parse, the Content-Type was not matched, or an error occurred). Assuming that's the case, how do I diagnose which one it is, and then fix it (in such a way that the fetch fallback continues to work). Or, if there's some other problem, back to the original question, how do I get this to work? :)
navigator.sendBeacon sends Content-Type: text/plain whereas express.json() only parses the body if Content-Type: application/json.
Use express.text() in combination with JSON.parse(req.body) instead, or additionally:
app.post(API_PREFIX + '/log',
express.json(), express.text(), function(req, res) {
if (typeof req.body === "string") req.body = JSON.parse(req.body);
...
});

Headers not set node.js api push notification

Hello im trying to set up push notifications for my webapp.
I'm getting my subscription like I should.
It saves it to my database correctly.
It sends my notification like it should if there only is ONE user in the db
and i want to send to more than only one user :)
Im using:
Vue.js (framework)
Axios (post)
node.js (api)
mongoDB (database)
Here's my post to API.
await axios({
method: 'post',
url: 'API',
data: {
subscription: JSON.stringify(subscription),
storeId: storeId
},
headers: {
'Content-Type': 'application/json'
}
})
It registreres my post, but then i get an throw error.
that "Can't set headers after they are sent."
I'm using CORS in my app like this:
const cors = require('cors')
const app = express();
app.use(bodyParser.json());
app.use(cors())
app.use(morgan('combined'))
The way I'm handling the post from my website is by finding my subscriptions and then map through and say foreach subscription
webpush
//subscribe routes
app.post('/pushNotification', (req, res) => {
var storeId = req.body.storeId
res.setHeader('Content-Type', 'application/json');
console.log(storeId)
if (req.body.storeId != null) {
console.log('Test1')
//get pushSubscription object
//create payload
const payload = JSON.stringify({ title: 'push test' })
Push.find({
"storeId": storeId
},
'subscription', function(error, response) {
console.log('Test2')
console.log(response)
response.map(item => {
res.status(201).json({});
console.log('Test3')
var subscription = item.subscription
console.log(subscription)
webpush.sendNotification(subscription, payload).catch(err => console.error(err));
})
})
} else {
res.send("failed")
}
})
As i can read around somewhere is it im not setting headers or something right. I have used cors like in tutorials and stuff.
So it's like it is crashing because it iterates wrong.
but i can't see how.
ERROR MESSAGE:
Thanks in advance
you are getting this error because res.status(201).json({}) has already set the headers and sent back the response to the client but webpush.sendNotification also trying to set the headers.You should use only webpush.sendNotification(subscription, payload).catch(err => console.error(err));
res.json([body]) sets the corresponding header and sends the result:
Sends a JSON response. This method sends a response (with the correct content-type) that is the parameter converted to a JSON string using JSON.stringify().
So, first of all you don't need to set header manually.
second, If the response has more than one item, since you can't send multiple result for a request, you shouldn't use res.json in a map.
Moreover, be aware of webpush.sendNotification that it may send a result too.

Send body JSON with Postman in a POST method to execute procedure in ms sql server

I want to send a JSON (body) on Postman with POST method and receive a result.
Im a trainee and my boss asked me this. I've been looking in web for a week and didn't find. I said to him that method to receive a data is GET, but he said that GET has a limit on URL. If the stored procedure have a lot of parameters we will not receive the expected result, so a I have to use Post method.
This is my code to connect to ms sql server:
var express = require('express');
var app = express();
var sql = require('mssql');
var config = {
user: 'MY_USER',
password: 'MY_PASS',
server: 'MY_SERVER',
database: 'MY_DB'
};
Searching in google I found a way to execute a procedure with GET method. In the browser I put the value I want and I receive the result, but is not still what he wants. The code is:
app.get('/get/:pNU_EST001', function (req, res) {
//conexão com o DB
sql.connect(config, function(){
var request = new sql.Request();
request.input('pNU_EST001', req.params.pNU_EST001);
request.execute('dbo.ESTSP004_ConsultaLivrosEmprestadosAluno_XX', function(err, recordsets, returnValue, affected) {
if(err) console.log(err);
res.send(recordsets);
//res.end(JSON.stringify(recordsets)); /*--- result in JSON format ---*/
});
});
});
On Postman he showed me a example with DB2, but I couldn't see the code. On Post Method, on HEADERS it has two key:
KEY => Content-Type (value: application/json) // KEY => Accept (value: application/json)
And in his example, on BODY, he wrote a JSON like: { "pNU_EST001" : "3"} and received the related result below. That's what I need.
Express has a few other verbs to use you are using
app.get but there is also app.post if you change your code to use the latter instead it will handle a post request
app.post('/path', function (req, res) {
Then in express to get values from the POST body you get that from
req.body property
So in your case you would want to use req.body.pNU_EST001 instead of req.params.pNU_EST001

How to perform a POST request with session data to an endpoint within the server node js

I am working on express and I need to perform a POST request to an endpoint within the server. My code for this is :
request({
url : 'http://localhost:3000/api/oauth2/authorize',
qs:{
transaction_id:req.oauth2.transactionID,
user:req.user,
client : req.oauth2.client
},
headers:{
'Authorization':auth,
'Content-Type':'application/x-www-form-urlencoded'
},
method:'POST'
},function(err,res,bo){
console.log("Got response with body :"+bo);
});
localhost is the current server, this works properly but the session data is lost when i perform the POST request.
Is there any other way to perform a POST within the same server or to save the session data such that it is maintained after the POST?
Well, typically you register your routes something like:
var handlePostRequest = function(req,res,next) {
// process req.body etc.
};
app.post('/api/oauth2/authorize', handlePostRequest);
If you want to call that endpoint from within your application, you simply call handlePostRequest() providing the req, res, next objects as well.
Assuming handlePostRequest is in global scope, or required already; in your example that would be:
app.get('/some/other/endpoint', function(req,res,next){
// override the default req.body with your supplied data
req.body = {
transaction_id: req.oauth2.transactionID,
user: req.user,
client: req.oauth2.client
};
// you may also override req.headers etc. for authorization
// ...
// then call the "api" again with the new values
return handlePostRequest(req,res,next);
});
IF you however strictly want to make a POST request (for some reason), you need to supply the sessionID as well, which will be in your cookie. Then the session data will be available.

Categories

Resources