Hi I am trying to get a response via a http using the callback method. But I get a lot of information but not my data :
Request {
domain: null,
_events:
{ error: [Function: bound ],
complete: [Function: bound ],
pipe: [Function] },
_eventsCount: 3,
_maxListeners: undefined,
uri:
Url {
protocol: 'http:',
slashes: true,
auth: null,
host: 'localhost',
port: 80,
hostname: 'localhost',
hash: null,
search: '?filter=route_short_name',
query: 'filter=route_short_name',
pathname: '/php-rest/api.php/routes',
path: '/php-rest/api.php/routes?filter=route_short_name',
href: 'http://localhost/php-rest/api.php/routes?filter=route_short_name' },
callback: [Function],
readable: true,
writable: true,
_qs:
Querystring {
request: [Circular],
lib: { formats: [Object], parse: [Function], stringify: [Function] },
useQuerystring: undefined,
parseOptions: {},
stringifyOptions: {} },
_auth:
Auth {
request: [Circular],
hasAuth: false,
sentAuth: false,
bearerToken: null,
user: null,
pass: null },
_oauth: OAuth { request: [Circular], params: null },
_multipart:
Multipart {
request: [Circular],
boundary: '9ab5d31f-9896-4fb9-8f89-47e5501e9342',
chunked: false,
body: null },
_redirect:
Redirect {
request: [Circular],
followRedirect: true,
followRedirects: true,
followAllRedirects: false,
followOriginalHttpMethod: false,
allowRedirect: [Function],
maxRedirects: 10,
redirects: [],
redirectsFollowed: 0,
removeRefererHeader: false },
_tunnel:
Tunnel {
request: [Circular],
proxyHeaderWhiteList:
[ 'accept',
'accept-charset',
'accept-encoding',
'accept-language',
'accept-ranges',
'cache-control',
'content-encoding',
'content-language',
'content-location',
'content-md5',
'content-range',
'content-type',
'connection',
'date',
'expect',
'max-forwards',
'pragma',
'referer',
'te',
'user-agent',
'via' ],
proxyHeaderExclusiveList: [] },
headers: { host: 'localhost' },
setHeader: [Function],
hasHeader: [Function],
getHeader: [Function],
removeHeader: [Function],
method: 'GET',
localAddress: undefined,
pool: {},
dests: [],
__isRequestRequest: true,
_callback: [Function],
proxy: null,
tunnel: false,
setHost: true,
originalCookieHeader: undefined,
_disableCookies: true,
_jar: undefined,
port: 80,
host: 'localhost',
path: '/php-rest/api.php/routes?filter=route_short_name',
httpModule:
{ IncomingMessage: { [Function: IncomingMessage] super_: [Object] },
METHODS:
[ 'ACL',
'BIND',
'CHECKOUT',
'CONNECT',
'COPY',
'DELETE',
'GET',
'HEAD',
'LINK',
'LOCK',
'M-SEARCH',
'MERGE',
'MKACTIVITY',
'MKCALENDAR',
'MKCOL',
'MOVE',
'NOTIFY',
'OPTIONS',
'PATCH',
'POST',
'PROPFIND',
'PROPPATCH',
'PURGE',
'PUT',
'REBIND',
'REPORT',
'SEARCH',
'SUBSCRIBE',
'TRACE',
'UNBIND',
'UNLINK',
'UNLOCK',
'UNSUBSCRIBE' ],
OutgoingMessage: { [Function: OutgoingMessage] super_: [Object] },
ServerResponse: { [Function: ServerResponse] super_: [Object] },
STATUS_CODES:
{ '100': 'Continue',
'101': 'Switching Protocols',
'102': 'Processing',
'200': 'OK',
'201': 'Created',
'202': 'Accepted',
'203': 'Non-Authoritative Information',
'204': 'No Content',
'205': 'Reset Content',
'206': 'Partial Content',
'207': 'Multi-Status',
'208': 'Already Reported',
'226': 'IM Used',
'300': 'Multiple Choices',
'301': 'Moved Permanently',
'302': 'Found',
'303': 'See Other',
'304': 'Not Modified',
'305': 'Use Proxy',
'307': 'Temporary Redirect',
'308': 'Permanent Redirect',
'400': 'Bad Request',
'401': 'Unauthorized',
'402': 'Payment Required',
'403': 'Forbidden',
'404': 'Not Found',
'405': 'Method Not Allowed',
'406': 'Not Acceptable',
'407': 'Proxy Authentication Required',
'408': 'Request Timeout',
'409': 'Conflict',
'410': 'Gone',
'411': 'Length Required',
'412': 'Precondition Failed',
'413': 'Payload Too Large',
'414': 'URI Too Long',
'415': 'Unsupported Media Type',
'416': 'Range Not Satisfiable',
'417': 'Expectation Failed',
'418': 'I\'m a teapot',
'421': 'Misdirected Request',
'422': 'Unprocessable Entity',
'423': 'Locked',
'424': 'Failed Dependency',
'425': 'Unordered Collection',
'426': 'Upgrade Required',
'428': 'Precondition Required',
'429': 'Too Many Requests',
'431': 'Request Header Fields Too Large',
'451': 'Unavailable For Legal Reasons',
'500': 'Internal Server Error',
'501': 'Not Implemented',
'502': 'Bad Gateway',
'503': 'Service Unavailable',
'504': 'Gateway Timeout',
'505': 'HTTP Version Not Supported',
'506': 'Variant Also Negotiates',
'507': 'Insufficient Storage',
'508': 'Loop Detected',
'509': 'Bandwidth Limit Exceeded',
'510': 'Not Extended',
'511': 'Network Authentication Required' },
Agent: { [Function: Agent] super_: [Object], defaultMaxSockets: Infinity },
globalAgent:
Agent {
domain: null,
_events: [Object],
_eventsCount: 1,
_maxListeners: undefined,
defaultPort: 80,
protocol: 'http:',
options: [Object],
requests: {},
sockets: {},
freeSockets: {},
keepAliveMsecs: 1000,
keepAlive: false,
maxSockets: Infinity,
maxFreeSockets: 256 },
ClientRequest: { [Function: ClientRequest] super_: [Object] },
request: [Function],
get: [Function],
_connectionListener: [Function: connectionListener],
Server: { [Function: Server] super_: [Object] },
createServer: [Function],
Client: [Function: deprecated],
createClient: [Function: deprecated] },
agentClass:
{ [Function: Agent]
super_:
{ [Function: EventEmitter]
EventEmitter: [Circular],
usingDomains: false,
defaultMaxListeners: [Getter/Setter],
init: [Function],
listenerCount: [Function] },
defaultMaxSockets: Infinity },
agent:
Agent {
domain: null,
_events: { free: [Function] },
_eventsCount: 1,
_maxListeners: undefined,
defaultPort: 80,
protocol: 'http:',
options: { path: null },
requests: {},
sockets: {},
freeSockets: {},
keepAliveMsecs: 1000,
keepAlive: false,
maxSockets: Infinity,
maxFreeSockets: 256 } }
My Node JS code is :
var http = require('http');
function getRoutes(callback){
var callback = request('http://localhost/php-rest/api.php/routes?filter=route_short_name', function(error, response, body, callback) {
if (!error && response.statusCode == 200) {
result = JSON.stringify(JSON.parse(body));
//console.log(result);
//res.setHeader('Content-Type', 'application/json');
//res.send(result);
return callback = result;
} else {
//res.end('Error: ' + error);
return callback = error;
}
});
return callback;
}
app.get('/getRoutes', function(req, res) {
var data = getRoutes();
console.log(data);
//res.setHeader('Content-Type', 'application/json');
res.send(data);
});
I want the callback (content of result or error).
If anyone can help me on this it would be greatly appreciated.
This is how you should write your function using callback. request module doesn't have a callback param, see here.
var http = require('http');
function getRoutes(callback){
request('http://localhost/php-rest/api.php/routes?filter=route_short_name', function(error, response, body) {
if (!error && response.statusCode == 200) {
result = JSON.stringify(JSON.parse(body));
return callback(result, false);
} else {
return callback(null, error);;
}
});
}
app.get('/getRoutes', function(req, res) {
getRoutes(function(err, data){
if(err) return res.send(err);
res.send(data);
});
});
You have issues with callback in your code. I think you should learn how to use callbacks. here is tutorial for you https://www.tutorialspoint.com/nodejs/nodejs_callbacks_concept.htm
var http = require('http');
function getRoutes(callback){
request('http://localhost/php-rest/api.php/routes?filter=route_short_name', function(error, response, body) {
if (!error && response.statusCode == 200) {
result = JSON.stringify(JSON.parse(body));
return callback(null, result);
} else {
return callback(error, null);
}
});
}
app.get('/getRoutes', function(req, res) {
getRoutes(function(err, data){
if(!err){
res.send(data);
}
else{
res.send(err);
}
});
});
You didn't do the callbacks right (oops im slow)
var request = require('request');
function getRoutes(callback){
request('http://localhost/php-rest/api.php/routes?filter=route_short_name', (error, response, body) => {
if (!error && response.statusCode == 200) {
result = JSON.stringify(JSON.parse(body));
callback(null, result);
} else {
callback(error, null);
}
});
};
app.get('/getRoutes', (req, res) => {
getRoutes(function(err, data) {
if (err) console.log('error', err)//error handling
console.log(data);
});
});
Related
I took on the role of a maintainer in an app that has this code, which uses the HERE API:
{
name: 'onEnderecoSave',
listenModel: 'ClienteEndereco',
methodsHook: ['afterSave'],
async handle (payload) {
const mapMethods = {
afterSave: async () => {
const { entity: enderecoSaved, options, models } = payload
const { ConfiguracoesGerais } = models
const { transaction } = options
try {
const cepResult = await utilitarios.buscarCep(enderecoSaved.cep)
if (cepResult.erro) {
throw new CustomError('CEP inválido! Erro ao tentar consumir os dados deste cep')
}
const { bairro, localidade, logradouro, uf } = cepResult
const enderecoBaseCep = `${logradouro} - ${bairro}, ${localidade} - ${uf}`
const configuracoesGerais = await ConfiguracoesGerais.findOne({
where: {}
})
if (!configuracoesGerais) {
throw new CustomError('Ocorreu um problema para identificar as configurações gerais do sistema')
}
const execGeoCode = (cepResult, mixinParams = {}) => {
const geoCodeParams = queryString.stringify({
country: 'Brazil',
state: cepResult.uf,
city: cepResult.localidade,
district: cepResult.uf,
postalCode: String(enderecoSaved.cep).replace(/[^\d]+/g, ''),
...(cepResult.logradouro ? { street: cepResult.logradouro } : {})
}, ';')
return request.get(`https://geocode.search.hereapi.com/v1/geocode?apiKey=${configuracoesGerais.hereApiKey}&qq=${geoCodeParams}`)
}
const { latitude, longitude } = await execGeoCode(cepResult)
.then(async ({ data: hereResult }) => {
if (!hereResult.items.length) {
const { data } = await execGeoCode({
...cepResult,
logradouro: cepResult.bairro
})
hereResult = data
if (!hereResult.items.length) {
const { data } = await execGeoCode({
...cepResult,
logradouro: undefined
})
hereResult = data
}
}
const latitude = lodash.get(hereResult, 'items["0"].position.lat')
const longitude = lodash.get(hereResult, 'items["0"].position.lng')
return { latitude, longitude }
})
if (!latitude || !longitude) {
throw new CustomError('CEP inválido! Erro ao tentar consumir os dados deste cep')
}
const { x, y } = { y: configuracoesGerais.latitudeRestaurante, x: configuracoesGerais.longitudeRestaurante }
const { data: resultRouter } = await request.get(`https://router.hereapi.com/v8/routes?destination=${latitude},${longitude}&origin=${y},${x}&return=summary&transportMode=car&apiKey=${configuracoesGerais.hereApiKey}`)
if (!resultRouter) {
throw new CustomError('CEP inválido! Erro ao tentar verificar rotas de entrega')
}
let distanceKm = lodash.get(resultRouter, 'routes[0].sections[0].summary.length', null)
if (distanceKm === null) {
throw new CustomError('CEP inválido! Erro ao tentar verificar rotas de entrega')
}
distanceKm = distanceKm / 1000 // o Here informa a distância em metros
enderecoSaved.enderecoBaseCep = enderecoBaseCep
enderecoSaved.$noCyclic = true
await enderecoSaved.update({
nomeBairroDistrito: bairro,
enderecoBaseCep,
taxaEntrega: 0,
distanciaDoRestauranteKm: distanceKm
}, {
hooks: false,
transaction
})
} catch (error) {
console.error('teste', error)
if (enderecoSaved) {
await enderecoSaved.destroy()
}
throw error
}
}
}
return mapMethods[payload.methodHook] ? mapMethods[payload.methodHook]() : null
}
And, when i make a request on the app, i get this error in return:
response: {
status: 401,
statusText: 'Unauthorized',
headers: {
'content-type': 'application/json',
date: 'Sun, 07 Aug 2022 22:50:04 GMT',
server: 'openresty',
'x-request-id': 'REQ-082dbbe9-49a8-4d03-aeeb-2e19b8107057',
'content-length': '66',
connection: 'Close'
},
config: {
adapter: [Function: httpAdapter],
transformRequest: [Object],
transformResponse: [Object],
timeout: 0,
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: -1,
validateStatus: [Function: validateStatus],
headers: [Object],
method: 'get',
url: 'https://router.hereapi.com/v8/routes?destination=-15.79931,-47.86015&origin=-15.8697718,-47.9738754&return=summary&transportMode=car&apiKey=nhtKpzL7jDCdppdqSI2G4sIeQukduxhH74b-6xPcCV8?',
data: undefined
},
request: ClientRequest {
_events: [Object: null prototype],
_eventsCount: 6,
_maxListeners: undefined,
outputData: [],
outputSize: 0,
writable: true,
_last: true,
chunkedEncoding: false,
shouldKeepAlive: false,
useChunkedEncodingByDefault: false,
sendDate: false,
_removedConnection: false,
_removedContLen: false,
_removedTE: false,
_contentLength: 0,
_hasBody: true,
_trailer: '',
finished: true,
_headerSent: true,
socket: [TLSSocket],
connection: [TLSSocket],
_header: 'GET /v8/routes?destination=-15.79931,-47.86015&origin=-15.8697718,-47.9738754&return=summary&transportMode=car&apiKey=nhtKpzL7jDCdppdqSI2G4sIeQukduxhH74b-6xPcCV8? HTTP/1.1\r\n' +
'Accept: application/json, text/plain, */*\r\n' +
'User-Agent: axios/0.18.1\r\n' +
'Host: router.hereapi.com\r\n' +
'Connection: close\r\n' +
'\r\n',
_onPendingData: [Function: noopPendingOutput],
agent: [Agent],
socketPath: undefined,
method: 'GET',
insecureHTTPParser: undefined,
path: '/v8/routes?destination=-15.79931,-47.86015&origin=-15.8697718,-47.9738754&return=summary&transportMode=car&apiKey=nhtKpzL7jDCdppdqSI2G4sIeQukduxhH74b-6xPcCV8?',
_ended: true,
res: [IncomingMessage],
aborted: false,
timeoutCb: null,
upgradeOrConnect: false,
parser: null,
maxHeadersCount: null,
reusedSocket: false,
_redirectable: [Writable],
[Symbol(kCapture)]: false,
[Symbol(kNeedDrain)]: false,
[Symbol(corked)]: 0,
[Symbol(kOutHeaders)]: [Object: null prototype]
},
data: { error: 'Unauthorized', error_description: 'Illegal API key id' }
}
}
{ error: 'Unauthorized', error_description: 'Illegal API key id' }
But, the strange thing is that, if i run a simple GET with the same URL on Insomnia:
https://router.hereapi.com/v8/routes?destination=-15.79931,-47.86015&origin=-15.8697718,-47.9738754&return=summary&transportMode=car&apiKey=t1057tOh4Vnx-OYrni_4_mnsTu-BoLVE8ckKYavow1A
It runs with no error:
enter image description here
So, what is the problem here?
Trying to send an image through GupShup. I'm using their sandbox. My backend is node.js with feathersjs.
But it's returning me this error:
Response {
size: 0,
timeout: 0,
[Symbol(Body internals)]: {
body: PassThrough {
_readableState: [ReadableState],
readable: true,
_events: [Object: null prototype],
_eventsCount: 2,
_maxListeners: undefined,
_writableState: [WritableState],
writable: false,
allowHalfOpen: true,
_transformState: [Object],
[Symbol(kCapture)]: false
},
disturbed: false,
error: null
},
[Symbol(Response internals)]: {
url: 'https://api.gupshup.io/sm/api/v1/msg',
status: 400,
statusText: 'Bad Request',
headers: Headers { [Symbol(map)]: [Object: null prototype] },
counter: 0
}
}
This is the code to send the image
const form = new URLSearchParams();
form.append('channel', 'whatsapp');
form.append('destination', destination);
form.append('source', app.get('GUPSHUP_NUMBER'));
form.append('message.payload', JSON.stringify(message));
form.append('src.name', 'OneAccess');
console.log(form);
try {
const res = await fetch('https://api.gupshup.io/sm/api/v1/msg', {
method: 'POST',
body: form,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
apikey: app.get('GUPSHUP_API'),
},
});
console.log('result message', res);
} catch (err) {
console.log('errro sending msg', err);
}
This is the message that I'm trying to send
message: {
type: 'image',
originalUrl:
'https://images.pexels.com/photos/248797/pexels-photo-248797.jpeg',
previewUrl:
'https://images.pexels.com/photos/248797/pexels-photo-248797.jpeg',
caption: 'Sample image',
},
Can anyone help me?
Change message.payload to message. You can check the correct signature at https://www.gupshup.io/developer/docs/bot-platform/guide/whatsapp-api-documentation#SendImage
Hi I am writing a unit test case of my function. this function returns a json response in case request is successful else return an error.
describe("Operations", async () => {
it("user info", async () => {
let accessToken = 'dfsf;
const result = await authConnectors.getUser(accessToken);
});
});
How to assert http error and response using chai in nodejs ?
{ Error: Unauthorized
at Request.callback (/vagrant/node_modules/superagent/lib/node/index.js:699:13)
at IncomingMessage.parser (/vagrant/node_modules/superagent/lib/node/index.js:903:18)
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._tickCallback (internal/process/next_tick.js:104:9)
status: 401,
response:
Response {
domain: null,
_events: {},
_eventsCount: 0,
_maxListeners: undefined,
res:
IncomingMessage {
_readableState: [Object],
readable: false,
domain: null,
_events: [Object],
_eventsCount: 4,
_maxListeners: undefined,
socket: [Object],
connection: [Object],
httpVersionMajor: 1,
httpVersionMinor: 1,
httpVersion: '1.1',
complete: true,
headers: [Object],
rawHeaders: [Object],
trailers: {},
rawTrailers: [],
upgrade: false,
url: '',
method: null,
statusCode: 401,
statusMessage: 'Unauthorized',
client: [Object],
_consuming: true,
_dumped: false,
req: [Object],
text: '',
read: [Function] },
request:
Request {
domain: null,
_events: {},
_eventsCount: 0,
_maxListeners: undefined,
_agent: false,
_formData: null,
method: 'GET',
url: 'https://id-dev',
_header: [Object],
header: [Object],
writable: true,
_redirects: 0,
_maxRedirects: 5,
cookies: '',
qs: {},
_query: [],
qsRaw: [],
_redirectList: [],
_streamRequest: false,
req: [Object],
protocol: 'https:',
host: 'id-dh',
_endCalled: true,
_callback: [Function],
res: [Object],
response: [Circular],
called: true },
req:
ClientRequest {
domain: null,
_events: [Object],
_eventsCount: 3,
_maxListeners: undefined,
output: [],
outputEncodings: [],
outputCallbacks: [],
outputSize: 0,
writable: true,
_last: true,
upgrading: false,
chunkedEncoding: false,
shouldKeepAlive: false,
useChunkedEncodingByDefault: false,
sendDate: false,
_removedHeader: {},
_contentLength: 0,
_hasBody: true,
_trailer: '',
finished: true,
_headerSent: true,
socket: [Object],
connection: [Object],
_header: 'GET oqcnM_4xWNbmv-WaoJ63UOjcZSHW-KrULLRUFzXrQKS6iuPWp6poHLjop1WsRtw5Y-KQCTZVI783awnn3_utEw6yqD6qpHHZwhxiPeM8mFZgN_zH4xX0ChbQ3ayao9Ms6ZHQT0X00N467HPfq5hVAW4D3a-3DURwnUvvVTIsYTShhZAsag2P26WDbKapPdgfVpjQKV-4GP--cLWbAZpEWJT3yS31YiY-VEcdfjdDU\r\nAccept: application/json\r\nConnection: close\r\n\r\n',
_headers: [Object],
_headerNames: [Object],
_onPendingData: null,
agent: [Object],
socketPath: undefined,
timeout: undefined,
method: 'GET',
path: '/userinfo',
_ended: true,
parser: null,
res: [Object] },
text: '',
body: {},
files: undefined,
buffered: true,
headers:
{ 'content-length': '0',
'strict-transport-security': 'max-age=31536000; includeSubDomains; preload',
'x-xss-protection': '1; mode=block',
'x-content-type-options': 'nosniff',
'content-security-policy': 'default-src \'self\';script-src \'self\' https://track.abc.net;style-src \'self\' \'unsafe-inline\' https://track.abc.net;img-src \'self\' https://track.abc.net;frame-src \'self\' https://track.abc.net;object-src \'none\';',
'www-authenticate': 'Bearer error="invalid_token"',
date: 'Wed, 28 Mar 2018 11:57:56 GMT',
connection: 'close' },
header:
{ 'content-length': '0',
'strict-transport-security': 'max-age=31536000; includeSubDomains; preload',
'x-xss-protection': '1; mode=block',
'x-content-type-options': 'nosniff',
'content-security-policy': 'default-src \'self\';script-src \'self\' https://track.abc.net;style-src \'self\' \'unsafe-inline\' https://track.abc.net;img-src \'self\' https://track.abc.net;frame-src \'self\' https://track.abc.net;object-src \'none\'',
'www-authenticate': 'Bearer error="invalid_token"',
date: 'Wed, 28 Mar 2018 11:57:56 GMT',
connection: 'close' },
statusCode: 401,
status: 401,
statusType: 4,
info: false,
ok: false,
redirect: false,
clientError: true,
serverError: false,
error:
{ Error: cannot GET /sts/connect/userinfo (401)
at Response.toError (/vagrant/node_modules/superagent/lib/node/response.js:94:15)
at ResponseBase._setStatusProperties (/vagrant/node_modules/superagent/lib/response-base.js:123:16)
at new Response (/vagrant/node_modules/superagent/lib/node/response.js:41:8)
at Request._emitResponse (/vagrant/node_modules/superagent/lib/node/index.js:739:20)
at IncomingMessage.parser (/vagrant/node_modules/superagent/lib/node/index.js:903:38)
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._tickCallback (internal/process/next_tick.js:104:9)
status: 401,
text: '',
method: 'GET',
path: '/sts' },
accepted: false,
noContent: false,
badRequest: false,
unauthorized: true,
notAcceptable: false,
forbidden: false,
notFound: false,
type: '',
links: {},
setEncoding: [Function: bound ],
redirects: [] } }
Using expect and should you can test as below:
describe('Testing https responses', () => {
it("user info", async (done) => {
.... request here...
.catch((err) => {
err.response.should.have.status(404);
err.response.body.should.have.property('error');
err.response.body.error.should.eql('User could not be found');
done()
});
})
it('testing using expect', (done) => {
request.get('http://localhost:8000', function (err, res, body) {
expect(res.statusCode).to.equal(400);
expect(res).to.have.property('body');
expect(res.body).to.equal('wrong header');
done();
});
});
})
These tests are asynchronous, so they need the promise to be solved at the end with done()
Edit - Added once more example
.property(name[, val[, msg]])
Asserts that the target has a property with the given key name.
expect({a: 1}).to.have.property('a');
Here three links that can be helpful:
How to properly test for HTTP failure responses
Testing HTTP Responses in Node.js
Michael Herman - Testing Node.js with Mocha and Chai
Chai Doc - method property using expect
You could use try-catch and handle errors =)
it("user info", async () => {
try{
let accessToken = 'dfsf;
const result = await authConnectors.getUser(accessToken);
} catch(e) {
// check error
}
});
I am trying to authorise my server for calling the youtube analytics api via the module "googleapis" (https://www.npmjs.com/package/googleapis). I want to use the JWT to authorise. As you can see I get a forbidden error back from the api.
I read a ton of posts and tinkered around for a whole while, but I can't figure out what is wrong.
Is my code ok? Otherwise it as to be a google cloud related issue. (E.g. I did not set up the roles properly there.)
import fs from 'fs';
import { google } from 'googleapis';
// read credentials from file
const credentialsFromFile = fs.readFileSync(`${__dirname}/../credentials.json`);
const credentials = JSON.parse(credentialsFromFile.toString());
const scopes = [
'https://www.googleapis.com/auth/youtube.readonly',
'https://www.googleapis.com/auth/yt-analytics-monetary.readonly',
'https://www.googleapis.com/auth/youtubepartner',
];
// get an authorized client
const jwtClient = new google.auth.JWT(
credentials.client_email,
null,
credentials.private_key,
scopes
);
const youtubeAnalyticsClient = google.youtubeAnalytics({
version: 'v1',
auth: jwtClient,
});
function runQuery(callback) {
youtubeAnalyticsClient.reports.query(
{
auth: jwtClient,
ids: 'channel==MINE',
'start-date': '2018-01-01',
'end-date': '2018-02-01',
metrics: 'views',
},
(error, result) => {
if (error) console.log(error.errors);
else {
console.log(result);
callback(result);
}
}
);
}
jwtClient.authorize((error, result) => {
if (error) console.log(error);
else {
/*
{ access_token: '{THE ACCESS TOKEN}',
token_type: 'Bearer',
expiry_date: 1522070090000,
refresh_token: 'jwt-placeholder' } */
console.log(result);
runQuery(() => {
// worked :)
});
}
});
The response object may be helpful:
response:
{ status: 403,
statusText: 'Forbidden',
headers:
{ vary: 'X-Origin, Origin,Accept-Encoding',
'content-type': 'application/json; charset=UTF-8',
date: 'Mon, 26 Mar 2018 10:39:33 GMT',
expires: 'Mon, 26 Mar 2018 10:39:33 GMT',
'cache-control': 'private, max-age=0',
'x-content-type-options': 'nosniff',
'x-frame-options': 'SAMEORIGIN',
'x-xss-protection': '1; mode=block',
server: 'GSE',
'alt-svc': 'hq=":443"; ma=2592000; quic=51303432; quic=51303431; quic=51303339; quic=51303335,quic=":443"; ma=2592000; v="42,41,39,35"',
'accept-ranges': 'none',
connection: 'close' },
config:
{ adapter: [Function: httpAdapter],
transformRequest: [Object],
transformResponse: [Object],
timeout: 0,
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: 2147483648,
validateStatus: [Function],
headers: [Object],
method: 'get',
url: 'https://www.googleapis.com/youtube/analytics/v1/reports',
paramsSerializer: [Function],
data: undefined,
params: [Object] },
request:
ClientRequest {
domain: null,
_events: [Object],
_eventsCount: 6,
_maxListeners: undefined,
output: [],
outputEncodings: [],
outputCallbacks: [],
outputSize: 0,
writable: false,
_last: true,
upgrading: false,
chunkedEncoding: false,
shouldKeepAlive: false,
useChunkedEncodingByDefault: false,
sendDate: false,
_removedConnection: false,
_removedContLen: false,
_removedTE: false,
_contentLength: 0,
_hasBody: true,
_trailer: '',
finished: true,
_headerSent: true,
socket: [Object],
connection: [Object],
_header: 'GET /youtube/analytics/v1/reports?ids=channel%3D%3DMINE&start-date=2018-01-01&end-date=2018-02-01&metrics=views HTTP/1.1\r\nAccept: application/json, text/plain, */*\r\nAuthorization: Bearer ya29.c.El6KBUokXWf8yjN1LXk04b3FTGa1jadNEmvbyLBQfVmK9KIbxwxA6e88m_OujuTcyrJW60ojwnKiNfH-9E2iegmwlDOdKI8VxORrniGIt9gc_FGp2tvi2GLabzTri74b\r\nUser-Agent: google-api-nodejs-client/1.3.2\r\nHost: www.googleapis.com\r\nConnection: close\r\n\r\n',
_onPendingData: [Function: noopPendingOutput],
agent: [Object],
socketPath: undefined,
timeout: undefined,
method: 'GET',
path: '/youtube/analytics/v1/reports?ids=channel%3D%3DMINE&start-date=2018-01-01&end-date=2018-02-01&metrics=views',
_ended: true,
res: [Object],
aborted: undefined,
timeoutCb: null,
upgradeOrConnect: false,
parser: null,
maxHeadersCount: null,
_redirectable: [Object],
[Symbol(outHeadersKey)]: [Object] },
data: { error: [Object] } },
code: 403,
errors: [ { domain: 'global', reason: 'forbidden', message: 'Forbidden' } ] }
Update 1
I updated the code a little, so that is analog to this example implementation: https://github.com/google/google-api-nodejs-client/blob/HEAD/samples/jwt.js
I get an authorised client as seen in the code, but the same error occurs. I am pretty sure I messed up the settings in the google cloud settings. Is it necessary to do the domain verification at google cloud when developing locally?
Update 2
Even with OAuth2 Authentication (passing a code as cli arg after allowing scopes in the browser) I get the forbidden-error. Seems like I need to enable it in the cloud dev console, but how do I do that?
I'm pretty new in Node.js and I have this project. Basically I have some data sits in a mongoDB collection("data") and I'm trying to get that data and display it on the browser.
Here is what I've got so far;
var MongoClient = require('mongodb').MongoClient
,format = require('util').format;
var sys = require ("sys");
my_http = require("http");
my_http.createServer(function(request, response){
sys.puts("Touched !!");
response.writeHeader(200, {"Content-Type": "text/plain"});
response.write(extractData()).toString();
response.end();
}).listen(8080);
sys.puts("Server is running on 8080"); // Server kicks in...np
function extractData(){
MongoClient.connect('mongodb://127.0.0.1:27017/mongoDB', function(err, db){
if (err){
console.log("Can't Connect to DB !!");
}else {
console.log("Connected to DB !!"); // connects to DB, np
db.data.find({}, function(err, data){ // .find is the problem
if (err || !data) console.log("No Data Found");
else data.forEach(function (data){
console.log(data);
});
}).toArray();
}
});
}
And after I run "node server.js" and refresh the already open localhost:8080, I get this;
Server is running on 8080
Touched !!
Touched !!
Connected to DB !!
d:\Projects\SCRIPTS\mdp.scripts.testing-tools\jsFinderWmongoDB\node_modules\mongodb\lib\mongodb\mongo_client.js:475
throw err
^
TypeError: Cannot call method 'find' of undefined
at d:\Projects\SCRIPTS\mdp.scripts.testing-tools\jsFinderWmongoDB\server.js:21:21
at d:\Projects\SCRIPTS\mdp.scripts.testing-tools\jsFinderWmongoDB\node_modules\mongodb\lib\mongodb\mongo_client.js:4
72:11
at process._tickCallback (node.js:415:13)
Don't understand why there is a problem with .find() and of course can't display any data...
Any ideas?
Edit:
Well, we are certainly getting somewhere. I've made some changes.
Current code:
function extractData(){
MongoClient.connect('mongodb://127.0.0.1:27017/mongoDB', function(err, db){
if (err){
console.log("Can't Connect to DB !!");
}else {
sys.puts("Connected to DB !!"); // connects to DB, np
db.collection('data').find({}, function(err, data){
if (err || !data) console.log("No Data Found");
//else db.collection('data').forEach(function (data){
// console.log(data);
//});
});//.toArray();
}
});
}
Browser response is "undefined"
I'm guessing "extractData" function is NOT returning something legit. Therefore the collection set "data" is returning empty.
And yes I've checked one more time, I have data in the dataset.
You need to set a collection to use before you can do anything with it.
var collection = db.collection('data');
collection.find({},function(err,data){
console.log(data);
});
Would be how you do it.
Update ** This was how I did my first mongoDB stuff using express
Might help you.
var mongo = require('mongodb');
var monk = require('monk');
var db = monk('localhost:27017/nodetest1');
app.get('/userlist', function(req, res) {
var db = req.db;
var collection = db.get('usercollection');
collection.find({},{},function(e,docs){
res.render('userlist', {
"userlist" : docs
});
});
});
I get the details about the stored data when do console.log(data);
Here is a glimpse of it
Server is running on 8080
Touched !!
Connected to DB !!
{ db:
{ domain: null,
_events: {},
_maxListeners: 10,
databaseName: 'mongoDB',
serverConfig:
{ domain: null,
_events: {},
_maxListeners: 10,
auth: [Getter],
_callBackStore: [Object],
_commandsStore: [Object],
_dbStore: [Object],
host: '127.0.0.1',
port: 27017,
options: [Object],
internalMaster: true,
connected: true,
poolSize: 5,
disableDriverBSONSizeCheck: false,
_used: true,
replicasetInstance: null,
emitOpen: false,
ssl: false,
sslValidate: false,
sslCA: null,
sslCert: undefined,
sslKey: undefined,
sslPass: undefined,
serverCapabilities: [Object],
name: '127.0.0.1:27017',
socketOptions: [Object],
logger: [Object],
eventHandlers: [Object],
_serverState: 'connected',
_state: [Object],
recordQueryStats: false,
socketTimeoutMS: [Getter/Setter],
_readPreference: [Object],
db: [Circular],
dbInstances: [Object],
connectionPool: [Object],
isMasterDoc: [Object] },
options:
{ read_preference_tags: null,
read_preference: 'primary',
url: 'mongodb://127.0.0.1:27017/mongoDB',
native_parser: true,
readPreference: [Object],
safe: false,
w: 1 },
_applicationClosed: false,
slaveOk: false,
bufferMaxEntries: -1,
native_parser: true,
bsonLib:
{ BSON: [Object],
Long: [Object],
ObjectID: [Object],
DBRef: [Object],
Code: [Object],
Timestamp: [Object],
Binary: [Object],
Double: [Object],
MaxKey: [Object],
MinKey: [Object],
Symbol: [Object] },
bson: { promoteLongs: true },
bson_deserializer:
{ Code: [Object],
Symbol: [Object],
BSON: [Object],
DBRef: [Object],
Binary: [Object],
ObjectID: [Object],
Long: [Object],
Timestamp: [Object],
Double: [Object],
MinKey: [Object],
MaxKey: [Object],
promoteLongs: true },
bson_serializer:
{ Code: [Object],
Symbol: [Object],
BSON: [Object],
DBRef: [Object],
Binary: [Object],
ObjectID: [Object],
Long: [Object],
Timestamp: [Object],
Double: [Object],
MinKey: [Object],
MaxKey: [Object],
promoteLongs: true },
_state: 'connected',
pkFactory:
{ [Function: ObjectID]
index: 16043018,
createPk: [Function: createPk],
createFromTime: [Function: createFromTime],
createFromHexString: [Function: createFromHexString],
isValid: [Function: isValid],
ObjectID: [Circular],
ObjectId: [Circular] },
forceServerObjectId: false,
safe: false,
notReplied: {},
isInitializing: true,
openCalled: true,
commands: [],
logger: { error: [Function], log: [Function], debug: [Function] },
tag: 1425061857066,
eventHandlers:
{ error: [],
parseError: [],
poolReady: [],
message: [],
close: [] },
serializeFunctions: false,
raw: false,
recordQueryStats: false,
retryMiliSeconds: 1000,
numberOfRetries: 60,
readPreference: { _type: 'ReadPreference', mode: 'primary', tags: undefined } },
collection: