I want to post a request to a service using the npm request package. The service accepts a request body of comma-separated numbers such as 1,2,3, but when I post the request, the body is "1,2,3" instead, which the service does not recognise. I use the following code:
import request from "request";
export function getIt(numbers) {
return new Promise((resolve, reject) => {
const uri = 'http://foo.bar/getIt';
const numbersBody = numbers.join(',')
console.log('post body: ', numbersBody) // prints 1,2,3
request
.post(
uri,
{ json: true, rejectUnauthorized: false, body: numbersBody },
(err, httpResponse, body) => {
let error = err && err.message ? err.message : err;
if (body && body._error_code) {
error = body.message;
}
if (error) {
reject(error);
} else {
resolve(body);
}
}
)
});
When I inspect the network traffic with Wireshark, I can see that the body becomes "1,2,3". It seems to be because the request package writes it as a json object. I have tried to remove the json: true part of the option, and also tried changing it to false, but that throws an exception. So I don't know how to make the string be the raw body, without the quotation marks. Is there any way to make that happen?
Related
I am creating the client using Redis and node js, I want to add a message to stream with the below format. I am facing an issue when trying the parse the message with the request body value.
async function userRegister (request) {
var userID = request.body.userID
var username = request.body.userName
redisClient.xadd(
'user:create',
'*',
'module',
`userRegister`,
'request_id',
'2312432434',
'message',
`{"module":"*","user_id":"1","username":"fffff"}`, // this works bcoz its string.
`{"module":"*","userID":"1","username":"here i need pass the above request body value"}`,
function (err, resp) {
if (err) {
console.log(err)
} else {
console.log(resp)
}
}
)
}
I'm using axios to get the http status for URLs:
async function getUrlHttpStatus (url) {
try {
const res = await axios({ method: 'get', url })
return {
status: res.status,
statusText: res.statusText
}
} catch (err) {
return {
status: err.response.status,
statusText: err.response.statusText
}
}
}
This obviously brings back all the content from that URL as well, and if there is a lot, it can be very slow.
Is there a way to make a HTTP request, to get the HTTP status code, without downloading all the content from the URL, so it's quick..?
You can just use the HEAD method, which per definition returns just the Head (i.e. Status code) and no body.
The way you access error is : err.response.data.your_attribute_from_the_server
If the message from the server is in the the error object is in the message attribute
Eg : err.response.data.message
async function getUrlHttpStatus (url) {
try {
const res = await axios({ method: 'get', url })
return {
status: res.status,
statusText: res.statusText
}
} catch (err) {
return {
status: err.response.status,
statusText: err.response.data.message//here replace the message attibute with whatever attribute you've sent from the server
}
}
}
As you may imagine, I'm familiar with Express, but this is the first time I'm using Fastify.
I'd like to access the unmodified body of a Fastify request, for signature verification of a webhook - ie, I would like to see the request as it came in, unmodified by any middleware. In Express this is often done by accessing request.rawBody.
How do I access the raw body of a Fastify request?
You can also check this community plugin: https://github.com/Eomm/fastify-raw-body
If you are using Typescript & fastify/autoload, place this to plugins/rawbody.ts:
import fp from "fastify-plugin";
import rawbody, { RawBodyPluginOptions } from "fastify-raw-body";
export default fp<RawBodyPluginOptions>(async (fastify) => {
fastify.register(rawbody, {
field: "rawBody", // change the default request.rawBody property name
global: false, // add the rawBody to every request. **Default true**
encoding: "utf8", // set it to false to set rawBody as a Buffer **Default utf8**
runFirst: true, // get the body before any preParsing hook change/uncompress it. **Default false**
routes: [], // array of routes, **`global`** will be ignored, wildcard routes not supported
});
});
Since global:false We need to configure it in the specific handler:
fastify.post<{ Body: any }>(
"/api/stripe_webhook",
{
config: {
// add the rawBody to this route. if false, rawBody will be disabled when global is true
rawBody: true,
},
},
async function (request, reply) {
...
Then you can access raw body in the handler using request.rawBody
Note: Fastify requests can only have req.body - they can't have, for example, req.body and req.rawBody like other web servers (for example, Express). This is because addContentTypeParser() only returns a modified body, it can't add anything else to the request.
Instead, in a content type parser we only add to one route, we make:
req.body.parsed (the object, same content that would normally be in req.body)
req.body.raw (the string)
See GitHub and the addContentTypeParser() docs for more.
server.addContentTypeParser(
"application/json",
{ parseAs: "string" },
function (req, body, done) {
try {
var newBody = {
raw: body,
parsed: JSON.parse(body),
};
done(null, newBody);
} catch (error) {
error.statusCode = 400;
done(error, undefined);
}
}
);
There's an issue on GitHub for rawBody support
And there's a module too: "raw-body". To use this module in Fastify:
const rawBody = require('raw-body')
fastify.addContentTypeParser('*', (req, done) => {
rawBody(req, {
length: req.headers['content-length'],
limit: '1mb',
encoding: 'utf8', // Remove if you want a buffer
}, (err, body) => {
if (err) return done(err)
done(null, parse(body))
})
})
I hope that I helped you, I'm new on fastify too
I am trying to use ES6's fetch api to post some login data to a java spark server. The GET requests work perfectly, but when I try to POST something, the Promise on the client side stays 'pending'. I checked, and the server receives the request body, and parses it to an object. Using postman, it also returns true or false, so I think something is wrong with the CORS setup. I'm new to that, so i jut let * through, thinking it should work. I am using VueJS, but i don't think that really matters here, thought I'd add this info, maybe it helps. I will post the code below.
JS:
methods: {
login: function () {
data = '"perfectly valid json string"'
this.postData('http://te.st/login', data)
},
postData: function(url, data){
return fetch(url, {
body: data,
method: 'POST',
})
.then(response => response.json())
.then(function (result){
app.response = result
})
}
}
Java:
private static void enableCORS(final String origin, final String methods, final String headers) {
options("/*", (request, response) -> {
String accessControlRequestHeaders = request.headers("Access-Control-Request-Headers");
if (accessControlRequestHeaders != null) {
response.header("Access-Control-Allow-Headers", accessControlRequestHeaders);
}
String accessControlRequestMethod = request.headers("Access-Control-Request-Method");
if (accessControlRequestMethod != null) {
response.header("Access-Control-Allow-Methods", accessControlRequestMethod);
}
return "OK";
});
before((request, response) -> {
response.header("Access-Control-Allow-Origin", origin);
response.header("Access-Control-Request-Method", methods);
response.header("Access-Control-Allow-Headers", headers);
response.type("application/json");
});
}
(called in the code as enableCORS("*","GET,POST","Origin, Content-Type, Access-Control-Allow-Origin"); )
And the endpoint:
post("/login", (req, res) -> {
boolean ret = dao.checkLogin(gson.fromJson(req.body(), User.class));
return gson.toJson(ret);
});
I am attempting to use the request.js library for Node to send a post request with plain text as the body, but I'm finding that the server I'm sending to is receiving an empty body, or perhaps a body consisting of an empty object (logging the body yields {}).
If I send it using Postman, it works properly, so it seems clear that the problem is with my usage of request.js.
The code of the relevant function (with the url changed) is as follows:
function (queryText) {
const options = {
url: "https://myurl.com/",
body: queryText
};
return new Promise ((resolve, reject) => {
request.post(options, (err, response) => {
if (err) reject(err);
else resolve(response);
});
});
}
Anybody know what I'm doing wrong here?
Try adding content-type header like so:
const options = {
url: "https://myurl.com/",
body: queryText,
headers: {
'content-type': 'text/plain'
}
};