I'm new to a lot of this technology, but I think I've diagnosed my issue and need some help. I've seen numerous posts on SO regarding this issue, but none have worked, though they have helped me diagnose issue.
I believe the issue is when I send the Header Content-Type w/ my pre-flight w/ Axios, it fails. This is possibly due to lower/case upper case? The error has lower case, but I tried both on the server without luck.
Basically, if I don't specify any header and Axios uses json as content-type, it works, but as soon as I specify Content-Type my pre-flight fails (even though I think post would work..).
Here is the elasticsearch.yml
cluster.name: "docker-cluster"
network.host: 0.0.0.0
http.cors.enabled : true
http.cors.allow-origin: "*"
http.cors.allow-methods: OPTIONS,HEAD,GET,POST,PUT,DELETE
http.cors.allow-headers: X-Requested-With,X-Auth-Token,Content-Type,Content-Length
#http.cors.allow-credentials: true
Here is my JS that I'm testing BTW w/ an Office Add-In solution in Visual Studio 2017 which I think is using IE as a browser.
Main Func:
var URL = "https://elasticsearch:9200/users/_search"
const data = {
"query": {
"match": {
"name": "freesoftwareservers"
}
}
};
Do_Axios('get', URL, data, null, false)
Do_Axios('post', URL, data, null, false)
Do_Axios:
async function Do_Axios(method, URL, data, headers, withCredentials) {
return axios({
method: method,
url: URL,
withCredentials: withCredentials,
//contentType: 'application/json', // does nothing
//data: JSON.stringify(data), //Causes urlformencoded which is wrong
data: data, //caues type to be json and I get error
headers: {
//"Content-Type": "application/json"
},
})
.then(function (response) {
console.log("Axios " + method + " response:");
console.log(response)
return response;
})
.catch(function (error) {
console.log(error);
});
}
Note: I can get/post if I comment out //data but then the post doesn't run my query. If I uncomment data then Axios uses urlformencoded but that doesn't work.
For now, I've been able to search API via urlformencoded queries, but I'd like to fix my ability to POST correctly to resolve future errors. I'm unsure if issue should be pointed to Axios or Elasticsearch if I open a request.
Well, I finally figured it out. I wonder how many of the other posts I read have similar issues... anyway, the issue was w/ my NGinX proxy server. No better way to learn about CORS then to setup an API and make CORS requests via IE! Without the below, I was still able to post w/ POSTMAN to the same URL which hit my nginx server, but the call from Axios/IE/JS Evironment failed.
I found these snippets and this was the magic that needed added to my "regular" configuration:
proxy_pass_header Access-Control-Allow-Origin;
proxy_pass_header Access-Control-Allow-Methods;
proxy_hide_header Access-Control-Allow-Headers;
add_header Access-Control-Allow-Headers 'X-Requested-With, Content-Type';
add_header Access-Control-Allow-Credentials true;
https://gist.github.com/sahilsk/b16cb51387847e6c3329
Here is my code as it stands, cleaned up but generic atm:
Note: I pass axios because I can't figure out how to get my Webpack to transform/polyfill my funcs in seperate js files. But I can declare axios in the main func and pass it and then I can move my funcs into separate files as needed for organization. There is likely a better way to do without passing axios and configuring webpack
Main Func:
var username = "freesoftwareservers"
var ipv4 = "192.168.1.255"
var showhelp = "false"
await Do_AddUserToES(axios,username, ipv4, showhelp)
Get_UserFromES(axios,username)
var index = "users"
var query = {
query: {
match: {
"username": username
}
}
};
Get_PostQueryToES(axios,query, index)
Funcs:
function Do_Axios(axios, method, URL, data, headers, withCredentials) {
return axios({
method: method,
url: URL,
withCredentials: withCredentials,
data: data,
headers: headers,
})
.then(function (response) {
console.log("Axios " + method + " response:");
console.log(response)
return response;
})
.catch(function (error) {
console.log(error);
});
}
function Get_ESURL(Bool_Search, Bool_Doc, Bool_Update, Opt_Index, Opt_IndexKey) {
var ESUrl = "https://elasticsearch:9200"
var ESSearch = "/_search"
var ESDoc = "/_doc"
var ESUpdate = "/_update"
var ReturnURL = ESUrl
if (Opt_Index != undefined) { ReturnURL = ReturnURL + "/" + Opt_Index }
if (Bool_Search == true) { ReturnURL = ReturnURL + ESSearch }
if (Bool_Doc == true) { ReturnURL = ReturnURL + ESDoc }
if (Bool_Update == true) { ReturnURL = ReturnURL + ESUpdate }
if (Opt_IndexKey != undefined) { ReturnURL = ReturnURL + "/" + Opt_IndexKey }
console.log("ReturnURL:" + ReturnURL)
return ReturnURL;
}
function Do_AddUserToES(axios, username, ipv4, showhelp) {
var adduser = {
"username": username,
"ipv4": ipv4,
"showhelp": showhelp
};
var URL = Get_ESURL(false, true, false, "users", username)
return Do_Axios(axios, 'post', URL, adduser, null, false);
}
function Get_UserFromES(axios, username) {
var URL = Get_ESURL(false, true, false, "users", username)
return Do_Axios(axios, 'get', URL, null, null, false);
}
function Get_PostQueryToES(axios, query, index) {
var URL = Get_ESURL(true, false, false, index)
return Do_Axios(axios, 'post', URL, query, null, false);
}
I am new at AWS. Like 3 days new. I found in one of the Amazon's tutorials the code for a lambda function that would interact with a DynamoDB table. The sample is only providing the test JSON for a GET request, which would result in a list of items in the database, but the code itself supports PUT, POST and DELETE, for a full CRUD with the table.
So, I created a DynamoDB table named "Users" with a partition key CompanyId which is a string, and a sort key Email which is also a string.
I then created a lambda function and added the code from the tutorial:
console.log('Loading function');
const doc = require('dynamodb-doc');
const dynamo = new doc.DynamoDB();
/**
* Demonstrates a simple HTTP endpoint using API Gateway. You have full
* access to the request and response payload, including headers and
* status code.
*
* To scan a DynamoDB table, make a GET request with the TableName as a
* query string parameter. To put, update, or delete an item, make a POST,
* PUT, or DELETE request respectively, passing in the payload to the
* DynamoDB API as a JSON body.
*/
exports.handler = (event, context, callback) => {
console.log('Received event:', JSON.stringify(event, null, 2));
const done = (err, res) => callback(null, {
statusCode: err ? '400' : '200',
body: err ? err.message : JSON.stringify(res),
headers: {
'Content-Type': 'application/json',
},
});
switch (event.httpMethod) {
case 'DELETE':
dynamo.deleteItem(JSON.parse(event.body), done);
break;
case 'GET':
dynamo.scan({ TableName: event.queryStringParameters.TableName }, done);
break;
case 'POST':
console.log(event.body);
dynamo.putItem(JSON.parse(event.body), done);
break;
case 'PUT':
dynamo.updateItem(JSON.parse(event.body), done);
break;
default:
done(new Error(`Unsupported method "${event.httpMethod}"`));
}
};
After testing the GET code (and getting a 0-length list of items, since my table is empty), I decided to create a test that would add one item to the database. I created a test event called PostTest and with the following test content:
{
"httpMethod": "POST",
"body": "{\"Item\": {\"CompanyId\": {\"S\": \"test-company-id\"},\"FirstName\": {\"S\": \"John\"}, \"LastName\": {\"S\": \"Doe\"}, \"Email\": {\"S\": \"john.doe#gmail.com\"}, \"Password\": {\"S\": \"password\"}}, \"TableName\": \"Users\"}"
}
I want to point out the fact that the CompanyId is set to be a "S", or in other words, set to be of type string.
When I ran the test, I got the following response:
{
"statusCode": "400",
"body": "One or more parameter values were invalid: Type mismatch for key CompanyId expected: S actual: M",
"headers": {
"Content-Type": "application/json"
}
}
and the content of the log was:
START RequestId: 294a7414-cde5-11e8-a7bd-bd58483e1612 Version: $LATEST
2018-10-12T06:07:56.232Z 294a7414-cde5-11e8-a7bd-bd58483e1612 Received event: {
"httpMethod": "POST",
"body": "{\"Item\": {\"CompanyId\": {\"S\": \"test-company-id\"},\"FirstName\": {\"S\": \"John\"}, \"LastName\": {\"S\": \"Doe\"}, \"Email\": {\"S\": \"john.doe#gmail.com\"}, \"Password\": {\"S\": \"password\"}}, \"TableName\": \"Users\"}"
}
2018-10-12T06:07:56.232Z 294a7414-cde5-11e8-a7bd-bd58483e1612 {"Item": {"CompanyId": {"S": "test-company-id"},"FirstName": {"S": "John"}, "LastName": {"S": "Doe"}, "Email": {"S": "john.doe#gmail.com"}, "Password": {"S": "password"}}, "TableName": "Users"}
END RequestId: 294a7414-cde5-11e8-a7bd-bd58483e1612
REPORT RequestId: 294a7414-cde5-11e8-a7bd-bd58483e1612 Duration: 173.04 ms Billed Duration: 200 ms Memory Size: 512 MB Max Memory Used: 30 MB
I am baffled by the error in the response:
Type mismatch for key CompanyId expected: S actual: M
If you look in the log, in the body of the request CompanyId is set to "S". Where does "M" come from? What did I do wrong?
Needless to say that no items have been added to my table.
I do not know what is behind dynamodb-doc, but I had similar issue with aws-sdk.
Given const AWS = require('aws-sdk') you may have two connectors. Example:
const DDB = new AWS.DynamoDB();
const DC = new AWS.DynamoDB.DocumentClient();
When using the DDB connection, you have to format the items the way you do, using the types.
When using the DocumentClient (DC) the types are inferred, thus you do not have to explicitly provide the types. Try something like this:
{
"httpMethod": "POST",
"body": "{\"Item\": {\"CompanyId\": \"test-company-id\",\"FirstName\": \"John\", \"LastName\": \"Doe\", \"Email\": \"john.doe#gmail.com\", \"Password\": \"password\"}, \"TableName\": \"Users\"}"
}
Using the DC, the CompanyId is correctly inferred as a Map: {\"S\": \"test-company-id\"}. Garbage in, garbage out. :)
I have created a custom API in Oracle MCS to get the user information and trying to call it from MAF application... As a response i am getting 200 as success code... but when i try to parse the response it shows a HTML page instead of actual responce....
Custom API
https://mobileportalsetrial1304dev-mcsdem0001.mobileenv.us2.oraclecloud.com:443/mobile/custom/rvs_ekkfetchuserinfo/fetchcontent
and userid=101 as parameter
Calling Method to get User information
#Override
public Response getUserInformation(int userId) {
System.out.println("In loginService");
String restURI = "https://mobileportalsetrial1304dev-mcsdem0001.mobileenv.us2.oraclecloud.com:443/mobile/custom/rvs_ekkfetchuserinfo/fetchcontent?userid=" + userId;
String jsonRequest = "";
Response response = new Response();
response = RestUtil.callGet(restURI, jsonRequest);
return response;
}
callGet Method
public static Response callGet(String restURI, String jsonRequest) {
String responseJson = "";
Response response = new Response();
System.out.println("restURI:" + restURI);
RestServiceAdapter restServiceAdapter = Model.createRestServiceAdapter();
restServiceAdapter.clearRequestProperties();
restServiceAdapter.setConnectionName("MiddlewareAPI");
restServiceAdapter.setRequestType(RestServiceAdapter.REQUEST_TYPE_GET);
restServiceAdapter.addRequestProperty("Content-Type", "application/json");
restServiceAdapter.addRequestProperty("Accept", "application/json; charset=UTF-8");
restServiceAdapter.addRequestProperty("Oracle-Mobile-Backend-Id", "da5c7d86-29c0-43e8-b613-53de55a7ae6c");
restServiceAdapter.addRequestProperty("Authorization", "Basic TUNTREVNMDAwMV9NT0JJTEVQT1JUQUxTRVRSSUFMMTMwNERFVl9NT0JJTEVfQU5PTllNT1VTX0FQUElEOmR5Nm91NW5wX3RnbE5r");//+new String(encodedBytes));
restServiceAdapter.setRequestURI(restURI);
restServiceAdapter.setRetryLimit(0);
try {
responseJson = restServiceAdapter.send(jsonRequest);
System.out.println("response" + responseJson);
int responseCode = restServiceAdapter.getResponseStatus();
System.out.println("responseCode" + responseCode);
response.setResponseCode(responseCode);
response.setResponseMessage(responseJson);
response.setHeader(restServiceAdapter.getResponseHeaders());
} catch (Exception e) {
System.out.println("Error in calling API" + e.getStackTrace());
int responseCode = restServiceAdapter.getResponseStatus();
response.setResponseCode(responseCode);
response.setResponseMessage(responseJson);
}
return response;
}
Json Parsing
JSONObject obj = new JSONObject(response);
JSONArray arr = obj.getJSONArray("posts");
for (int i = 0; i < arr.length(); i++)
{
String user_id = arr.getJSONObject(i).getString("UserId");
}
Here what i am getting is JSONObject["items"] is not found... when i print the responce message it gives a HTML Script file
Expected Output
{
"items": [
{
"UserId": "101",
"AgentId": null,
"Category": "Rental",
"Division": "KDR",
"Status": null,
"LocationId": null,
"Operation": "CheckOut",
"Admin": "N",
"createdBy": "mcs-demo_user09#oracleads.com",
"createdOn": "2015-09-25T11:29:10.215564+00:00",
"modifiedBy": "mcs-demo_user09#oracleads.com",
"modifiedOn": "2015-09-25T11:29:10.215564+00:00"
}
]
}
what is the content of the HTML page (it will have some JavaScript I assume but should have a HTML title as well). Anyway, a user Id in MCS is not 101 but an internal ID, so I don't know if you've chosen 101 for simplification in this question.
In MAF, the REST connection is defined through a REST connection with the root URL and the relative URI. In your example, the REST connection is referenced as "MiddlewareAPI". Unless the value of this connection is null, the restURI you provide needs to be reduced to not contain the root URL.
The HTTP 200 you get because the request is answered by the server. However, it appears to be missing either an authorized user (in case of a failed basic authorization for accessing the API) or the authenticated user is not allowed to request the user platform API (by default you can only request information about the user you re authenticated as).
Frank
Hi I got the solution...
I was trying to call customAPI through Oracle-MCS. I replaced RestServiceAdapter with HttpsURLConnection. Then it Works perfectly fine.
I'm trying to send an email via parse.com via mandrill. The examples are very easy to follow, but I'm getting a strange error.
here is my code:
Parse.Cloud.afterSave("ip", function(request) {
var IPLogger_config = require('cloud/mandrillapp_config.js');
var Mandrill = require('mandrill');
Mandrill.initialize(IPLogger_config.mandrillAppKey);
console.log('within afterSave for ip');
console.log(request.object.id);
var ip = Parse.Object.extend("ip");
var query = new Parse.Query(ip);
query.descending("createdAt");
query.limit(2); // limit to at most 2 results
query.find({
success: function(results){
console.log('success query');
console.log('got ' + results.length + ' results');
var newestIp = results[0];
var olderIp = results[1];
if (newestIp.get('ip') == olderIp.get('ip') ) {
// the newest ip and the older one are equal, do nothing.
console.log('No ip change');
} else
{
console.log('ip change!');
console.log(Mandrill.initialize);
console.log(Mandrill.sendEmail);
Mandrill.sendEmail({
message: {
text: "The IP of your server has changed! The new ip is: " + newestIp.get('ip') ,
subject: "The IP of your server has changed!",
from_email: "parse#cloudcode.com",
from_name: "IPLogger",
to: [
{
email: IPLogger_config.your_email,
name: IPLogger_config.your_name
}
]
},
async: true
},{
success: function(httpResponse) {
console.log(httpResponse);
response.success("Email sent!");
},
error: function(httpResponse) {
console.error(httpResponse);
response.error("Uh oh, something went wrong");
}
});
}
},
error: function (error){
console.log('no success for query');
console.error("Got an error " + error.code + " : " + error.message);
}
});
});
my mandrillapp_config.js looks like this:
var IPLogger_config = {};
IPLogger_config.mandrillAppKey = "xxx";
IPLogger_config.your_email = 'myemail#bla.com';
IPLogger_config.your_name = 'myName';
The mandrillAppKey is correctly set. I double checked that. Sending email from mandrill website also works. I just created a new account and did no other settings on the mandrill site.
I'm getting this error: "code":-1,"name":"ValidationError","message":"You must specify a key value". In https://www.parse.com/questions/sometimes-getting-mandrill-you-must-specify-a-key-value-error-when-sending-email is written that the header might be wrong, but as you can see on my log, the "Content-Type":"application/json; charset=utf-8" is set correctly.
I2014-06-09T22:34:20.601Z] {
"uuid":"fbb215c4-1d2a-e2da-23fc-a838bd6bf217",
"status":500,
"headers":{
"Access-Control-Allow-Credentials":"false",
"Access-Control-Allow-Headers":"Content-Type",
"Access-Control-Allow-Methods":"POST, GET, OPTIONS",
"Access-Control-Allow-Origin":"*",
"Connection":"close",
"Content-Encoding":"gzip",
"Content-Type":"application/json; charset=utf-8",
"Date":"Mon, 09 Jun 2014 22:34:20 GMT",
"Server":"nginx/1.6.0",
"Vary":"Accept-Encoding",
"X-Powered-By":"PHP/5.3.10-1ubuntu3.11"
},
"text":"{\"status\":\"error\",\"code\":-1,\"name\":\"ValidationError\",\"message\":\"You must specify a key value\"}",
"data":{"status":"error","code":-1,"name":"ValidationError","message":"You must specify a key value"},
"buffer":{"0":123,"1":34,"2":115,"3":116,"4":97,"5":116,"6":117,"7":115,"8":34,"9":58,"10":34,"11":101,"12":114,"13":114,"14":111,"15":114,"16":34,"17":44,"18":34,"19":99,"20":111,"21":100,"22":101,"23":34,"24":58,"25":45,"26":49,"27":44,"28":34,"29":110,"30":97,"31":109,"32":101,"33":34,"34":58,"35":34,"36":86,"37":97,"38":108,"39":105,"40":100,"41":97,"42":116,"43":105,"44":111,"45":110,"46":69,"47":114,"48":114,"49":111,"50":114,"51":34,"52":44,"53":34,"54":109,"55":101,"56":115,"57":115,"58":97,"59":103,"60":101,"61":34,"62":58,"63":34,"64":89,"65":111,"66":117,"67":32,"68":109,"69":117,"70":115,"71":116,"72":32,"73":115,"74":112,"75":101,"76":99,"77":105,"78":102,"79":121,"80":32,"81":97,"82":32,"83":107,"84":101,"85":121,"86":32,"87":118,"88":97,"89":108,"90":117,"91":101,"92":34,"93":125,"length":94,
"parent":{"0":123,"1":34,"2":115,"3":116,"4":97,"5":116,"6":117,"7":115,"8":34,"9":58,"10":34,"11":101,"12":114,"13":114,"14":111,"15":114,"16":34,"17":44,"18":34,"19":99,"20":111,"21":100,"22":101,"23":34,"24":58,"25":45,"26":49,"27":44,"28":34,"29":110,"30":97,"31":109,"32":101,"33":34,"34":58,"35":34,"36":86,"37":97,"38":108,"39":105,"40":100,"41":97,"42":116,"43":105,"44":111,"45":110,"46":69,"47":114,"48":114,"49":111,"50":114,"51":34,"52":44,"53":34,"54":109,"55":101,"56":115,"57":115,"58":97,"59":103,"60":101,"61":34,"62":58,"63":34,"64":89,"65":111,"66":117,"67":32,"68":109,"69":117,"70":115,"71":116,"72":32,"73":115,"74":112,"75":101,"76":99,"77":105,"78":102,"79":121,"80":32,"81":97,"82":32,"83":107,"84":101,"85":121,"86":32,"87":118,"88":97,"89":108,"90":117,"91":101,"92":34,"93":125,"length":94},"offset":0},"cookies":{}}
Where can be the problem? any ideas how to get it running?
thank you very much!
I finally found the problem. There was en error in the config script.
it need to look like this:
var IPLogger_config = {};
IPLogger_config.mandrillAppKey = "xxx";
IPLogger_config.your_email = 'myemail#bla.com';
IPLogger_config.your_name = 'myName';
exports.IPLogger_config = IPLogger_config;
in the main.jsfile, the resources of the config file need to be called like this:
var config = require('cloud/mandrillapp_config.js');
Mandrill.initialize(config.IPLogger_config.mandrillAppKey);
and now it works fine.