On the client-side, I want to observe a resource with a large message and I'm getting a bad request as a status code.
I would like to intensify that for small and medium messages(size until 1K), it works well.
What do I need to do to get the payload for the large message?
Am I doing something wrong?
const coap = require("coap");
const setup = {
host: 'CLOUD_IP',
observe: true,
port: 5683,
pathname: '/middlewareToCloud',
method: 'GET'
}
const req = coap.request(setup)
// edit this to adjust max packet
req.setOption('Block2', Buffer.of(0x2))
req.on('response', (res) =>
{
res.on('data', (data) => {
console.log(Buffer.from(data).toString('utf8'));
})
});
req.end()
Related
Here is the code for my server which works fine. I am trying to achieve this with netlify's serverless functions which I have pasted further below.
CODE ON STANDARD SERVER-HEROKU
const ratingController = {};
const Rating = require("../models/ratingModel");
ratingController.getAllRatings = async function (req, res) {
const rating = await Rating.find();
res.status(200).json({
status: "success",
data: rating,
});
};
ratingController.createOneRating = async function (req, res) {
console.log(req.body);
req.body.userIp = req.headers["x-forwarded-for"];
const rating = await Rating.create(req.body);
// const rating = new Rating(req.body);
// await rating.save();
res.status(200).json({
status: "success",
data: {
rating,
},
});
};
PART 1 - GET REQUEST
Here's my code for the getAllRatings and it works fine
SERVERLESS FUNCTION - NETLIFY
const { MongoClient } = require("mongodb");
require("dotenv").config();
exports.handler = async function getData(event, context) {
const client = await MongoClient.connect(process.env.DB, {
useUnifiedTopology: true,
useNewUrlParser: true,
});
const db = client.db();
try {
const slug = event.queryStringParameters.id;
const data = await db.collection("collectionName").find({ slug }).toArray();
client.close();
return {
statusCode: 200,
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
status: "success",
data: data,
}),
};
} catch (error) {
console.log(error);
return {
statusCode: 400,
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
status: "fail",
message: error.message,
}),
};
}
};
My first question for the above is
Just because it works may not mean it's the right way to do it.. I had a few concerns if calling the database each time there's a call is correct and then placing the code the way I have, if it's the way it should be. It's all based on testing and random research. There's no real method being followed so would appreciate some guidance on a more efficient method to do this.
Normally on a regular server the database connection is done just once.. and here I seem to be doing it every time and I am a bit confused if that's ok or not..
PART 2 - POST REQUEST
Here's my code for the POST request createOneRating
SERVERLESS FUNCTION - NETLIFY
const { MongoClient } = require("mongodb");
require("dotenv").config();
exports.handler = async function createRating(event, context) {
const client = await MongoClient.connect(process.env.DB, {
useUnifiedTopology: true,
useNewUrlParser: true,
});
const db = client.db();
try {
console.log(event);
const rating = await db.collection("ratings").insertOne(event.body);
client.close();
return {
statusCode: 200,
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
status: "success",
data: rating,
}),
};
} catch (error) {
console.log(error);
return {
statusCode: 400,
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
status: "fail",
message: error.message,
}),
};
}
};
This one does not work as it says
{
"status": "fail",
"message": "Cannot create property '_id' on string ''"
}
And I guess that's because event.body is not where the data is.. but I am not sure how to get the POST data in a serverless deployment.
So my second question is
How do I retrieve the data sent by a POST request. As there's no request parameter I am a bit confused.
Also I'd like to add the IP of the user so other than the POST data I'd also need some help on how to do this
req.body.userIp = req.headers["x-forwarded-for"];
Based on my own research, I have answers to the questions and am placing them here for my own reference and for those who might face a similar situation in the future.
Question 1 : Is it ok to make a database connection on every call that's made to a serverless function
It seems it's ok to do this and for those, like me, who thought that maybe it was not the right way to do it, it's definitely not the wrong way. Maybe there's an efficient way to do this and I'd be open to learn more about this if possible. But for now, it's good to know that it's not wrong to connect to the database each time you make a call.
Question 2: How to make a POST request on a serverless as there's no request parameter
I was not aware that the event parameter is in fact a replacement for the request parameter and that the headers and body are properties of the event object and can be accessed in the same way ie event.body and event.headers. Here's a link that could save you some time to confirm this.
(https://docs.netlify.com/functions/build-with-javascript/#synchronous-function-format)
And if you, like me, don't know if a serverless function can be defined as GET or POST or run into an issue where the POST request gets converted into a GET when making a function call here's a link that would help.
How to define Netlify function endpoint as POST?
I have built the server and the client and I am having trouble processing a response on the client that the server sends over. I've used res.send(data) and res.json(data), but the response that the client processes doesn't contain any of the information the server has sent back.
Here is my server code. I am deleting an item and just want to send some random data back to see if I can receive it on the client.
app.delete('/deleteReward/:id', (req, res) => {
console.log('\n\n\n\nInside delete\n\n\n\n')
console.log(req.params.id)
var rewardId = req.params.id
const sessionCookie = req.cookies.session || "";
var idToken = ""
var type = ""
if (sessionCookie) {
idToken = sessionCookie['idToken']
type = sessionCookie['type']
}
console.log("Printing session cookie")
console.log(sessionCookie)
admin
.auth()
.verifySessionCookie(idToken, true /** checkRevoked */)
.then((decodedClaims) => {
console.log(decodedClaims.user_id)
deleteReward(decodedClaims.user_id, rewardId)
// res.send("new data being sent")
})
.catch((error) => {
console.log(error)
});
res.json({'key': 'value'})
})
Here is my code on the client-side
for(var i = 0; i < rewardDeleteButtons.length; i++) {
var deleteButton = rewardDeleteButtons[i]
deleteButton.addEventListener('click', function(e) {
console.log(document.cookie)
console.log(this.value)
var response = fetch("/deleteReward/" + this.value, {
method: "DELETE",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
"CSRF-Token": Cookies.get("XSRF-TOKEN"),
},
});
response.then((data) => {
console.log(data)
})
})
}
The data I'm getting back looks like this when I console.log it
Response {type: "basic", url: "http://localhost:5000/deleteReward/1", redirected: false, status: 200, ok: true, …}body: (...)bodyUsed: falseheaders: Headers {}ok: trueredirected: falsestatus: 200statusText: "OK"type: "basic"url: "http://localhost:5000/deleteReward/1"[[Prototype]]: Response
I should see something like "{'key': 'value'}" or something like that in the returned JSON but it's not there. Not sure what I'm doing. Couldn't find any examples online of handling a response and extracting data within on the client from Node.
The first then() block of fetch doesn't directly resolve the response body. It resolves the response object. You should return the JSON response from the first resolver and use second then() to use it.
More Info: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
The code should be like
response
.then(res => res.json())
.then(data => console.log(data));
I am trying to integrate with a payment gateway in Node and I have successfully been able to post data, but I need to grab the HTTP response status code and store it in a global variable in order to use it for validation.
_doRequest(postData) {
const hostName = XXXXXXXXXXXXXXX;
const path = '/api/transact.php';
postData.security_key = this.security_key;
postData = querystring.stringify(postData);
const options = {
hostname: hostName,
path: path,
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(postData)
}
};
// Make request to Direct Post API
const req = https.request(options, (response) => {
console.log(`STATUS: ${response.statusCode}`);
console.log(`HEADERS: ${JSON.stringify(response.headers)}`);
response.on('data', (chunk) => {
console.log(`BODY: ${chunk}`);
});
response.on('end', () => {
console.log('No more data in response.');
});
});
req.on('error', (e) => {
console.error(`Problem with request: ${e.message}`);
});
response.statusCode is what I'm looking to hoist somehow and store in a global variable like const status = statusCode, but I cannot figure out how to accomplish this. I would appreciate any help!
Please try using global.status = statusCode.
You can always access it, while node is running, however this is considered an antipattern.
I wold like to know how to make a GET request in node.js sending a body.
const options = {
hostname: 'localhost',
port: 3000,
path: '/abc',
method: 'GET'
}
http.get(options, (res) => {
res.on('data', (chunk) => {
console.log(String(chunk))
})
})
As it says in the documentation:
Since most requests are GET requests without bodies, Node.js provides this convenience method. The only difference between this method and http.request() is that it sets the method to GET and calls req.end() automatically.
So the answer is to use http.request directly. http.request has an example using POST, but it's the same for GET (start the request with http.request, use write to send the body data, use end when done sending data), other than the fact that (as noted above) GET usually doesn't have any body. In fact, RFC 7231 notes that:
A payload within a GET request message has no defined semantics;
sending a payload body on a GET request might cause some existing
implementations to reject the request.
Using the standard http:
`const http = require('http');
https.get('http://localhost:3000/abc', (resp) => {
let data = '';
// A chunk of data has been recieved.
resp.on('data', (chunk) => {
data += chunk;
});
// The whole response has been received. Print out the result.
resp.on('end', () => {
console.log(JSON.parse(data).explanation);
});
}).on("error", (err) => {
console.log("Error: " + err.message);
});`
Hope this helps
Using Body in GET request is not recommended at all cause it is not the suggest behavior by HTTP 1.1 but you can use the following method:
const data = JSON.stringify({
"userId": 1,
"id": 1,
"title": "delectus aut autem",
"completed": false
});
const https = require('https')
const options = {
hostname: 'jsonplaceholder.typicode.com',
port: 443,
path: '/posts',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': data.length
}
}
const req = https.request(options, (res) => {
console.log(`statusCode: ${res.statusCode}`)
res.on('data', (d) => {
process.stdout.write(d)
})
})
req.on('error', (error) => {
console.error(error)
})
req.write(data)
req.end()
Posting data using net.request is not working. It's reaching the URL. But data not posted. My code is below. Please help me on this.
const net = remote.net;
const querystring = require('querystring');
//**
var postData = querystring.stringify({
'username' : 'test',
'password': 'test'
});
const request = net.request({
method: 'POST',
url: 'http://127.0.0.1/post.php',
});
request.on('error', (error) => {});
request.on('response', (response) => {});
request.write(postData);
request.end();
I know it's been a while. But for the next people who will have the same problem.
Don't forget you must be declare the size of your "postData" in the header.
for example :
var postData = JSON.stringify({"q" : sqlQuery });
const request = net.request({
method: 'POST',
protocol: 'http:',
hostname: '127.0.0.1',
port: 3000,
path: '/select',
headers: {
'Content-Type': 'application/json',
'Content-Length': postData.length
}
})
request.on('response', (response) => {
.... // Something
})
request.write(postData)
request.end()
When using net.request you need to call request.end() after you write your data to assure the request data has been sent.
The reason you need to call request.end() is to allow for changes to be made to the headers and body of your request before you actually make it.
request() will connect and wait for request.end() to send the headers and body in one pass.
Also, it is never a good idea to ignore responses if you want to understand what your code is doing.
You really should hook the request.response event to see what, if any, errors occurred, as in:
request.on('response', (response) => {
console.log(`STATUS: ${response.statusCode}`)
console.log(`HEADERS: ${JSON.stringify(response.headers)}`)
})
Updated - per comment
Your code should read (expanded from example code for net in Electron API Docs):
const request = net.request({
method: 'POST',
url: 'http://127.0.0.1/post.php',
})
let body = ''
request.on('response', (response) => {
// check response.statusCode to determine if the request succeeded
console.log(`STATUS: ${response.statusCode}`)
console.log(`HEADERS: ${JSON.stringify(response.headers)}`)
// capture body of response
// - can be called more than once for large result
response.on('data', (chunk) => {
console.log(`BODY: ${chunk}`)
body += chunk.toString()
})
// when response is complete, print body
response.on('end', () => {
console.log(`BODY: ${body}`)
})
})
request.write(postData)
request.end()