Node.js unexpected token R - node.js

I am getting this error from my terminal:
SyntaxError: Unexpected token R
at Object.parse (native)
at Client.exports.json [as parse] (/Users/terrychen/Desktop/Git/ControlPanel/node_modules/hippie/lib/hippie/parsers.js:15:18)
at Request._callback (/Users/terrychen/Desktop/Git/ControlPanel/node_modules/hippie/lib/hippie/client.js:388:10)
at Request.self.callback (/Users/terrychen/Desktop/Git/ControlPanel/node_modules/hippie/node_modules/request/request.js:129:22)
at Request.EventEmitter.emit (events.js:98:17)
at Request.<anonymous> (/Users/terrychen/Desktop/Git/ControlPanel/node_modules/hippie/node_modules/request/request.js:873:14)
at Request.EventEmitter.emit (events.js:117:20)
at IncomingMessage.<anonymous> (/Users/terrychen/Desktop/Git/ControlPanel/node_modules/hippie/node_modules/request/request.js:824:12)
at IncomingMessage.EventEmitter.emit (events.js:117:20)
at _stream_readable.js:920:16
While I am just executing a simple script with hippie API testing module:
var hippie = require('hippie');
hippie()
.json().get('https://api.github.com/users/vesln')
.expectStatus(200)
.end(function(err, res, body) {
if (err) throw err;
});
Any idea why this is happening? Appreciate your answers!

The issue here is that at some point hippie expects the API to be returning JSON to be parsed. And you probably manually checked that URL and saw it was JSON. But this type of error is an indication of bad input into JSON.parse. Commonly you'll see unexpected token u when undefined is passed in.
First step in debugging I took was putting console.log(arguments) before if(err.. while actually only interested in the contents of the res object, it reveals GitHub actually returned an error here.
{
...,
body: 'Request forbidden by administrative rules. Please make sure your request has a User-Agent header (http://developer.github.com/v3/#user-agent-required). Check https://developer.github.com for other possible causes.' }
}
And this is the R of unexpected token, this is not valid JSON. And as the message states, the missing User-Agent header is the likeliest cause.
This code works.
var hippie = require('hippie');
hippie()
.header("user-agent", "derpbot")
.json().get('https://api.github.com/users/vesln')
.expectStatus(200)
.end(function(err, res, body) {
if (err) throw err;
});

Related

Duplicate Content-Length with Axios running in NodeJS/JEST

I face really weird problem with Axios / nanoexpress. I started to write JEST test and copied working piece of code from Vuex that calls my backend. This code works reliably in Vue but here it fails with a network error. The Axios version is the same on both SPA and JEST test.
JEST:
let response = await axios.get(`${API}/users/1234`, getAuthHeader());
function getAuthHeader() {
const config = { headers: { } };
config.headers.Authorization = "bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiIxZTQwdjBiMWo1Iiwibmlja25hbWUiOiJsaXRlcmFrbCIsInB3ZFRpbWVzdGFtcCI6IjIwMjAtMDMtMjJUMTE6MTA6NDkuNDg2WiIsInJvbGVzIjpbImFkbWluOnBvbGwiXSwiaWF0IjoxNTg2NjkwNzc2LCJleHAiOjE1ODkzNjkxNzZ9.N5MfpZ9i9Sjv-izdYItR4gXCmzVkqkuVcVSEL_6Q89c";
return config;
}
When I remove the config with Authorization header, the code works well:
let response = await axios.get(`${API}/users/1234`, getAuthHeader());
This is the error:
Network Error
at createError (node_modules/axios/lib/core/createError.js:16:15)
at XMLHttpRequest.handleError (node_modules/axios/lib/adapters/xhr.js:83:14)
at XMLHttpRequest.<anonymous> (node_modules/jsdom/lib/jsdom/living/helpers/create-event-accessor.js:33:32)
at innerInvokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:316:27)
at invokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:267:3)
at XMLHttpRequestEventTargetImpl._dispatch (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:214:9)
at fireAnEvent (node_modules/jsdom/lib/jsdom/living/helpers/events.js:17:36)
at requestErrorSteps (node_modules/jsdom/lib/jsdom/living/xhr-utils.js:121:3)
at Object.dispatchError (node_modules/jsdom/lib/jsdom/living/xhr-utils.js:51:3)
at EventEmitter.<anonymous> (node_modules/jsdom/lib/jsdom/living/xmlhttprequest.js:675:20)
at Request.<anonymous> (node_modules/jsdom/lib/jsdom/living/xhr-utils.js:384:47)
at Request.onRequestError (node_modules/request/request.js:877:8)
console.error node_modules/jsdom/lib/jsdom/virtual-console.js:29
Error: Error: Parse Error: Duplicate Content-Length
at Object.dispatchError (C:\Users\leos\WebstormProjects\nano-options\node_modules\jsdom\lib\jsdom\living\xhr-utils.js:54:19)
at EventEmitter.<anonymous> (C:\Users\leos\WebstormProjects\nano-options\node_modules\jsdom\lib\jsdom\living\xmlhttprequest.js:675:20)
at EventEmitter.emit (events.js:327:22)
at Request.<anonymous> (C:\Users\leos\WebstormProjects\nano-options\node_modules\jsdom\lib\jsdom\living\xhr-utils.js:384:47)
at Request.emit (events.js:315:20)
at Request.onRequestError (C:\Users\leos\WebstormProjects\nano-options\node_modules\request\request.js:877:8)
at ClientRequest.emit (events.js:315:20)
at Socket.socketOnData (_http_client.js:486:9)
at Socket.emit (events.js:315:20)
at addChunk (_stream_readable.js:297:12) undefined
The service is nothing fancy and it is never called when Authorization header is present and it is called when the Authorization header is missing.
app.get('/v1/users/:userId', async (req, res) => {
console.log("getUser handler starts");
const response = {};
res.send(response);
return res;
});
I have spent several hours trying to see the raw network communication but failed. It must be something with Axios because I can run successfuly exactly the same request with the Authorization header from Postman.
Update:
it seems to be related to NodeJS version. I submitted an issue: https://github.com/axios/axios/issues/2889
Update 2:
I switched from Axios to Got and the test is working properly. https://github.com/literakl/mezinamiridici/commit/e667c5661429fc8cba273716dfced2244e211abf

Cloud Functions 400 Bad Request with invalid JSON in hello world app

I have hello world cloud functions app, it's working fine either locally by firebase serve or online after firebase deploy
const functions = require('firebase-functions');
exports.helloWorld = functions.https.onRequest((request, response) => {
response.send("Hello from Firebase!");
});
Locally I can open http://localhost:5000/testing-98b0b/us-central1/helloWorld without any issues, but if I use postman to send post call with an invalid body like "#" it crashes and keep loading with below error:
error: { SyntaxError: Unexpected token # in JSON at position 0
at JSON.parse (<anonymous>)
at createStrictSyntaxError (/usr/local/lib/node_modules/firebase-tools/node_modules/body-parser/lib/types/json.js:158:10)
at parse (/usr/local/lib/node_modules/firebase-tools/node_modules/body-parser/lib/types/json.js:83:15)
at /usr/local/lib/node_modules/firebase-tools/node_modules/body-parser/lib/read.js:121:18
at invokeCallback (/usr/local/lib/node_modules/firebase-tools/node_modules/raw-body/index.js:224:16)
at done (/usr/local/lib/node_modules/firebase-tools/node_modules/raw-body/index.js:213:7)
at IncomingMessage.onEnd (/usr/local/lib/node_modules/firebase-tools/node_modules/raw-body/index.js:273:7)
at IncomingMessage.emit (events.js:182:13)
at endReadableNT (_stream_readable.js:1094:12)
at process._tickCallback (internal/process/next_tick.js:63:19)
expose: true,
statusCode: 400,
status: 400,
body: '#',
type: 'entity.parse.failed' }
Also after firebase deploy I can open
https://us-central1-staff-testing-98b0b.cloudfunctions.net/helloWorld
without any issues but if I use postman to send post call with an invalid body like "#" it crashes and returns 400 bad request with below error:
SyntaxError: Unexpected token # in JSON at position 0
at Object.parse (native)
at createStrictSyntaxError (/var/tmp/worker/node_modules/body-parser/lib/types/json.js:157:10)
at parse (/var/tmp/worker/node_modules/body-parser/lib/types/json.js:83:15)
at /var/tmp/worker/node_modules/body-parser/lib/read.js:121:18
at invokeCallback (/var/tmp/worker/node_modules/raw-body/index.js:224:16)
at done (/var/tmp/worker/node_modules/raw-body/index.js:213:7)
at IncomingMessage.onEnd (/var/tmp/worker/node_modules/raw-body/index.js:273:7)
at emitNone (events.js:86:13)
at IncomingMessage.emit (events.js:185:7)
at endReadableNT (_stream_readable.js:974:12)
Is it bug in the firebase-functions library? Is there any way to handle this type of invalid requests?

Workaround from client side for invalid HTTP response headers that contain both Transfer-Encoding and Content-Length?Can see response using Postman

I'm calling an API that returns 5 keys in the header including Transfer-encoding:chunked and Content-Length values, in the header.
According to stackoverflow question, and this below, this is illegal:
"...Node.js server returns a parse error with code HPE_UNEXPECTED_CONTENT_LENGTH when consuming the endpoint, because the response headers contains both Transfer-encoding:chunked and Content-Length values.
This is considered has an error as specified in RFC 7230 section 3.3.3.3 :
If a message is received with both a Transfer-Encoding and a Content-Length header field, the Transfer-Encoding overrides the Content-Length. Such a message might indicate an attempt to perform request smuggling (Section 9.5) or response splitting (Section 9.4) and ought to be handled as an error. A sender MUST remove the received Content-Length field prior to forwarding such a message downstream." (1)
I'm using node.js and npm-request module to send the request and try and parse the response. The function being called is
function createPostAPI(req, res, userid, detailText, title, location, custImpact){
var myJSONObject = {
"userId" : userid,
"apiKey" : "{API-Key}",
"detail" : {
"detailText" : detailText
},
"info" : {
"title":title
"location" : location,
"priority" : 0,
"customerImpact" : custImpact
}
}
request1({
url: "http://theAPIurl",
method: "POST",
body:JSON.stringify(myJSONObject)
json: true, // <--Very important!!!
body: myJSONObject
}, function (error, response, body){
console.log(error);
console.log(response);
console.log(body);
});
}
This is the error i get as expected :
{ Error: Parse Error
at Error (native)
at Socket.socketOnData (_http_client.js:362:20)
at emitOne (events.js:96:13)
at Socket.emit (events.js:188:7)
at readableAddChunk (_stream_readable.js:176:18)
at Socket.Readable.push (_stream_readable.js:134:10)
at TCP.onread (net.js:547:20) bytesParsed: 194, code: 'HPE_UNEXPECTED_CONTENT_LENGTH' }
However, I can see that the API call is working, since I can visually verify that it's working! Also using Postman I can see the response that I need!
Postman Response:
The header with the 2 headers (content-length and transfer-encoding):
The response body that I need that i can see being returned:
So finally my question is, is there anything i can do from my side (client) to avoid the error and read that http response from the server (even though the format is wrong)? How come I can see the body in Postman? Any ideas would be truly appreciated!
Using node v6.10.3
Reference:
(1) https://jira.spring.io/browse/SPR-15212

Node server is getting down with error buffer.js:488 throw new Error('toString failed');

We have an app build on nodejs (Server A), which is fetching data from another nodejs app(Server B) using REST API's.
Similarly for downloading files Server A make request on Server B and Server B fetches files from AWS S3 and pipes the data back to server A.
This system works perfectly and we are able to download files upto 1GB.
Issue is sometimes Server A crashes with below error:
buffer.js:488
throw new Error('toString failed');
^
Error: toString failed
at Buffer.toString (buffer.js:488:11)
at Request.<anonymous> (/var/www/sky/portal/node_modules/request/request.js:1145:39)
at emitOne (events.js:95:20)
at Request.emit (events.js:182:7)
at IncomingMessage.<anonymous> (/var/www/sky/portal/node_modules/request/request.js:1091:12)
at IncomingMessage.g (events.js:273:16)
at emitNone (events.js:85:20)
at IncomingMessage.emit (events.js:179:7)
at endReadableNT (_stream_readable.js:913:12)
at _combinedTickCallback (internal/process/next_tick.js:74:11)
at process._tickCallback (internal/process/next_tick.js:98:9)
Server A is calling server B using below code:
exports.downloadAsset = function(req, res, assetUrl, cb) {
res.cookie('fileDownload', 'true');
request(
config.api.baseUrl + assetUrl
,
function(error, response, body) {
}
).pipe(res);
}
We are not sure from where app is getting crashed.
Please suggest.
The Solution I used to sort above issue:
I had to modify our flow. We were streaming data from Server B to Server A, but now Server B is sending signed URL to Server A and file is being downloaded directly from S3 using that signed url.

Creating REST API using nodejs for use with contentBlocks (createjs.org)

My question here is pretty specific but struggling with how to setup a REST find call to be used with the contentBlocks NodeJS plugin (https://github.com/primaryobjects/contentblocks).
My contentBlock paths are setup as follows:
var contentBlocks = require('contentblocks')(
{
app: app,
host: 'localhost',
pathFind: '/content/find?q={"#subject":"[id]"}',
pathPost: '/content',
pathPut: '/content/[id]',
pathDelete: '/content/[id]'
});
My Route is setup as:
router.get('/content/find?q={"#subject":"[id]"}', content.find);
Which maps to content.js:
exports.find = function(req, res) {
res.json("[]");
}
When I execute, I keep getting the following error when the page is accessed:
GET /content/find?q={"#subject":"<homePage_description>"} 404 275.193 ms - 3986
undefined:1
<!DOCTYPE html><html><head><title></title><link rel="stylesheet" href="/styles
^
SyntaxError: Unexpected token <
at Object.parse (native)
at c:\dev\camsc\node_modules\contentblocks\lib\managers\WebManager.js:19:42
at IncomingMessage.<anonymous> (c:\dev\camsc\node_modules\contentblocks\node_modules\e
asypost\lib\easypost.js:19:13)
at IncomingMessage.emit (events.js:117:20)
at _stream_readable.js:943:16
at process._tickCallback (node.js:419:13)
And my view is as follows:
block content
h1= title
#homeContentBlock(about='homePage_description')
div(property='content')
p.
Some text here...
I think the issues is from the '<' in the find request that is being passed, but this is part of how the contentBlocks package passes the data so not sure how to encode that data coming in.
Any help is greatly appreciated.
I figured out what I was doing wrong here. I had my route setup incorrectly:
router.get('/content/find?q={"#subject":"[id]"}', content.find);
Should be simply:
router.get('/content/find', content.find);
This now gets routed correctly.

Resources