问题
Thanks to help from EVK on my previous Q (can use API GET but not API POST) I was able to resolve the problem of not being able to make an API POST request from an aws lambda in node, when I could hit the GET. The problem was not populating post_options.
Anyway, now I am able to successfully call the post but I cant get the body populated.
related documentation https://nodejs.org/api/http.html#http_http_request_options_callback
If you see my API POST call below.
//// POST api/<controller>
public string SapEaiCall([FromBody]string xmlFile)
{
string responseMsg = "Failed Import Active Directory User";
if (string.IsNullOrEmpty(xmlFile))
{
responseMsg = "XML file is NULL";
}
if (responseMsg != "XML file is NULL")
{
xmlFile = RemoveFirstAndLastQuotes(xmlFile);
if (!IsNewestVersionOfXMLFile(xmlFile))
{
responseMsg = "Not latest version of file, update not performed";
}
else
{
Business.PersonnelReplicate personnelReplicate = BusinessLogic.SynchronisePersonnel.BuildFromDataContractXml<Business.PersonnelReplicate>(xmlFile);
bool result = Service.Personnel.SynchroniseCache(personnelReplicate);
if (result)
{
responseMsg = "Success Import Sap Cache User";
}
}
}
return "{\"response\" : \" " + responseMsg + " \" , \"isNewActiveDirectoryUser\" : \" false \"}";
}
Every time I call it from the aws lambda, it returns responseMsg = "XML file is NULL";
Please see my example below:
var querystring = require('querystring');
var https = require('https');
var fs = require('fs');
exports.handler = function(event, context) {
const post_data = querystring.stringify({'msg': 'Hello World!'});
// An object of options to indicate where to post to
var post_options = {
host: 'URL',
protocol: 'https:',
port: '443',
path: '/api/SyncPersonnelViaAwsApi/SapEaiCall',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': post_data.length
}
};
//ignores SSL
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
var post_request = https.request(post_options, function(res) {
var body = "";
res.on('data', function(chunk) {
body += chunk;
});
res.on('end', function() {
context.done(body);
});
res.on('error', function(e) {
context.fail('error:' + e.message);
});
});
// post the data
post_request.write(post_data);
post_request.end();
console.log("posted data " +post_data); //returns posted data msg=Hello%20World!
};
So I have populated post data, and also tried populating the body. Still returns XML file is NULL
Does anyone please have any idea why?
Thanks
回答1:
You are sending the following text in body:
msg=Hello%20World!
And you state that request content type is:
'Content-Type': 'application/json'
Does your body represents valid json? It doesn't. So that's first problem - content type stated in your request and actual data your send do not match each other.
Then let's look at:
public string SapEaiCall([FromBody]string xmlFile)
It basically says: look at the body of request and use binder appropriate for request content type to bind value of xmlFile
parameter. Since request content type is "application/json" - binder expects body to contain one single json string, that is, body in such case should be (including quotes):
"Hello World!"
So if you pass that (for example via const post_data = JSON.stringify('Hello World!');
- it should work.
But then what if you want to pass more parameters in your body, not just xmlFile
? Then you need to define a model, and I'd say even if you have just one parameter - it's better to do that. For example:
public class SapEaiCallParameters {
public string XmlFile { get; set; }
}
// FromBody can be omitted in this case
public IHttpActionResult Post(SapEaiCallParameters parameters) {
}
And then you call it as you would expect, passing json:
const model = {xmlFile: 'Hello World!'};
const post_data = JSON.stringify(model);
Side note: don't do this:
return "{\"response\" : \" " + responseMsg + " \" , \"isNewActiveDirectoryUser\" : \" false \"}";
Instead, create another model, like this:
public class SapEaiCallResponse {
public string Response { get; set; }
public bool IsNewActiveDirectoryUser { get; set; }
}
And return it:
public IHttpActionResult Post(SapEaiCallParameters parameters) {
...
return Json(new SapEaiCallResponse {
Response = responseMsg,
IsNewActiveDirectoryUser = false,
});
}
来源:https://stackoverflow.com/questions/49788577/aws-lambda-call-not-populating-body-on-post