Angular JS - HTTP GET request throws error - json

I am very new to Angular JS and the Ionic application. I have tried to fetch the json data from the url . But, unfortunately I could not get any response. Instead, I get the error as shown in the screen below
I have tried in two ways,
Try 1:
function(){
return $http.get("url?subjStudyId=441",{'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}).then(function(response){
chats = response.data;
alert(JSON.stringify(chats));
return chats;
},function(err) {
alert(JSON.stringify(err));
})
}
Try 2:
function($http) {
var chats = [];
return {
all: function(){
return $http.get("url?subjStudyId=441").then(function(response){
chats = response.data;
alert(JSON.stringify(chats));
return chats;
},function(err) {
alert(JSON.stringify(err));
})
}
}
Please help me finding the solution .

Your problem may be CORS which stands for Cross-Origin Resource Sharing take a look at this in-depth CORS article here.
Enable CORS on your backend and try to do the request again. You can also make use of JSONP by enabling that on the backend then doing
$http.jsonp('url?callback=JSON_CALLBACK&param=value);
JSONP stands for "JSON with Padding" (and JSON stands for JavaScript
Object Notation), is a way to get data from another domain that
bypasses CORS (Cross Origin Resource Sharing) rules. CORS is a set of
"rules," about transferring data between sites that have a different
domain name from the client.
I coded up two examples, one using $http.get and the other $http.jsonp, neither work which tells me that you don't have Access-Control-Allow-Origin "*" in your server nor do you have JSONP support setup. Head over to enable-cors.org, they got nice articles to help you get CORS setup on your backend.
Technically, you should stick to CORS, since JSONP is more of a security concern. So if nothing is stopping you from just enabling CORS then stick to that.
Example of doing a standard $http.get and $http.jsonp requests via the use of promises.
var app = angular.module("MyApp", []);
app.controller("MyCtrl", function($scope, $http){
$scope.data = "";
$scope.normalCall = function(){
var results = $http.get('http://202.133.56.91:8081/SD_BIO/app/retrievenotifications.action?subjStudyId=441')
.then(function(response){
$scope.data = response;
}, function(error){
$scope.data = error;
});
return results;
};
$scope.jsonPCall = function(){
var results =$http.jsonp("http://202.133.56.91:8081/SD_BIO/app/retrievenotifications.action?callback=JSON_CALLBACK")
.then(function(response){
$scope.data = response;
}, function(error){
$scope.data = error;
});
return results;
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="MyApp">
<div ng-controller="MyCtrl">
<button ng-click="normalCall()">Original Call</button> |
<button ng-click="jsonPCall()">JSONP Call</button>
<br><br>
<div ng-model="data">{{data}}</div>
</div>
</div>

You need to specify the url you are going to do the GET
url?subjStudyId=441
isn't a url, it needs to be something like -> someurl.com/?subjStudyId=441 where the -> ? is the query start and the -> = is the value you are

Related

How to retrieve data from AWS Lambda and display it on a static website that's hosted on AWS S3?

I'm attempting to use AWS DynamoDB, Lambda, API Gateway, and S3 to create a simple website. DDB has a table and in the table is a single entry. S3 has a simple file for a HTML for a website. The goal is to display the entry located in DDB in the website, if I update the value in DDB, then refreshing the website should change the number to reflect the update in DDB. At the moment, I have a lambda function which successfully retrieves the entry from DDB. I am stuck in trying to tell the HTML file to call the lambda function and get the data back (using API Gateway). I have never worked with AWS before, forgive me if this isn't even the right approach for this goal.
Below is code for lambda function:
'use-strict';
const AWS = require('aws-sdk');
const docClient = new AWS.DynamoDB.DocumentClient({region: 'us-location-x'});
exports.handler = (event, context, callback) => {
let tableToRead = {
TableName: 'dataStore',
Limit: 10
};
docClient.scan(tableToRead, function(err,data){
if(err){
callback(err,null);
} else {
callback(null,data);
}
});
};
And this is the HTML that's on S3:
<html>
<head>
</head>
<body>
<h1> This number that's in DDB </h1>
<div id="entries">
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script type="text/javascript">
//This is the link generated by API Gateway
var API_URL = 'https://xxxxxxxxxx.execute-api.us-location-x.amazonaws.com/prod/retrieveDDB';
$(document).ready(function(){
$.ajax({
type: 'GET',
url: API_URL,
success: function(data){
$('#entries').html('');
data.Items.forEach(function(tableItem){
$('#entries').append('<p>' + tableItem.Row + '</p>');
})
}
});
});
</script>
</body>
</html>
When I run the lambda function using the "test" button, it successfully retrieves the data from the DDB. But when I try to run the HTML, it does say the header text but then it doesn't append the value from DDB. I'm assuming I'm just not understanding how to call/parse the lambda data (If I even have it set up properly).
Thanks in advance for any help!
The cross-origin request blocked error occurs because you are trying to access the api from a different domain (for e.g www.example.com). This is a security feature of the browsers called CORS( cross origin resource sharing requests). The browser will send a pre-light request to the api to check whether the call should be allowed.
A prelight request is sent as http options request to the api method.
There are two steps.
You need to enable Cors to the API gateway, resource method. So that it will enable the Options method for the resource. In short, you need to select the particular resource and then click Enable Cors from the actions.
Reference: Please read "Enable CORS support on a REST API resource" section of https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors.html
You should return the origin header from your lambda.
const docClient = new AWS.DynamoDB.DocumentClient({ region: 'us-location-x' });
exports.handler = async (event) => {
let tableToRead = {
TableName: 'dataStore',
Limit: 10
};
const headers = {
"Access-Control-Allow-Origin": '*'
// other headers
}
try {
const data = docClient.scan(tableToRead).promise();
return {
statusCode: 200,
body: JSON.stringify(data),
headers: headers
}
} catch (error) {
return {
statusCode: 400,
body: error.message,
headers: headers
}
}
};
Hope this helps. #Ashish Modi, thanks for sharing the link.

Sending nested object via post request

I'm running this little node express server, which is supposed to check if the voucher is valid later and then send an answer back to the client
this is my code
app.post('/voucher', function (request, response) {
response.setHeader('Access-Control-Allow-Origin', '*');
response.setHeader('Access-Control-Request-Method', '*');
response.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET');
response.setHeader('Access-Control-Allow-Headers', 'authorization, content-type');
if ( request.method === 'OPTIONS' ) {
response.writeHead(200);
response.end();
return;
}
console.log(request)
let results;
let body = [];
request.on('data', function(chunk) {
body.push(chunk);
}).on('end', function() {
results = Buffer.concat(body).toString();
// results = JSON.parse(results);
console.log('#### CHECKING VOUCHER ####', results)
let success = {success: true, voucher: {name: results,
xxx: 10}}
success = qs.escape(JSON.stringify(success))
response.end(success)
} )
}
);
It is obviously just an example and the actual check is not implemented yet. So far so good.
Now on the client side where I work with REACT, I can not seem to decode the string I just send there.
there I'm doing this
var voucherchecker = $.post('http://localhost:8080/voucher', code , function(res) {
console.log(res)
let x = JSON.parse(res)
console.log(x)
console.log(qs.unescape(x))
It gives me the error
Uncaught SyntaxError: Unexpected token % in JSON at position 0
When I do it the other way arround
let x = qs.unescape(res)
console.log(x)
console.log(JSON.parse(x))
Than it tells me
Uncaught TypeError: _querystring2.default.unescape is not a function
Maybe you can help me? I don't know what the issue is here. Thank you.
Also another question on this behalf, since I'm only a beginner. Is there smarter ways to do such things than I'm doing it now? I have react which renders on the client and I have a mini express server which interacts a few times with it during the payment process.
The both run on different ports.
What would be the standard way or best practice to do such things?
I'm a bit perplexed as to why your backend code has so much going on in the request.
Since you asked for if there is a different way to write this, I will share with you how I would write it.
Server
It seems that you want your requests to enable CORS, it also seems that you originally wanted to parse a JSON in your request body.
This is how I would recommend you re-write your endpoint
POST /voucher to take a request with body JSON
{
code: "xxxxx"
}
and respond with
{
success: true,
voucher: {
name: results,
xxx: 10
}
}
I would recommend you use express's middleware feature as you will probably use CORS and parse JSON in most your requests so in your project I would.
npm install body-parser
npm install cors
then in your app initialization
var bodyParser = require('body-parser')
var cors = require('cors')
var app = express()
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))
// parse application/json you can choose to just pars raw text as well
app.use(bodyParser.json())
// this will set Access-Control-Allow-Origin * similar for all response headers
app.use(cors())
You can read more about body-parser and cors in their respective repos, if you don't want to use them I would still recommend you use your own middleware in order to reduse future redundancy in your code.
So far this will substitute this part of your code
response.setHeader('Access-Control-Allow-Origin', '*');
response.setHeader('Access-Control-Request-Method', '*');
response.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET');
response.setHeader('Access-Control-Allow-Headers', 'authorization, content-type');
if ( request.method === 'OPTIONS' ) {
response.writeHead(200);
response.end();
return;
}
console.log(request)
let results;
let body = [];
request.on('data', function(chunk) {
body.push(chunk);
}).on('end', function() {
results = Buffer.concat(body).toString();
// results = JSON.parse(results);
Now your route definition can just be
app.post('/voucher', function (request, response) {
var result = request.body.code // added by body-parser
console.log('#### CHECKING VOUCHER ####', result)
// express 4+ is smart enough to send this as json
response.status(200).send({
success: true,
voucher: {
name: results,
xxx: 10
}
})
})
Client
your client side can then be, assuming $ is jquery's post function
var body = {
code: code
}
$.post('http://localhost:8080/voucher', body).then(function(res) {
console.log(res)
console.log(res.data)
return res.data
})

Fetching data from a JSON object (from a given API) in AngulaJS

I have the following code to present data from a link (API) as suggestion for an autocomplete box. Although it is working for one link and not the other. I observed that data format for both are different, modified my code accordingly but it is still not helpful.
.js file:
var plunker= angular.module('plunker', ['ui.bootstrap', 'ngGrid']);
function TypeaheadCtrl($scope, $window, $http, limitToFilter) {
$scope.cities = function (cityName) {
return $http.jsonp("http://mtapi.azurewebsites.net/api/institute").then(function (response) {
return response[0].description;
});
};
}
HTML file:
<input type="text" id="depn" ng-model="formdata.department"
typeahead="suggestion.description for suggestion in cities($viewValue)"
placeholder="department" class="form-control">
If you replace the cities function with this one,
$scope.cities = function (cityName) {
return $http.jsonp("http://gd.geobytes.com/AutoCompleteCity?callback=JSON_CALLBACK &filter=US&q=" + cityName).then(function (response) {
return response.data;
});
};``
Even after I changed my code jsonP request to .get, it is still not working
var plunker= angular.module('plunker', ['ui.bootstrap', 'ngGrid']);
function TypeaheadCtrl($scope, $window, $http, limitToFilter) {
$scope.cities = function (cityName) {
return $http.get("http://mtapi.azurewebsites.net/api/institute").success(function(data) {
return data[0].description;
});
};
}
It is working fine.
Is there a problem with my code, or a back end server issue?
Change your cities function to use the data property of the response in your .then (that's how you'll access the response from a resolved HttpPromise):
var plunker= angular.module('plunker', ['ui.bootstrap', 'ngGrid']);
function TypeaheadCtrl($scope, $window, $http, limitToFilter) {
$scope.cities = function (cityName) {
return $http.get("http://mtapi.azurewebsites.net/api/institute").then(function (response) {
return response.data[0].description;
});
};
EDIT
Even making that code change won't solve your problem. This url does not support cross-origin requests, so you either need to host your angularjs app on the same domain and use a plain $http.get instead of $http.jsonp, or this url needs to support JSONP requests (the content-type of the response from this url is application/json. For JSONP to work it should be application/javascript).
I figured it out lately. Apart from the problem at back end there were issues in this code as well. I was returning the promise, but promise was never resolved to return the value also I was trying to return a string, whereas I should return array of strings. Here's the change:
$scope.aap = result.data;
var res = [];
res.push($scope.aap[0].Description);
return res;

Angular.js: $http request with JSON as response doesn't work

it's my first app with Angular.js and I've searched so hardly but I can't find a solution:
I've got a search form that makes a request to a web server which retrieves a JSON object; the problem is that this request fails and the error function begins.
Here my code:
$scope.queryUser = {};
$scope.url = "http://xxxx:8080/MyApp/search.do?index=central&query=";
$scope.search = function(query) {
$scope.queryUser= angular.copy(query);
// Create the http post request
// the data holds the keywords
// The request is a JSON request.
$http.post($scope.url + $scope.queryUser.value).
success(function(data, status) {
$scope.status = status;
$scope.data = JSON.stringify(data);
$scope.result = data; // Show result from server in our <pre></pre> element
console.log(data);
})
.
error(function(data, status) {
$scope.data = data || "Request failed";
$scope.status = status;
console.log($scope.data);
});
and this is a sample response:
{"Workstation, Laptop#Workstation$$Laptop":[{"values":{"instanceid":"OI-4A35F9C31E114FBCB5B7668FC5E1FFB4","classid":"COMPUTERSYSTEM"},"index":"distributed"},{"values":{"instanceid":"OI-6A03793A658E45EE90E589D82B0D0962","classid":"COMPUTERSYSTEM"},"index":"distributed"}]}
Any suggestions?
Thanks in advance
I understood the problem: this is a problem of domain. Making the request calling the same webservlet it works...calling an external server it doesn't work.
DOH! I'm sorry for the question

Node: Basic JSON request

I'm a complete beginner in Node.js and I wanted to consult something I could not figure out.
Even though I've researched extensively I could not find any method to receive JSON request without using a plugin. I will be using it to program a mobile application API. But even though I've incluede parameter request I cannot reach the content by using request.body, or request.data. The request I'm trying to make is;
{
"id":"123"
}
And my failing code is;
var http = require('http');
function onRequest(request, response){
console.log("Request: "+request.data+"\n");
response.writeHead(200, {"Content-Type":"text/plain"});
response.write("Hello, World");
response.end();
}
http.createServer(onRequest).listen(8888);
The problem here is that you're not listening to the request events to let you know that you have data, and then parsing the data. You're assuming that request has request.data.
It should be:
var http = require('http');
function onRequest(request, response){
var data = '';
request.setEncoding('utf8');
// Request received data.
request.on('data', function(chunk) {
data += chunk;
});
// The end of the request was reached. Handle the data now.
request.on('end', function() {
console.log("Request: "+data+"\n");
response.writeHead(200, {"Content-Type":"text/plain"});
response.write("Hello, World");
response.end();
});
}
http.createServer(onRequest).listen(8888);
See this for the documentation for the methods that request contains.