Call Wordnik API from NodeJS using Swagger - javascript

I am having problems trying to use the Wordnik API via Swagger (NodeJS).
I am trying to follow this documentation: swagger-api
The Wordnik API can be founded here: hhttp://developer.wordnik.com/docs.html#!/word/getRelatedWords_get_4
The JSON description of the Wordnik API: hhttp://developer.wordnik.com/v4/word.json
I am trying to call the GET /word.json/{word}/relatedWords method with the following parameters:
{word:"cars", useCanonical:true, relationshipTypes:"synonim", limitPerRelationshipType:10}
The Wordnik API requires authentification, according to the swagger-api documentation I have written the following code:
var Swagger = require('swagger-client');
var client = new Swagger({
url: 'http://developer.wordnik.com/v4/word.json',
success: function() {
client.word.getRelatedWords({word:"cars",useCanonical:true,relationshipTypes:"synonim",limitPerRelationshipType:10}, function(success){
console.log('succeeded and returned this object: ' + success.obj);
},
function(error) {
console.log('failed with the following: ' + error.statusText);
});
},
authorizations: {
api_key: new Swagger.ApiKeyAuthorization('api_key', 'MY_WORDNIK_API_KEY', 'query'),
}
});
My main problem is that I do not know how to write properly the code to call that method with that parameters. The code written above returns this error:
failed with the following: {"message": "unauthorized", "type":
"error"}
Any idea about how to write the code to make that call?

Two things: one, the Swagger url for Wordnik should be
http://api.wordnik.com/v4/word.json
Two, you need to use 'synonym', not 'synonim'.
I tried your code with both these changes and it works fine for me.
Also, I'm not sure why you're using Swagger.js here? It's definitely cooler, but you can call the API with request, e.g.:
request("http://api.wordnik.com:80/v4/word.json/"+'car'+"/relatedWords?useCanonical=false&relationshipTypes=synonym&limitPerRelationshipType=10&api_key=YOURKEYHERE", function (error, response, body) {
if (error || response.statusCode !== 200 || (body == "")) {
console.log(word + " had error: " + error)
return callback(error || {statusCode: response.statusCode});
}
else {
// console.log(word);
callback(null, JSON.parse(body));
}
});

Related

Javascript and Django Rest Framework - cannot read property

I'm trying to retrieve data from an API endpoint that i created with Django Rest Framework. At first, my code worked but now i keep getting this error:
Uncaught TypeError: Cannot read property 'ticker' of undefined
It's weird, because the console.logstatement in the following code returns nothing, although i'm sure that there is data in the endpoint that i'm calling.
This is what the data i'm trying to retrieve looks like:
[
{
ticker: "TEST",
Price: 7876
}
]
And this is the Ajax function that i built:
function doPoll(){
$.getJSON('http://127.0.0.1:8000/tst/', function(data) {
console.log(data[0]);
$('#data').text(data[0].ticker + ' ' + data[0].Price);
setTimeout(doPoll, 100);
});
}
doPoll();
And this is where the data should appear:
<h3 id="data"></h3>
The function should be supposed to place my data on my html page and refresh that data every second.
http://127.0.0.1:8000/tst/ is the DRF API endpoint that i'm trying to call, from where i'm retrieving the JSON data.
you need to access data.results... this is standard DRF response format
function doPoll(){
$.getJSON('http://127.0.0.1:8000/tst/', function(data) {
var results = data.results;
console.log(results[0]);
$('#data').text(results[0].ticker + ' ' + results[0].price);
setTimeout(doPoll, 100);
});
}
doPoll();
You have a typo here data[0].Price should be data[0].price
$.getJSON('http://127.0.0.1:8000/tst/', function(data) {
if(data && data.length > 0){
console.log(data[0]);
$('#data').text(data[0].ticker + ' ' + data[0].Price);
setTimeout(doPoll, 100);
}else{
//console.log('No Data')
console.log("DATA is: ", data)
}
});
Validate that data[0] exists before accessing properties of it
The best way to debug this is to check the response in your browser dev tools
Network tab

Reading from NegotiatedContentResult object (sent from WebAPI) in angular js promise

Displayed below is my WebAPI method which returns a list of Information about several books.
[System.Web.Http.Authorize]
public async Task<IHttpActionResult> Get(Guid id)
{
try
{
var result = await _assetAssetRepository.View(id);
if (result == null)
{
return NotFound();
}
return Content(HttpStatusCode.Found, result);
}
catch (Exception ex)
{
return Content(HttpStatusCode.InternalServerError,
"Exception Occurred" + ex.Message + " " + ex.StackTrace);
}
}
Angular js code to consume this data
var getAssetDetails = function (assetId) {
var deferred = $q.defer();
$http.get("/api/Asset/" + assetId, { headers: { 'Authorization': 'Bearer ' + $cookies.get('accessToken') } })
.then(function (response) {
deferred.resolve(response);
}).catch(function (response) {
alert("Oops something wrong: " + response.data);
deferred.reject(response);
}).finally(function () {
});
return deferred.promise;
};
The bit i am struggling is if you replace this line of code in webapi
"return Content(HttpStatusCode.OK,result)" with "return Ok(result)" i can see the data in the UI without any problem. However when i use "return Content(HttpStatusCode.OK,result)", the angular code for some cannot read this and throws out exception and shows the alert message saying "Oops something wrong [object Object]" so it seems like its getting the data but for some reason its still throwing exception. Anyone up for help?
Well, it's best to start with details given by the catch block. But one of many errors can be (which I first had):
Unexpected token R in JSON at position 0
which is be due to responseType: 'JSON' added in your http request. Angular takes the response as JSON where in this case it is not. So we need to remove this.
Here is how I do it (end-to-end). From my API:
return Content(HttpStatusCode.<statuscode>, "ResponseContent: " + "my_custom_error");
Second Case:
//If I'm getting output from another API/Layer then I pass it's output like this
var output = response.Content.ReadAsStringAsync().Result;
return Content(response.StatusCode, "ResponseContent: " + output);
And in the Angular code, I read it like this:
$http({ method: methodType, url: endpoint })
.then(function (response) {
response.status; //gets you the HttpStatusCode to play with
response.data; //gets you the ReponseContent section
}, function (response) {
response.status; //gets you the HttpStatusCode
response.data; //gets you the ReponseContent section
});
From https://docs.angularjs.org/api/ng/service/$http
The response object has these properties:
data – {string|Object} – The response body transformed with the
transform functions.
status – {number} – HTTP status code of the response.
headers – {function([headerName])} – Header getter function.
config – {Object} – The configuration object that was used to
generate the request.
statusText – {string} – HTTP status text of the response.

xmlReader Failed with: TypeError: Cannot call method 'text' of undefined

I am using the npm xmlreader to parse my xml I am receiving from yahoo weather on parse's cloud. I have been using the examples from the git repository and the example here: https://www.npmjs.org/package/xmlreader to try to see if I can get the contents of any node at this point and I am having no luck. I am doing it as such:
Parse.Cloud.job("getPage", function(request, status) {
var response = "I never get set";
Parse.Cloud.httpRequest({
url: 'http://weather.yahooapis.com/forecastrss?w=2442047&u=f',
success: function (httpResponse) {
console.log("Got here yo");
response = httpResponse.text;
response = response.toString();
response = parseXML(response);
status.success(response.toString());
},
error: function (httpResponse) {
status.error('Request failed with response code ' + httpResponse.status);
}
});
});
function parseXML (p1)
{
var xmlreader = require('cloud/xmlreader.js');
xmlreader.read(p1, function (err, xmldata) {
if(err) return console.log(err);
console.log( xmldata.title.text() );
});
return "hello";
}
every time I run the job I get the error.
Failed with: TypeError: Cannot call method 'text' of undefined
<title>Yahoo! Weather - Los Angeles, CA</title>
<description>Yahoo! Weather for Los Angeles, CA</description>
<language>en-us</language>
<lastBuildDate>Thu, 10 Jul 2014 10:47 am PDT</lastBuildDate>
<ttl>60</ttl>
I have imported everything correctly and installed it correctly. If I just call xmlreader.text() it won't fail but there will be nothing to print is it not reading the xml properly? Any help would be great thanks!
I was not navigating the nodes correctly. I was missing a node when trying to access the title I was just trying to do res.title instead I needed to do res.rss.title.

Seems that no response received on getJSON

I am sending the jsonp request as:
var jsoncallback = "?jsoncallback=?"
$.getJSON( reportURL + jsoncallback, {
tags: "",
tagmode: "any",
format: "json"
})
.done(function( data ) {
$.each( data.items, function( i, item ) {
alert( item );
});
});
I have put an alert to see if the request works. On server side, in node js file I am responding to request as:
..
console.log("request received");
response.writeHead( 200, { "Content-Type": "application/json" } );
..
response.end();
In the logs I can see that the request received. The problem is that no alert windows pops up.
What could be the reason to this?
I just reponse.writeHead(...) and (for testing reasons - just the head and end) response.end()
With the jsoncallback=? in the URL, jQuery is expecting a JSONP <script> as a response. For this to work, the server should at the very least write out the "padding."
That is a call to the function named by jsoncallback. And it won't be just ? -- jQuery replaces that with a pseudo-random function name along the lines of jQuery1910123456789_0123456789. For that, the response should at least be:
jQuery1910123456789_0123456789();
You'll need to get the value from the request.url:
var parsedUrl = url.parse(request.url, true);
var query = parsedUrl.query || {};
if ('jsoncallback' in query) {
response.write(query.jsoncallback + '();');
}
// ...
And, once you have data to output with it:
if ('jsoncallback' in query) {
response.write(query.jsoncallback + '(' + JSON.stringify(data) + ');');
} else {
response.write(JSON.stringify(data));
}
Have you confirmed the JSON is correctly formatted? Check it against http://jsonlint.com/.
From the getJSON() docs:
As of jQuery 1.4, if the JSON file contains a syntax error, the
request will usually fail silently.

How to override Backbone.sync so it adds the apikey and username at the end?

I am using backbone-tastypie, but I am having the toughest time getting it to work properly. In Tastypie, I am using ApiKeyAuthentication for my resources, so every ajax request, I need to append the apikey and username to the end of a request or send additional headers that add on the username and api key.
I am trying to remove a view and its model using backbone with the following code:
// Remove the goal update view from the DOM
removeItem: function() {
this.model.destroy({wait: true, success: function() {
console.log("success");
}, error: function() {
console.log("error");
}});
},
After the function executes, the browser tries to do a GET request on the following URL:
:8000/api/v1/update/2/
It does not include the api_key or username at the end, and it has a trailing slash at the end of the url. I think it is trying to use Backbone.oldSync to do the GET request. How would I make it so the sync does include the username/api key at the end and removes the trailing slash?
In all of the other requests, I have made it so the api key and username is appended to the end of the http request by adding the following code to backbone-tastypie:
if ( !resp && ( xhr.status === 201 || xhr.status === 202 || xhr.status === 204 ) ) { // 201 CREATED, 202 ACCEPTED or 204 NO CONTENT; response null or empty.
var location = xhr.getResponseHeader( 'Location' ) || model.id;
return $.ajax( {
url: location + "?" + "username=" + window.app.settings.credentials.username + "&api_key=" + window.app.settings.credentials.api_key,
success: dfd.resolve,
error: dfd.reject,
});
}
Let's explore the possibilities
Using headers
Backbone.sync still just uses jQuery ajax so you can override ajaxSend and use headers to send information along.
$(document).ajaxSend(function(e, xhr, options)
{
xhr.setRequestHeader("username", window.app.settings.credentials.username);
xhr.setRequestHeader("api_key", window.app.settings.credentials.api_key);
});
Using Ajax Options
If you need to send the information in just one or two locations, remember that the destroy, fetch, update and save methods are just shortcuts to the ajax caller. So you can add all jQuery ajax parameters to these methods as such:
// Remove the goal update view from the DOM
removeItem: function ()
{
this.model.destroy({
wait: true,
success: function ()
{
console.log("success");
},
error: function ()
{
console.log("error");
},
data:
{
username: window.app.settings.credentials.username,
api_key: window.app.settings.credentials.api_key
}
});
}
Overriding jQuery's ajax method
Depending on your needs, this might be the better implementation (note that this is no production code, you may need to modify this to fit your needs and test this before using it)
(function ($) {
var _ajax = $.ajax;
$.extend(
{
ajax: function (options)
{
var data = options.data || {};
data = _.defaults(data, {
username: window.app.settings.credentials.username,
api_key: window.app.settings.credentials.api_key
});
options.data = data;
return _ajax.call(this, options);
}
});
})(jQuery);
Just for future readers of this post, when you do a model.destroy() you can't pass any data because the delete request doesn't have a body, see this issue for more info:
https://github.com/documentcloud/backbone/issues/789

Categories

Resources