может использовать API GET, но не API POST
Im работает над существующим проектом Windows Service в VS 2013.
Я добавил класс API-интерфейса API, который я не могу запомнить, если его класс (v2.1) или (v1) контроллера... В любом случае я назвал его SyncPersonnelViaAwsApiController
Я пытаюсь называть его из лямбда AWS... так что если я позвоню GET
public string Get(int id)
{
return "value";
}
с константой req = https.request(' https://actualUrlAddress/api/SyncPersonnelViaAwsApi/Get/4 ', (res) => {
Я получаю returned body: undefined"value"
которое является правильным. Однако, если я попробую позвонить
const req = https.request('https://actualUrlAddress/api/SyncPersonnelViaAwsApi/SapCall', (res) => {
Я returned body: undefined{"Message":"The requested resource does not support http method 'GET'."}
//// POST api/<controller>
public string SapCall([FromBody]string xmlFile)
{
string responseMsg = "Failed Import User";
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 \"}";
}
Кто-нибудь знает, почему он работает для GET, а не POST?
Поскольку мы можем поразить уверенность, что это не лямбда, но я включил его просто в
const AWS = require('aws-sdk');
const https = require('https');
var s3 = new AWS.S3();
var un;
var pw;
var seralizedXmlFile;
let index = function index(event, context, callback) {
// For the purpose of testing I have populated the bucket and key params with objects that already exist in the S3 bucket
var params = {
Bucket: "testbucketthur7thdec",
Key: "personnelData_50312474_636403151354943757.xml"
};
// Get Object from S3 bucket and add to 'seralizedXmlFile'
s3.getObject(params, function (data, err) {
console.log("get object from S3 bucket");
if (err) {
// an error occurred
}
else
{
console.log("data " + data);
// populate seralizedXmlFile with data from S3 bucket
let seralizedXmlFile = err.Body.toString('utf-8'); // Use the encoding necessary
console.log("objectData " + seralizedXmlFile);
}
});
// set params
var ssm = new AWS.SSM({ region: 'Usa2' });
console.log('Instatiated SSM');
var paramsx = {
'Names': ['/Sap/ServiceUsername', '/Sap/ServicePassword'],
'WithDecryption': true
};
// password and username
ssm.getParameters(paramsx, function (err, data) {
console.log('Getting parameter');
if (err) console.log(err, err.stack); // an error occurred
else {
console.log('data: ' + JSON.stringify(data)); // successful response
console.log('password: ' + data.Parameters[0].Value);
console.log('username: ' + data.Parameters[1].Value);
pw = data.Parameters[0].Value;
un = data.Parameters[1].Value;
}
// request to external api application & remove dependency on ssl
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
//POST DOES NOT WORK
const req = https.request('https://actualUrlAddress/api/SyncPersonnelViaAwsApi/SapEaiCall', (res) => {
//GET WORKS
// const req = https.request('https://actualUrlAddress/api/SyncPersonnelViaAwsApi/Get/4', (res) => {
res.headers + 'Authorization: Basic ' + un + ':' + pw;
let body = seralizedXmlFile;
console.log('seralizedXmlFile: ' + seralizedXmlFile);
console.log('Status:', res.statusCode);
console.log('Headers:', JSON.stringify(res.headers));
res.setEncoding('utf8');
res.on('data', (chunk) => body += chunk);
res.on('end', () => {
console.log('Successfully processed HTTPS response');
callback(null, body);
console.log('returned body:', body);
});
});
req.end();
});
};
exports.handler = index;
ОБНОВЛЕНИЕ Спасибо @Thangadurai сообщение с AWS Lambda - NodeJS POST запрос и асинхронный файл записи/чтения
Я смог включить post_options... см. Обновленную лямбду
// An object of options to indicate where to post to
var post_options = {
host: 'https://actualUrlAddress',
port: '80',
path: '/api/SyncPersonnelViaAwsApi/SapEaiCall',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': post_data.length
}
};
const req = https.request(post_options, (res) => {
res.headers + 'Authorization: Basic ' + un + ':' + pw;
let body = seralizedXmlFile;
console.log('seralizedXmlFile: ' + seralizedXmlFile);
console.log('Status:', res.statusCode);
console.log('Headers:', JSON.stringify(res.headers));
res.setEncoding('utf8');
res.on('data', (chunk) => body += chunk);
res.on('end', () => {
console.log('Successfully processed HTTPS response');
callback(null, body);
console.log('returned body:', body);
});
});
req.end();
Теперь он помечен как ошибка:
Error: getaddrinfo ENOTFOUND http://actualUrlAddress http://actualUrlAddress.private:80
Раньше у меня была эта ошибка getaggrinfo ENOTFOUND, это означает, что она не может найти адрес.... но arnt имя хоста и путь api правильно?
Я пытаюсь достичь
const req = https.request('https://actualUrlAddress/api/SyncPersonnelViaAwsApi/SapCall
и да, порт 80
любая помощь будет оценена Та М
Ответы
Ответ 1
Переход к части обновления (все остальное не имеет значения, как я понимаю). Параметры должны выглядеть так:
var post_options = {
host: 'actualUrlAddress',
protocol: 'https:'
port: '443',
path: '/api/SyncPersonnelViaAwsApi/SapEaiCall',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': post_data.length
}
};
Поскольку, как указано в документации, хост и протокол находятся в двух отдельных свойствах, а для SSL-порта маловероятно 80, обычно это 443.
Ответ 2
Учитывая, что веб-API используется, предполагается, что маршрут по умолчанию также настроен.
Я бы предложил включить маршрутизацию атрибутов
Маршрутизация ссылочной атрибутики в ASP.NET Web API 2
public static class WebApiConfig {
public static void Register(HttpConfiguration config) {
// Attribute routing.
config.MapHttpAttributeRoutes();
// Convention-based routing.
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
и обновление контроллера с соответствующими атрибутами и синтаксисом
[RoutePrefix("api/SyncPersonnelViaAwsApi")]
public class SyncPersonnelViaAwsApiController : ApiController {
//GET api/SyncPersonnelViaAwsApi/4
[HttpGet]
[Route("{id:int}")]
public IHttpActionResult Get(int id) {
return Ok("value");
}
//POST api/SyncPersonnelViaAwsApi
[HttpPost]
[Route("")]
public IHttpActionResult SapCall([FromBody]string xmlFile) {
string responseMsg = "Failed Import User";
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";
}
}
var data = new {
response = responseMsg,
isNewActiveDirectoryUser = false
};
Ok(data);
}
}
Обратите внимание на ожидаемые пути в комментариях выше действий.
Атрибуты [Http{Verb}]
определяют структуру маршрутизации, какие запросы могут быть сопоставлены с действием.
теперь от клиента пути для вызова будут
GET api/SyncPersonnelViaAwsApi/4
POST api/SyncPersonnelViaAwsApi
Как уже упоминалось в комментариях, порт 80 не используется для HTTP-вызовов. Даже связанный пример в обновленном вопросе использует порт 443
для вызовов HTTPS. Заголовок в параметрах показывает JSON, но body
указывает, что отправляется XML.
var post_options = {
host: 'actualUrlAddress',
protocol: 'https',
port: '443',
path: '/api/SyncPersonnelViaAwsApi',
method: 'POST',
headers: {
'Content-Type': 'application/xml',
'Content-Length': post_data.length
}
};
Чтобы клиент мог успешно взаимодействовать с веб-API, клиенту необходимо убедиться, что он делает действительный запрос.