Why do I get empty reponse from this http request - json

I am working on my first node.js script which simply makes a http request to https://www.swapi.co/api/people/?search=Luke+ and parses the response data.
The endpoint is as follows:
var options = {
host: 'www.swapi.co',
path: `/api/people/?search=`+firstName+'+'+lastName
};
The logic is to get the data from response and parse it to a person object:
makeRequest(options, function( data, error) {
let person = data.results[0];
if (person) {
let height = person.height;
let response = person.name + " is " + height + " centimeters tall.";
callback(null, {"speech": response});
}
else {
callback(null, {"speech": "I'm not sure!"});
}
});
The definition of makerequest function is below:
function makeRequest(options, callback) {
var request = http.request(options,
function(response) {
var responseString = '';
response.on('data', function(data) {
responseString += data;
});
response.on('end', function() {
console.log('end: $$$' + responseString + '$$$');
var responseJSON = JSON.parse(responseString);
callback(responseJSON, null);
});
});
request.end();
}
When I run the script I got the error about parsing the JSON.
Unexpected end of JSON input
at Object.parse (native)
at IncomingMessage.<anonymous> (/var/task/index.js:42:37)
at emitNone (events.js:91:20)
at IncomingMessage.emit (events.js:185:7)
at endReadableNT (_stream_readable.js:974:12)
at _combinedTickCallback (internal/process/next_tick.js:80:11)
at process._tickDomainCallback (internal/process/next_tick.js:128:9)
I tested the endpoint using Postman and got the following JSON as response:
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"name": "Luke Skywalker",
"height": "172",
"mass": "77",
"hair_color": "blond",
"skin_color": "fair",
"eye_color": "blue",
"birth_year": "19BBY",
"gender": "male",
"homeworld": "https://www.swapi.co/api/planets/1/",
"films": [
"https://www.swapi.co/api/films/2/",
"https://www.swapi.co/api/films/6/",
"https://www.swapi.co/api/films/3/",
"https://www.swapi.co/api/films/1/",
"https://www.swapi.co/api/films/7/"
],
"species": [
"https://www.swapi.co/api/species/1/"
],
"vehicles": [
"https://www.swapi.co/api/vehicles/14/",
"https://www.swapi.co/api/vehicles/30/"
],
"starships": [
"https://www.swapi.co/api/starships/12/",
"https://www.swapi.co/api/starships/22/"
],
"created": "2014-12-09T13:50:51.644000Z",
"edited": "2014-12-20T21:17:56.891000Z",
"url": "https://www.swapi.co/api/people/1/"
}
]
}
However, when I debug my code, the response data is an empty string. And that explains the JSON error.
What is wrong with my http request? Why am I not getting the correct response?

It appears that the API you are targeting only supports SSL, but Node's HTTP library only supports plain-text requests. Try using their HTTPS library instead.
var https = require('https');
var request = https.request(options, ...);

That URL you are using returns HTML by default.
Instead you need to call: https://www.swapi.co/api/people/?format=json&search=Luke+
(Note the format=json parameter)

Related

Struggling to get data from AWS lambda JSON

I'm working on a lambda project and getting data from an API inside the function which looks like this
{ "Title": "300", "Year": "2006", "Rated": "R", "Released": "09 Mar 2007", "Runtime": "117 min", "Genre": "Action, Fantasy, War", "Director": "Zack Snyder", "Writer": "Zack Snyder (screenplay), Kurt Johnstad (screenplay), Michael B. Gordon (screenplay), Frank Miller (graphic novel), Lynn Varley (graphic novel)", "Actors": "Gerard Butler, Lena Headey, Dominic West, David Wenham", "Plot": "King Leonidas of Sparta and a force of 300 men fight the Persians at Thermopylae in 480 B.C.", "Language": "English", "Country": "USA, Canada, Bulgaria", "Awards": "17 wins & 45 nominations.", "Poster": "https://m.media-amazon.com/images/M/MV5BMjc4OTc0ODgwNV5BMl5BanBnXkFtZTcwNjM1ODE0MQ##._V1_SX300.jpg", "Ratings": [ { "Source": "Internet Movie Database", "Value": "7.7/10" }, { "Source": "Rotten Tomatoes", "Value": "60%" }, { "Source": "Metacritic", "Value": "52/100" } ], "Metascore": "52", "imdbRating": "7.7", "imdbVotes": "691,774", "imdbID": "tt0416449", "Type": "movie", "DVD": "31 Jul 2007", "BoxOffice": "$210,500,000", "Production": "Warner Bros. Pictures", "Website": "http://300themovie.warnerbros.com/", "Response": "True" }
I've tried dot notation, indexing all sorts but no matter what I try, the console log just comes out with
2019-06-14T18:33:46.394Z ecc5d247-6475-464e-8dd7-bec310d98c4a INFO undefined
Has anyone else had the same issue before with lambda and lex?
Thanks
const https = require('https')
let url = "http://www.omdbapi.com/?t=300&r&apikey=3ecc35a"
let reply;
const http = require('http')
let test;
http.get(url, res => {
res.setEncoding("utf8");
let body = "";
res.on("data", data => {
body += data;
});
res.on("end", () => {
console.log(body);
reply = JSON.parse(body);
});
});
This currently produces a perfectly good JSON in the console but it's impossible to actually extract anything. I've tried reply.Year, reply["Year"], reply.[0].Year almost any combination I can think off.
Full Code
'use strict';
'use fetch';
// Close dialog with the customer, reporting fulfillmentState of Failed or Fulfilled ("Thanks, your pizza will arrive in 20 minutes")
function close(sessionAttributes, fulfillmentState, message) {
return {
sessionAttributes,
dialogAction: {
type: 'Close',
fulfillmentState,
message,
},
};
}
// --------------- Events -----------------------
function dispatch(intentRequest, callback) {
console.log(`request received for userId=${intentRequest.userId}, intentName=${intentRequest.currentIntent.name}`);
const sessionAttributes = intentRequest.sessionAttributes;
//const film = intentRequest.currentIntent.film;
const film = intentRequest.currentIntent.slots.film.toString();
console.log(intentRequest.currentIntent.slots.film.toString());
const https = require('https')
let url = "http://www.omdbapi.com/?t=300&r&apikey=3ecc35a"
let reply;
const http = require('http')
let test;
http.get(url, res => {
res.setEncoding("utf8");
let body = "";
res.on("data", data => {
body += data;
});
res.on("end", () => {
console.log(body);
reply = JSON.parse(body);
});
});
//const rating = reply.imdbRating;
console.log(reply);
callback(close(sessionAttributes, 'Fulfilled',
{'contentType': 'PlainText', 'content': `The film ${film} has a rating of `}));
}
// --------------- Main handler -----------------------
// Route the incoming request based on intent.
// The JSON body of the request is provided in the event slot.
exports.handler = (event, context, callback) => {
try {
dispatch(event,
(response) => {
callback(null, response);
});
} catch (err) {
callback(err);
}
};
I tried to reproduce the issue with that code and got the following error
Response:
{
"errorType": "TypeError",
"errorMessage": "Cannot read property 'name' of undefined",
"trace": [
"TypeError: Cannot read property 'name' of undefined",
" at dispatch (/var/task/index.js:20:112)",
" at Runtime.exports.handler (/var/task/index.js:65:9)",
" at Runtime.handleOnce (/var/runtime/Runtime.js:63:25)",
" at process._tickCallback (internal/process/next_tick.js:68:7)"
]
}
Line 20 of index.js for me is:
console.log(`request received for userId=${intentRequest.userId}, intentName=${intentRequest.currentIntent.name}`);
However when using the test event in the question event.currentIntent doesn't exist and the name property of the event object doesn't exist either.
If I remove part of the console.log statement and change it to reference the Title attribute which exists in the test event I get:
console.log(`request received for Title=${intentRequest.Title}`);
INFO request received for Title=300
Seems like the function's code is referencing attributes fine but the function's just not receiving it's expected event objects.
HTH
-James

Error when trying to read JSON array using Should, Mocha, & Supertest

I have the following JSON payload:
"app": {
"name": "myapp",
"version": "1.0.0",
"last_commit": {
"author_name": "Jon Snow"
"author_email": "my#email.com"
}
}
and the following .js file (using Mocha, Supertest and Should):
var supertest = require('supertest')
var should = require('should')
var server = supertest.agent('http://localhost:3001')
describe('GET /', function () {
it('should respond with JSON', function (done) {
server
.get('/')
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.expect(200)
.end(function (err, res) {
var payload = res.body.app;
payload.should.have.property("app");
payload.should.have.property("name");
payload.should.have.property("version");
payload.should.have.property("last_commit");
payload.should.have.property("last_commit.author_name");
payload.should.have.property("last_commit.author_email");
done();
});
});
});
When I test the app, I receive the following error message:
Uncaught AssertionError: expected Object {
"name": "myapp",
"version": "1.0.0",
"last_commit": Object {
"author_name": "Jon Snow"
"author_email": "my#email.com"
}
} to have property 'last_commit.author_name'
Why am I receiving an assertion error on the these lines?
payload.should.have.property("last_commit.author_name");
payload.should.have.property("last_commit.author_email");
Assertion is looking for a property called last_commit.author_name which is not present. You may want to break that into two assertions.
payload.should.have.property("last_commit");
let last_commit = payload.last_commit;
last_commit.have.property("author_name");

Use API's URL to receive json

I am accessing the api of world weather online. I have configured the url and it is displayed below-
http://api.worldweatheronline.com/premium/v1/marine.ashx?key=XXXXXXXXXXXXXXXX&q=-34.48,150.92&format=json
Note: my API key is displayed as XXXXXXXXXXXX and this is returning the following:
{
"data": {
"request": [],
"weather": [
{
"date": "2016-11-20",
"astronomy": [],
"maxtempC": "27",
"maxtempF": "80",
"mintempC": "15",
"mintempF": "58",
"hourly": [
{
"time": "0",
"tempC": "15",
...
I want to GET this json in JS and then log the value of TempC.
How can this be done?
The simplest way would be using request. You can install it with npm install request
const request = require('request')
const apiKey = 'XXXXXXXX'
let url = 'http://api.worldweatheronline.com/premium/v1/marine.ashx'
let qs = {
q: '-34.48,150.92',
format: 'json',
key: apiKey
}
request({ url, qs }, (err, response, body) => {
if (err)
return console.error(err)
if (response.statusCode != 200)
return console.error('status:', response.statusCode, body)
body = JSON.parse(body)
console.log(body.data.weather[0].hourly[0].tempC)
})

Spotify API top-tracks broken

I'm trying to get the first top-track preview url from an artist but everytime I do the search it returns a broken json. I can parse it as a string to get what I need but a json would be a lot easier. Here is my code:
const https = require('https');
var open = require('open')
function songError(){
console.log('There was some kind of error fetching your artist ;(');
}
function getTopSong(p_id){
https.get('https://api.spotify.com/v1/artists/'+p_id+'/top-tracks?country=BR', function(res){
res.on("data", function(chunk){
var json = JSON.parse(chunk.toString('utf8'));
console.log(json);
});
});
}
function getArtistID(p_name) {
https.get('https://api.spotify.com/v1/search?q='+encodeURI(p_name)+'&type=artist', function(res){
res.on("data", function(chunk) {
var json = JSON.parse(chunk.toString('utf8'));
if(json['artists']['items'][0]['id'] != undefined || json['artists']['items'][0]['id'] != null){
console.log('id: ',json['artists']['items'][0]['id']);
getTopSong(json['artists']['items'][0]['id']);
}else
{
songError();
}
});
});
}
getArtistID("rage against the machine");
There seems to be an error in line 329:
undefined:329
"available_markets" : [ "AR", "AU", "AT", "BE", "BO", "BR", "BG", "CA", "CL", "CO", "CR", "CY", "CZ", "DK", "DO", "DE", "EC", "EE", "SV", "FI", "FR", "GR", "
My question is, am I doing something wrong or is it really broken?
Thanks!
I could curl it without any problems at least:
$ curl -s 'https://api.spotify.com/v1/artists/2d0hyoQ5ynDBnkvAbJKORj/top-tracks?country=BR' | python -mjson.tool | tail
"id": "25CbtOzU8Pn17SAaXFjIR3",
"name": "Take The Power Back - Remastered",
"popularity": 58,
"preview_url": "https://p.scdn.co/mp3-preview/b44e8f96a219871587d0559970ca5dce71c891f2",
"track_number": 3,
"type": "track",
"uri": "spotify:track:25CbtOzU8Pn17SAaXFjIR3"
}
]
}
I don't know much about nodejs, but don't you need to concatenate all callbacks to res.on("data"?
https://nodejs.org/api/http.html#http_http_request_options_callback
https.get('https://api.spotify.com/v1/artists/' + p_id + '/top-tracks?country=BR', function(res) {
var body = [];
res.on("data", function(chunk) {
body.push(chunk);
});
res.on("end", function() {
var json = JSON.parse(Buffer.concat(body).toString("utf8"));
console.log(json);
});
});
If the response is long and Spotify's servers decides to send the response back chunked transfer encoding, then the nodejs http module probably splits the response up as well.

AngularJS SyntaxError: Unexpected token s

I have a function called login, when the User pushes the button, the code below will be executed.
So i try to see if the user exists and to get his data in an JSON Object but that doesn't work, i get following Message:
SyntaxError: Unexpected token s
at Object.parse (native)
the URL is exactly like i want it to be.
$scope.login = function() {
var request = $http({
method : "GET",
url : "/REST/user" + "/" + $scope.email + "/" + "password" + "/" + $scope.password,
headers : {
'Content-Type' : "application/json"
}
});
request.success(function(response) {
location.href = "../views/test.html"
});
request.error(function(response) {
growl.addErrorMessage("doesn't work", {
ttl : 4000
});
});
}
Output by Browser
{
"id": "9be1804a-e366-11e4-9d4b-82ea0d805d53",
"email": "test#gmx.com",
"facebook_id": null,
"firstname": "test",
"lastname": "blabla",
"password": null,
"gender": null,
"is_active": "0",
"birthday": null
}
This error is due to JSON.parse throwing an error when it encounters an object with key that doesn't start with quotes ".
For example:
{ abc: 123 }
would throw "Unexpected token a".
$http, by default, treats any data in response with "Content-Type": "application/json" or anything that starts with { or [ as JSON, and invokes JSON.parse.
Take a look at the response in the Network tab of the developer console to see what may have triggered it.