I am making a request to an API in which they sign their response body with a private key and send me the signature in a header. I am supposed to use their public key to validate the signature with the original response body but at the moment axios parses the response data there is something that is changing in it which makes the signature invalid. Is there some way to get the raw response data with axios?
I am doing a post request and want to get the string of the JSON object that axios automatically parses for me.
You can set a "identity" transformResponse.
let res = axios.get("url",
{ transformResponse: (r) => r }); //null transform (we do not want to parse as JSON);
//res.data should now contain a plain unparsed string
Not sure if setting transformResponse to null does the same thing as the identity transform.
Related
I am trying to validate that an http POST request to an AWS Lamdbda function URL from a Twilio HTTP Request widget inside a Twilio Studio flow truly originated from Twilio. I am using the Node.js Twilio client library, which provides the validateRequest method to accomplish what I am after. The content-type header in the Twilio Studio flows HTTP Request widget is set to application/json
The problem is that I am passing in the "x-twilio-signature" header, the url, twilio auth token, and POST params to the validateRequest method and it always returns false. Below is the code snippet used to try and accomplish this.
const authToken = process.env.twilio_auth_token
const sid = process.env.twilio_account_sid
const client = require('twilio')
exports.handler = (event) =>
{
let twilioSignature = event.headers['x-twilio-signature']
let requestBody = event.body
let requestUrl = 'https://my-function-url.io/'
let requestIsValid = client.validateRequest(authToken, twilioSignature, requestUrl, requestBody)
if(requestIsValid){
console.log('valid request')
} else {
console.log('invalid request')
}
}
Seems like someone else had a similar issue in the past. I copied parts of the answer here:
The issue here is that query string parameters are treated differently to POST body parameters when generating the signature.
Notably part 3 of the steps used to generate the request signature says:
If your request is a POST, Twilio takes all the POST fields, sorts them by alphabetically by their name, and concatenates the parameter name and value to the end of the URL (with no delimiter).
I have an API where I need to call another API inside the controller function. Which I do using Axios, but when I try to attach Axios's response on my original API's response, it throws this error:
TypeError: Converting circular structure to JSON.
Here's a sample code snippet
const userController = async (req,res)=>{
const ax = await axios.put(someURL, reqBody)
res.status(200).json(ax)
}
I know it's nonsensical to do something like this and I know why this error is caused but could somebody explain to me How it's happening in this case?
TypeError: Converting circular structure to JSON is when some property in the object is repeated in another inner object.
Axios response has these properties:
// `data` is the response that was provided by the server
data: {..your real json response..},
// `status` is the HTTP status code from the server response
status: 200,
// `statusText` is the HTTP status message from the server response
statusText: 'OK',
// `headers` the HTTP headers that the server responded with
headers: {},
// `config` is the config that was provided to `axios` for the request
config: {},
// `request` is the request that generated this response
request: {}
If you send the entire axios response object to be converted to json, some property in your real json response could repeat the name of private axios properties like: status, data config, etc
Fix
Try with ax.data instead use the entire axios response ax
I'm sending a post request to a cloud function which contains the following body:
{message: "this is the message"}
If I try to print the entire body of the request, it shows it, but if I try to get the message field, I get undefined in the console.
Here's my function:
exports.myCloudFunction = functions.https.onRequest((req: any, res: any) => {
console.log(req.body)\\prints the body of the request fine
console.log(req.body.message)\\prints "undefined"
cors(req, res, () => {
const pl = req.body.message;
console.log(pl);\\prints "undefined"
});
return res.send("all done")
});
You don't need a body parser for Cloud Functions as described in the other answer here. Cloud Functions will automatically parse JSON and put the parsed JSON object in the body attribute. If you want this to happen automatically, you should set the content type of the request to "application/json" as described in the linked documentation. Then you can use req.body as you'd expect.
I personally haven't worked with firebase before, but from your code and the fact that req.body prints the body, it seems that you probably need to parse the request-body as json in order to be able to access the message property:
const body = JSON.parse(req.body);
console.log(body.message);
It could also be the case that you need to setup a bodyparser for json content. In a normal express-app you can do this using (note that you don't need the manual parsing from above anymore using bodyparser):
const bodyParser = require('body-parser');
app.use(bodyParser.json();
EDIT:
see Doug's answer for the correct way to do this, i.e. to fix your request and set the content-type to application/json in order for Cloud Functions to automatically parse and populate req.body with the request body.
You need to just convert the request body into a JSON object in cloud function.
const body = JSON.parse(req.body);
// message
console.log(body.message)
X server hitting the post req to Y server. x server body data {"number":0.0}, but when receiving it in y server (nodejs) its changing to {"number":0} in the req.body tag. every req through bodyParser.json()
why it is changing? it should get what the x server posted right? help me out.
tried with bodyParser.raw(), bodyParser.text() dosnt provide the body tag.
If you need to calculate a HMAC over the raw request body, you shouldn't be parsing it, or at least first take the raw request body, calculate the HMAC, then parse it.
To do the latter, you can use express.json's verify option:
app.use(express.json({
verify(req, res, buf, encoding) {
req._hmac = hmac(buf);
}
}));
This will use a function called hmac to calculate a HMAC over the request body (passed as a Buffer in the buf argument). It will then continue to parse the request body as JSON.
Caveats:
it will calculate the HMAC for every request that passed a request body;
it won't work if calculating the HMAC is asynchronous.
Both issues are relatively easy to solve, though.
Since I faced the same problem, I resolved using bodyparser in this way:
app.use(bodyParser.text({
type: 'application/json'
}))
In this way the request with application/json header are considered as text, and in req.body you will have the string representation of the json.
My Servicestack service is beeing posted Json (by jquery).
sendData = function(dataToSend) {
var request;
return request = $.ajax({
url: "/api/test",
type: "post",
data: JSON.stringify(dataToSend),
dataType: "json",
accept: "application/json",
contentType: "application/json"
});
The Json data is correctly deserialized if it corresponds to the root properties of my DTO (eg: userId:'foo' -> UserId=foo in the DTO).
I want to access the raw json posted data before it gets deserialized for adding custom deserialization.
Till now I had no problems accessing the querystrings with custom filters (RequestFilterAttribute) or if data vas posted like form.
Now I see the data that gets posted with Chrome Developer Tools is in the headers with "Request Payload" so it is nor in FormData and nor QueryString I can access when debugging my IHttpRequest.
How can I get my raw json data in the filter?
If you want to replace the default deserialization behavior with custom behavior for a specific request DTO, you can do this in your AppHost setup code:
JsConfig<MyRequestDtoClass>.DeSerializeFn = DeserializeMyRequestDto;
Where DeserializeMyRequestDto is a function or lambda taking a single string param - the raw request body - and returning the deserialized instance of your DTO:
MyRequestDtoClass DeserializeMyRequestDto(string rawBody) { ... }
RequestFilterAttribute subclasses purpotedly have access to the raw request body using request.GetRawBody(), where request is the IHttpRequest object passed into the filter's Execute method. But in my experience, GetRawBody returns an empty string, because the request input stream seems to be consumed by that time due to the deserialization. I worked around this once by creating an HTTP module (registered in AppHost via DynamicModuleUtility.RegisterModule) that would "peek" at the request input stream in a BeginRequest event handler. (The "peek" function would read the request input stream and then reset the Position of the stream to where it initially was.)