Im using node.js and a library called requestify.
The code looks like this:
console.log('body');
console.log(body);
return new Promise(function (f, r) {
requestify.request(myurl, {
method: 'POST',
body : body,
headers : {
"Content-Type" : "application/json; charset=utf-8"
}
})
.then(function (response) {
f({messge : "Success"});
}, function (err) {
console.log(err);
err.code == 405 ? r(err.body) : r({ success: false, message: err });
});
});
When the request contains special characters (in this case swedish characters) then it throws an error.
Sending exactly the same request without the swedish characters, the request succedes.
I dont really have access to the server that is handling the request that's why it is hard to debug.
But I print the body before sending the request and I cannot see any strange things in it.
Here are the 2 different body-requests:
//FAILURE
{ eventType: 'createUser',
eventId: '1e2ca3b4-0f6b-4ed9-ae79-2e112c8d693c',
version: '0.1',
date: 2016-10-07T06:42:26.209Z,
attributes:
{ userName: 'akeandersson#gmail.se',
email: 'akeandersson#gmail.se',
firstName: 'Åke',
lastName: 'Andresson',
phoneNumber: '1',
identifier: '198509120328',
assignment: 'se.me',
role: [ 'se.me.role.user' ] },
metadata: {} }
//SUCCESS
{ eventType: 'createUser',
eventId: '1e2ca3b4-0f6b-4ed9-ae79-2e112c8d693c',
version: '0.1',
date: 2016-10-07T06:44:09.857Z,
attributes:
{ userName: 'akeandersson212#gmail.se',
email: 'akeandersson212#gmail.se',
firstName: 'Ake',
lastName: 'Andresson',
phoneNumber: '9',
identifier: '196606095823',
assignment: 'se.me',
role: [ 'se.me.role.user' ] },
metadata: {} }
I also put "; charset=utf-8" in the header's content-type (by default it is already utf-8 according to requestify documentation).
But still the same result. Any idea how I could debug this?
This is what the server returns when the request fails:
{
code: 400,
headers:
{ connection: 'close',
'content-type': 'text/plain',
'content-length': '244',
date: 'Fri, 07 Oct 2016 06:42:27 GMT' },
body: 'Unexpected end-of-input: expected close marker for OBJECT (from [Source: ServletInputStreamImpl#75eb88e4; line: 1, column: 0])\n at [Source: ServletInputStreamImpl#75eb88e4; line: 1, column: 767]' }
I guess, you need to upload your requestify module to the most recent version. I use version 0.2.3 which doesn't throw me any error.
Assuming that you encounter an error while trying to read a norwegian (or) swedish character, I have tried reading a website which has norwegian characters in it, and with the below code, I'm able to output it to the console without any error. Same with a swedish page too. I'm using 0.2.3 version though (which is the most recent version). I have not set the encoding to UTF-8 too.
var requestify = require('requestify');
requestify.get('http://www.norwegian4people.com/lesson.php?id=41').then(function(response) {
// Get the response body
console.log(response.getBody());
});
Hope this helps!
Related
I'm currently writing a small Twitter app using the Twit API. To do what I need to do, I'd like the data to be able to be filtered by user id, and not get all the other garbage JSON spits out. Here's what the response looks like:
{ created_at: 'Sat Jun 23 03:45:13 +0000 2018',
id: 1010368149466697700,
id_str: '1010368149466697728',
text:
'RT #ClassicIsComing: "Let\'s Talk ETC!" Podcast Series by #chris_seberino of #InputOutputHK \nA deep series of powerful intervie
ws with influ…',
truncated: false,
entities:
{ hashtags: [],
symbols: [],
user_mentions: [ [Object], [Object], [Object] ],
urls: [] },
source:
'TweetDeck',
in_reply_to_status_id: null,
in_reply_to_status_id_str: null,
in_reply_to_user_id: null,
in_reply_to_user_id_str: null,
in_reply_to_screen_name: null,
user:
{ id: 759252279862104000,
id_str: '759252279862104064',
name: 'Ethereum Classic',
screen_name: 'eth_classic',
location: 'Blockchain',
description:
'Latest News and Information from Ethereum Classic (ETC). A crypto-currency with smart contracts which respects immutability a
nd neutrality.',
url: ,
entities: { url: [Object], description: [Object] },
protected: false,
followers_count: 216255,
friends_count: 538,
listed_count: 2147,
etc. The code i'm using to get this is:
T.get('statuses/home_timeline', {count: 1, exclude_replies: true},
function(err, data, response){
if (err){
console.log('Uh oh, we got a problem');
}
else{
console.log('We GUUCie bruh');
}
var tweets = data;
/* for (var i = 0; i < tweets.length; i++) {
console.log(tweets[i]);
} */
console.log(data);
});
the last block of code is commented out because I've attempted to define "tweets" as data.id, data.statuses.id, etc, but everything seems to spit out "undefined." I'm a complete noob to javascript and JSON as I'm only currently learning C++ # school, so any help would be appreciated!
edit
I thought I'd add in the error message to show you what happens when I try to treat the data as an object.
If I try to use JSON.parse(data) as the value for my tweet variable:
T.get('statuses/home_timeline', {count: 1, exclude_replies: true}, callBackFunction)
function callBackFunction(err, data, response){
if (err){
console.log('Uh oh, we got a problem');
}
else{
console.log('We GUUCie bruh');
}
var tweets = JSON.parse(data);
//for (var i = 0; i < tweets.length; i++) {
// console.log(tweets[i].id_str);
// }
console.log(tweets.id_str);
}
I get:
$ node crypt.js
the bot is starting
We GUUCie bruh
undefined:1
[object Object]
^
SyntaxError: Unexpected token o in JSON at position 1
at JSON.parse (<anonymous>)
If I try to treat it as an object right away, with:
function callBackFunction(err, data, response){
if (err){
console.log('Uh oh, we got a problem');
}
else{
console.log('We GUUCie bruh');
}
var tweets = data.id_str;
//for (var i = 0; i < tweets.length; i++) {
// console.log(tweets[i].id_str);
// }
console.log(tweets);
}
I get:
$ node crypt.js
the bot is starting
We GUUCie bruh
undefined
Have you tried JSON.parse?
So your line "var tweets = data;" would be "var tweets = JSON.parse(data);"
From there you should be able to interact with the data as if it were an object and grab specifically the id or whatever you're looking for.
I'm also a noob, so I don't have an in depth explanation as to why this works, but it helped fix an issue I had when pulling data from API.
Well, I have a user model that needs to implement customToJSON and make the removal of the password for the object to be returned json.
When I put the "responseType" in "exits" as "json" everything happens fine, and the password is taken out of the response. However, the responseType: "json" will be deprecated according to the message in the terminal that sends the responseType empty, however the customToJSON is not called. Can anyone help me understand this?
this is the model code:
[...]
attributes: {
name: {
type: 'string',
required: true,
},
email: {
type: 'string',
required: true,
},
password: {
type: 'string',
minLength: 6,
required: true,
},
},
customToJSON: function() {
return _.omit(this, ['password']);
},
[...]
this is the action code:
module.exports = {
friedlyName: 'Users List',
description: 'User list -> all users',
exits: {
success: {
}
},
fn: async (inputs, exits) => {
var users = await User.find();
return exits.success(users);
}
}
this is the message if you put the "responseType: 'json'":
The json response type will be deprecated in an upcoming release. Please use `` (standard) instead (i.e. remove responseType from the success exit.)
I defined custom responses inside api/responses folder.
So, for example... for 200 OK response create api/responses/ok.js
and then inside action2 controller method add this to exits:
exits: {
success: {
description: 'Returns ok response from api/responses/ok.js',
responseType: 'ok'
}
}, ...
Example of my simple api/responses/ok.js
module.exports = function ok(data) {
return this.res.status(200).json(data);
};
You can create responses for each status/exit you need and later on it's easy to maintain exits... I have responses for: badRequest, serverError, forbidden, notFound and unauthorized
I am trying to get only one result back for a query I know may return more than one result, so I would like to use the the terminate_after parameter, but I can't work out how to use it in a query body in javascript. I have tried putting it in the body, like below, but I get a parsing_exception: "Unknown key for a VALUE_NUMBER in [terminateAfter]."
client.search({
index: 'myindex',
type: 'mytype',
body: {
terminateAfter: 1,
query: {
term: {
searchField: searchString
}
}
}
}, function(error, results){}
I have also tried putting it inside the query, but this also causes a parsing_exception: "[terminateAfter] query malformed, no start_object after query name"
I am using version 5.3 of elasticsearch and version 13.3.1 of the elasticsearch npm module.
You've almost got it right, terminateAfter should go outside the body, like this:
client.search({
index: 'myindex',
type: 'mytype',
terminateAfter: 1,
body: {
query: {
term: {
searchField: searchString
}
}
}
}, function(error, results){}
I am using the Twit Node.js API.
What I am trying to do is reply to a tweet that matches a certain keyword. I want my reply tweet to show up within the other tweet underneath. Like when you reply via app or website.
My code to do that is here:
var reply = function(tweet) {
var res = {
status: 'This is a tweet',
in_reply_to_status_id: tweet.id_str
};
twitter.post('statuses/update', res,
function(err, data, response) {
console.log(data);
}
);
}
The status is written correctly to the reply JSON but in_reply_to_status_id remains null. The tweet is posted to the bots account but not in reply to the tweet is is supposed to be replying to.
Why dos it not work?
And yes I have tried to write to in_reply_to_status_id_str and I have tryed to make the tweet.id_str a string.
I there anyone who knows what I am missing?
Thank you!
My response JSON is here:
{ created_at: 'Wed Jun 21 07:44:22 +0000 2017',
id: 877431986071142400,
id_str: '877431986071142400',
text: 'This is a tweet',
truncated: false,
entities: { hashtags: [], symbols: [], user_mentions: [], urls: [] },
source: 'Spatinator',
in_reply_to_status_id: null,
in_reply_to_status_id_str: null,
in_reply_to_user_id: null,
in_reply_to_user_id_str: null,
in_reply_to_screen_name: null,
If you need more of the respone JSON let me know.
The solution is to include a mention to tweet.user.screen_name into the status of the response json.
Like this it works:
var reply = function(tweet) {
var res = {
status: 'This is a tweet #' + tweet.user.screen_name,
in_reply_to_status_id: '' + tweet.id_str
};
twitter.post('statuses/update', res,
function(err, data, response) {
console.log(data);
}
);
}
I'm just trying to create or replace a document, but the API docs aren't clear on how to do this.
The upsert example shows a document being created with a counter value of 1:
client.update({
index: 'myindex',
type: 'mytype',
id: '777',
body: {
script: 'ctx._source.counter += 1',
upsert: {
counter: 1
}
}
}, function(error, response) {
// ...
})
I don't need the increment script, so I try to just send an upsert by itself, but I get a 400 Validation Failed: 1: script or doc is missing:
client.update({
index: "testindex",
type: "testType",
id: 1234,
body: {
upsert: {
itworks: true,
ok: "oh yeah"
}
}
})
Well, let's try something silly and include the doc twice; once under doc, which would presumably replace an existing document if there was one, and once under upsert, which would be used to create a new document otherwise:
client.update({
index: "testindex",
type: "testType",
id: 1234,
body: {
upsert: {
itworks: true,
ok: "oh yeah"
},
doc: {
itworks: true,
ok: "oh yeah"
}
}
})
That actually worked, 201 Created. 200 OK when I repeat it to replace the doc with a different one:
client.update({
index: "testindex",
type: "testType",
id: 1234,
body: {
upsert: {
whatever: "man"
},
doc: {
whatever: "man"
}
}
})
But when I check the doc (client.get({index: "testindex", type: "testType", id: 1234})), I see that instead of replacing the existing doc, the new doc was merged with it.
How do you just replace a doc in Elasticsearch, with the standard Node client? The HTTP API makes it look so simple, but I've tried a bunch of permutations of that in the Node client without success. Is there no replace command? Do I have to delete and then create?
In Elasticsearch, to replace a document you simply have to index a document with the same ID and it will be replaced automatically.
If you would like to update a document you can either do a scripted update, a partial update or both.
To do a partial doc update you simply
Partial document update:
client.update({
index: 'myindex',
type: 'mytype',
id: '1',
body: {
// put the partial document under the `doc` key
doc: {
title: 'Updated'
}
}
}, function (error, response) {
// ...
})
Scripted update:
client.update({
index: 'myindex',
type: 'mytype',
id: '1',
body: {
script: 'ctx._source.tags += tag',
params: { tag: 'some new tag' }
}
}, function (error, response) {
// ...
});
More info in Elasticsearch JS documentation
This is one of the reasons I always use index instead of create:
client.index({
"index": 'index-name',
"type": 'mapping type',
"id": 'id you want to create/replace',
'body': JSON.stringify(obj)
}, function (err, resp) {
if (err) {
console.error(err['message'])
}
else {
console.log(resp);
return resp
}
});