Unhandled rejection at promise with feathersjs oauth call - node.js

I'm trying to create a frontend Vue(x) app with feathers-vuex and a backend feathers API using only oauth for authentication.
If I hit the backend directly on localhost:3030/oauth/google then the right flow and re-directs occur with google and I end up back at localhost:8080/#/access_token=ey.... with a valid jwt so the oauth config seems fine on the backend and with the oauth configuration at google. The configuration is..
"oauth": {
"redirect": "http://localhost:8080/",
"google": {
"key": "GOOGLE_CLIENT_KEY",
"secret": "GOOGLE_CLIENT_SECRET",
"scope": [
"email",
"profile",
"openid"
]
}
}
However, from my front end app running on localhost:8080 when I click something that invokes the login method..
login() {
this.$store.dispatch('auth/authenticate', {strategy: 'google'})
}
.. I get a rejected promise on the backend. With DEBUG=feathers*,#feathersjs* I see the following output:
#feathersjs/transport-commons Got 'create' call for service 'authentication' +0ms
#feathersjs/transport-commons Running method 'create' on service 'authentication' {
provider: 'socketio',
headers: {
host: 'localhost:3030',
connection: 'Upgrade',
pragma: 'no-cache',
'cache-control': 'no-cache',
'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.79 Safari/537.36',
upgrade: 'websocket',
origin: 'http://localhost:8080',
'sec-websocket-version': '13',
'accept-encoding': 'gzip, deflate, br',
'accept-language': 'en-GB,en-US;q=0.9,en;q=0.8',
cookie: 'connect.sid=s%3ACZWmOVc_1gtoJwDYsb0kvJ7vx06U-Rmd.jbQnNQL1GlFLWsJzyDP312ALpnI32mmYK7BIRka9Ro4',
'sec-websocket-key': 'umfZAU0K/7k+sKUg1A/wvA==',
'sec-websocket-extensions': 'permessage-deflate; client_max_window_bits'
}
} [ { strategy: 'google' }, {}, [Function] ] +0ms
#feathersjs/authentication/base Running authenticate for strategy google [ 'jwt', 'google' ] +16s
#feathersjs/authentication-oauth/strategy getProfile of oAuth profile from grant-profile with { strategy: 'google' } +0ms
#feathersjs/transport-commons Error in method 'create' on service 'authentication' Error: 401 Unauthorized
at module.exports (/home/darren/projects/stbgfc/develop/admin-api/node_modules/request-compose/utils/error.js:3:15)
at /home/darren/projects/stbgfc/develop/admin-api/node_modules/request-compose/response/status.js:11:11
at processTicksAndRejections (internal/process/task_queues.js:93:5) {
message: '401 Unauthorized',
res: IncomingMessage {
_readableState: ReadableState {
objectMode: false,
highWaterMark: 16384,
buffer: BufferList { head: null, tail: null, length: 0 },
length: 0,
pipes: null,
pipesCount: 0,
flowing: true,
ended: true,
endEmitted: true,
reading: false,
sync: false,
needReadable: false,
emittedReadable: false,
readableListening: false,
resumeScheduled: false,
paused: false,
emitClose: true,
autoDestroy: false,
destroyed: false,
defaultEncoding: 'utf8',
awaitDrain: 0,
readingMore: false,
decoder: null,
encoding: null
},
readable: false,
_events: [Object: null prototype] {
end: [Array],
data: [Function],
error: [Function]
},
_eventsCount: 3,
_maxListeners: undefined,
socket: TLSSocket {
_tlsOptions: [Object],
_secureEstablished: true,
_securePending: false,
_newSessionPending: false,
_controlReleased: true,
_SNICallback: null,
servername: 'openidconnect.googleapis.com',
alpnProtocol: false,
authorized: true,
authorizationError: null,
encrypted: true,
_events: [Object: null prototype],
_eventsCount: 11,
connecting: false,
_hadError: false,
_parent: null,
_host: 'openidconnect.googleapis.com',
_readableState: [ReadableState],
readable: false,
_maxListeners: undefined,
_writableState: [WritableState],
writable: false,
allowHalfOpen: false,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: undefined,
_server: null,
ssl: null,
_requestCert: true,
_rejectUnauthorized: true,
timeout: 5000,
parser: null,
_httpMessage: [ClientRequest],
write: [Function: writeAfterFIN],
[Symbol(res)]: [TLSWrap],
[Symbol(asyncId)]: 125,
[Symbol(kHandle)]: null,
[Symbol(lastWriteQueueSize)]: 0,
[Symbol(timeout)]: Timeout {
_idleTimeout: -1,
_idlePrev: null,
_idleNext: null,
_idleStart: 19758,
_onTimeout: null,
_timerArgs: undefined,
_repeat: null,
_destroyed: true,
[Symbol(refed)]: null,
[Symbol(asyncId)]: 135,
[Symbol(triggerId)]: 133
},
[Symbol(kBuffer)]: null,
[Symbol(kBufferCb)]: null,
[Symbol(kBufferGen)]: null,
[Symbol(kBytesRead)]: 689,
[Symbol(kBytesWritten)]: 150,
[Symbol(connect-options)]: [Object]
},
connection: TLSSocket {
_tlsOptions: [Object],
_secureEstablished: true,
_securePending: false,
_newSessionPending: false,
_controlReleased: true,
_SNICallback: null,
servername: 'openidconnect.googleapis.com',
alpnProtocol: false,
authorized: true,
authorizationError: null,
encrypted: true,
_events: [Object: null prototype],
_eventsCount: 11,
connecting: false,
_hadError: false,
_parent: null,
_host: 'openidconnect.googleapis.com',
_readableState: [ReadableState],
readable: false,
_maxListeners: undefined,
_writableState: [WritableState],
writable: false,
allowHalfOpen: false,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: undefined,
_server: null,
ssl: null,
_requestCert: true,
_rejectUnauthorized: true,
timeout: 5000,
parser: null,
_httpMessage: [ClientRequest],
write: [Function: writeAfterFIN],
[Symbol(res)]: [TLSWrap],
[Symbol(asyncId)]: 125,
[Symbol(kHandle)]: null,
[Symbol(lastWriteQueueSize)]: 0,
[Symbol(timeout)]: Timeout {
_idleTimeout: -1,
_idlePrev: null,
_idleNext: null,
_idleStart: 19758,
_onTimeout: null,
_timerArgs: undefined,
_repeat: null,
_destroyed: true,
[Symbol(refed)]: null,
[Symbol(asyncId)]: 135,
[Symbol(triggerId)]: 133
},
[Symbol(kBuffer)]: null,
[Symbol(kBufferCb)]: null,
[Symbol(kBufferGen)]: null,
[Symbol(kBytesRead)]: 689,
[Symbol(kBytesWritten)]: 150,
[Symbol(connect-options)]: [Object]
},
httpVersionMajor: 1,
httpVersionMinor: 1,
httpVersion: '1.1',
complete: true,
headers: {
pragma: 'no-cache',
date: 'Thu, 02 Jan 2020 22:13:43 GMT',
'cache-control': 'no-cache, no-store, max-age=0, must-revalidate',
expires: 'Mon, 01 Jan 1990 00:00:00 GMT',
'content-type': 'application/json; charset=utf-8',
vary: 'X-Origin, Referer, Origin,Accept-Encoding',
server: 'ESF',
'x-xss-protection': '0',
'x-frame-options': 'SAMEORIGIN',
'x-content-type-options': 'nosniff',
'alt-svc': 'quic=":443"; ma=2592000; v="46,43",h3-Q050=":443"; ma=2592000,h3-Q049=":443"; ma=2592000,h3-Q048=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000',
'accept-ranges': 'none',
connection: 'close'
},
rawHeaders: [
'Pragma',
'no-cache',
'Date',
'Thu, 02 Jan 2020 22:13:43 GMT',
'Cache-Control',
'no-cache, no-store, max-age=0, must-revalidate',
'Expires',
'Mon, 01 Jan 1990 00:00:00 GMT',
'Content-Type',
'application/json; charset=utf-8',
'Vary',
'X-Origin',
'Vary',
'Referer',
'Server',
'ESF',
'X-XSS-Protection',
'0',
'X-Frame-Options',
'SAMEORIGIN',
'X-Content-Type-Options',
'nosniff',
'Alt-Svc',
'quic=":443"; ma=2592000; v="46,43",h3-Q050=":443"; ma=2592000,h3-Q049=":443"; ma=2592000,h3-Q048=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000',
'Accept-Ranges',
'none',
'Vary',
'Origin,Accept-Encoding',
'Connection',
'close'
],
trailers: {},
rawTrailers: [],
aborted: false,
upgrade: false,
url: '',
method: null,
statusCode: 401,
statusMessage: 'Unauthorized',
client: TLSSocket {
_tlsOptions: [Object],
_secureEstablished: true,
_securePending: false,
_newSessionPending: false,
_controlReleased: true,
_SNICallback: null,
servername: 'openidconnect.googleapis.com',
alpnProtocol: false,
authorized: true,
authorizationError: null,
encrypted: true,
_events: [Object: null prototype],
_eventsCount: 11,
connecting: false,
_hadError: false,
_parent: null,
_host: 'openidconnect.googleapis.com',
_readableState: [ReadableState],
readable: false,
_maxListeners: undefined,
_writableState: [WritableState],
writable: false,
allowHalfOpen: false,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: undefined,
_server: null,
ssl: null,
_requestCert: true,
_rejectUnauthorized: true,
timeout: 5000,
parser: null,
_httpMessage: [ClientRequest],
write: [Function: writeAfterFIN],
[Symbol(res)]: [TLSWrap],
[Symbol(asyncId)]: 125,
[Symbol(kHandle)]: null,
[Symbol(lastWriteQueueSize)]: 0,
[Symbol(timeout)]: Timeout {
_idleTimeout: -1,
_idlePrev: null,
_idleNext: null,
_idleStart: 19758,
_onTimeout: null,
_timerArgs: undefined,
_repeat: null,
_destroyed: true,
[Symbol(refed)]: null,
[Symbol(asyncId)]: 135,
[Symbol(triggerId)]: 133
},
[Symbol(kBuffer)]: null,
[Symbol(kBufferCb)]: null,
[Symbol(kBufferGen)]: null,
[Symbol(kBytesRead)]: 689,
[Symbol(kBytesWritten)]: 150,
[Symbol(connect-options)]: [Object]
},
_consuming: true,
_dumped: false,
req: ClientRequest {
_events: [Object: null prototype],
_eventsCount: 5,
_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 /v1/userinfo HTTP/1.1\r\n' +
'user-agent: grant-profile 0.0.8\r\n' +
'authorization: Bearer undefined\r\n' +
'Host: openidconnect.googleapis.com\r\n' +
'Connection: close\r\n' +
'\r\n',
_onPendingData: [Function: noopPendingOutput],
agent: [Agent],
socketPath: undefined,
timeout: 5000,
method: 'GET',
path: '/v1/userinfo',
_ended: true,
res: [Circular],
aborted: false,
timeoutCb: [Function: emitRequestTimeout],
upgradeOrConnect: false,
parser: null,
maxHeadersCount: null,
[Symbol(kNeedDrain)]: false,
[Symbol(isCorked)]: false,
[Symbol(kOutHeaders)]: [Object: null prototype]
}
},
body: {
error: 'invalid_request',
error_description: 'Invalid Credentials'
},
raw: '{\n' +
' "error": "invalid_request",\n' +
' "error_description": "Invalid Credentials"\n' +
'}',
hook: {
type: 'before',
arguments: [ [Object], [Object] ],
service: {
app: [EventEmitter],
strategies: [Object],
configKey: 'authentication',
create: [Function: newMethod],
remove: [Function: newMethod],
methods: [Object],
hooks: [Function: hooks],
_events: [Object: null prototype],
_eventsCount: 2,
_maxListeners: undefined,
setMaxListeners: [Function: setMaxListeners],
getMaxListeners: [Function: getMaxListeners],
emit: [Function: emit],
addListener: [Function: addListener],
on: [Function: addListener],
prependListener: [Function: prependListener],
once: [Function: once],
prependOnceListener: [Function: prependOnceListener],
removeListener: [Function: removeListener],
off: [Function: removeListener],
removeAllListeners: [Function: removeAllListeners],
listeners: [Function: listeners],
rawListeners: [Function: rawListeners],
listenerCount: [Function: listenerCount],
eventNames: [Function: eventNames],
publish: [Function: publish],
registerPublisher: [Function: registerPublisher],
_super: undefined,
[Symbol(#feathersjs/transport-commons/publishers)]: [Object]
},
app: [Function: app] EventEmitter {
_events: [Object: null prototype],
_eventsCount: 6,
_maxListeners: undefined,
setMaxListeners: [Function: setMaxListeners],
getMaxListeners: [Function: getMaxListeners],
emit: [Function: emit],
addListener: [Function: addListener],
on: [Function: addListener],
prependListener: [Function: prependListener],
once: [Function: once],
prependOnceListener: [Function: prependOnceListener],
removeListener: [Function: removeListener],
off: [Function: removeListener],
removeAllListeners: [Function: removeAllListeners],
listeners: [Function: listeners],
rawListeners: [Function: rawListeners],
listenerCount: [Function: listenerCount],
eventNames: [Function: eventNames],
init: [Function: init],
defaultConfiguration: [Function: defaultConfiguration],
lazyrouter: [Function: lazyrouter],
handle: [Function: handle],
use: [Function: newMethod],
route: [Function: route],
engine: [Function: engine],
param: [Function: param],
set: [Function: set],
path: [Function: path],
enabled: [Function: enabled],
disabled: [Function: disabled],
enable: [Function: enable],
disable: [Function: disable],
acl: [Function],
bind: [Function],
checkout: [Function],
connect: [Function],
copy: [Function],
delete: [Function],
get: [Function],
head: [Function],
link: [Function],
lock: [Function],
'm-search': [Function],
merge: [Function],
mkactivity: [Function],
mkcalendar: [Function],
mkcol: [Function],
move: [Function],
notify: [Function],
options: [Function],
patch: [Function],
post: [Function],
propfind: [Function],
proppatch: [Function],
purge: [Function],
put: [Function],
rebind: [Function],
report: [Function],
search: [Function],
source: [Function],
subscribe: [Function],
trace: [Function],
unbind: [Function],
unlink: [Function],
unlock: [Function],
unsubscribe: [Function],
all: [Function: all],
del: [Function],
render: [Function: render],
listen: [Function: newMethod],
request: [IncomingMessage],
response: [ServerResponse],
cache: {},
engines: {},
settings: [Object],
locals: [Object: null prototype],
mountpath: '/',
configure: [Function: configure],
service: [Function: service],
setup: [Function: newMethod],
version: '4.4.3',
methods: [Array],
mixins: [Array],
services: [Object],
providers: [Array],
_setup: false,
hookTypes: [Array],
hooks: [Function: hooks],
eventMappings: [Object],
_super: undefined,
_router: [Function],
rest: [Object],
channel: [Function: channel],
publish: [Function: publish],
registerPublisher: [Function: registerPublisher],
lookup: [Function: lookup],
defaultAuthentication: [Function],
logger: [DerivedLogger],
io: [Server],
_isSetup: true,
[Symbol(#feathersjs/transport-commons/channels)]: [Object],
[Symbol(#feathersjs/transport-commons/publishers)]: [Object],
[Symbol(#feathersjs/transport-commons/router)]: [Object]
},
method: 'create',
path: 'authentication',
data: { strategy: 'google' },
params: {
query: {},
route: {},
connection: [Object],
provider: 'socketio',
headers: [Object]
}
}
} +2s
error: Unhandled Rejection at: Promise
And then a few seconds later, the front-end errors with a timeout due to the call not returning:
Timeout {type: "FeathersError", name: "Timeout", message: "Timeout of 5000ms exceeded calling create on authentication", code: 408, className: "timeout", …}
type: "FeathersError"
name: "Timeout"
message: "Timeout of 5000ms exceeded calling create on authentication"
code: 408
className: "timeout"
data: {timeout: 5000, method: "create", path: "authentication"}
errors: {}
hook: {type: "before", arguments: Array(2), service: {…}, app: {…}, method: "create", …}
stack: "Timeout: Timeout of 5000ms exceeded calling create on authentication↵ at new Timeout (webpack-internal:///./node_modules/#feathersjs/errors/lib/index.js:135:17)↵ at eval (webpack-internal:///./node_modules/#feathersjs/transport-commons/lib/client.js:60:55)"
__proto__: FeathersError
It appears to be complaining that the call to create on the authentication service itself requires authenticating (my reading of the 401 response message that can be seen near the top of the backend debug output).
My feathers-client.js on the front-end is almost verbatim from the docs..
import feathers from '#feathersjs/feathers'
import socketio from '#feathersjs/socketio-client'
import auth from '#feathersjs/authentication-client'
import io from 'socket.io-client'
import { iff, discard } from 'feathers-hooks-common'
import feathersVuex from 'feathers-vuex'
const socket = io('http://localhost:3030', { transports: ['websocket'] })
const feathersClient = feathers()
.configure(socketio(socket))
.configure(auth({
storageKey: 'auth',
storage: window.localStorage
}))
.hooks({
before: {
all: [
iff(
context => ['create', 'update', 'patch'].includes(context.method),
discard('__id', '__isTemp')
)
]
}
})
export default feathersClient
// Setting up feathers-vuex
const { makeServicePlugin, makeAuthPlugin, BaseModel, models, FeathersVuex } = feathersVuex(
feathersClient,
{
serverAlias: 'api', // optional for working with multiple APIs (this is the default value)
idField: '_id', // Must match the id field in your database table/collection
whitelist: ['$regex', '$options']
}
)
export { makeAuthPlugin, makeServicePlugin, BaseModel, models, FeathersVuex }
.. and given that the backend is invoked at all suggests that the vuex auth plugin is also correctly configured and used, but that could be speculation.
Can anyone suggest pointers as to how to proceed? Unfortunately I've come across no examples of this working anywhere (all examples I've seen with feathers authentication use local strategy only).

For anyone that happens to have similar issue: it seems I had an old and incompatible version of feathers-vuex installed in the project. Updating to 3.3.0 made it work.

Related

Solving Unauthorized API call using React, Node, Express

I am trying to use Marea Tide Api to build a tide application returning results based on location (latitude, longitude).
I was originally struggling to make a successful fetch from the front end due to a CORS error. I am now trying to build an express backend to both hide my api keys and navigate the CORS issue with a proxy.
I keep getting an unauthorized error when trying to navigate to localhost:8000/tides.
Express:
const PORT = 8000;
const express = require('express');
const cors = require('cors');
const axios = require('axios');
const { application, json } = require('express');
require('dotenv').config
const backend = express()
backend.listen(PORT, () => console.log(`Tide backend is working on PORT:${PORT}`))
backend.get('/tides', (req, res, next) => {
const url = 'https://api.marea.ooo/v2/tides';
const options = {
params: {
duration: 1440,
interval: 60,
latitude: 36.888,
longitude: -76.100,
}
};
const config = {
headers: {
'x-marea-api-token': process.env.MareaToken,
}
};
axios.get(url, options, config)
.then(response => {console.log(response)})
.catch(err => console.log(err))
});
Terminal Error:
[nodemon] starting `node backend.js`
Tide backend is working on PORT:8000
[AxiosError: Request failed with status code 401] {
code: 'ERR_BAD_REQUEST',
config: {
transitional: {
silentJSONParsing: true,
forcedJSONParsing: true,
clarifyTimeoutError: false
},
adapter: [Function: httpAdapter],
transformRequest: [ [Function: transformRequest] ],
transformResponse: [ [Function: transformResponse] ],
timeout: 0,
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: -1,
maxBodyLength: -1,
env: { FormData: [Function] },
validateStatus: [Function: validateStatus],
headers: {
Accept: 'application/json, text/plain, */*',
'User-Agent': 'axios/0.27.2'
},
params: {
duration: 1440,
interval: 60,
latitude: 36.888,
longitude: -76.1
},
method: 'get',
url: 'https://api.marea.ooo/v2/tides',
data: undefined
},
request: <ref *1> ClientRequest {
_events: [Object: null prototype] {
abort: [Function (anonymous)],
aborted: [Function (anonymous)],
connect: [Function (anonymous)],
error: [Function (anonymous)],
socket: [Function (anonymous)],
timeout: [Function (anonymous)],
prefinish: [Function: requestOnPrefinish]
},
_eventsCount: 7,
_maxListeners: undefined,
outputData: [],
outputSize: 0,
writable: true,
destroyed: false,
_last: true,
chunkedEncoding: false,
shouldKeepAlive: false,
maxRequestsOnConnectionReached: false,
_defaultKeepAlive: true,
useChunkedEncodingByDefault: false,
sendDate: false,
_removedConnection: false,
_removedContLen: false,
_removedTE: false,
_contentLength: 0,
_hasBody: true,
_trailer: '',
finished: true,
_headerSent: true,
_closed: false,
socket: TLSSocket {
_tlsOptions: [Object],
_secureEstablished: true,
_securePending: false,
_newSessionPending: false,
_controlReleased: true,
secureConnecting: false,
_SNICallback: null,
servername: 'api.marea.ooo',
alpnProtocol: false,
authorized: true,
authorizationError: null,
encrypted: true,
_events: [Object: null prototype],
_eventsCount: 10,
connecting: false,
_hadError: false,
_parent: null,
_host: 'api.marea.ooo',
_readableState: [ReadableState],
_maxListeners: undefined,
_writableState: [WritableState],
allowHalfOpen: false,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: undefined,
_server: null,
ssl: [TLSWrap],
_requestCert: true,
_rejectUnauthorized: true,
parser: null,
_httpMessage: [Circular *1],
[Symbol(res)]: [TLSWrap],
[Symbol(verified)]: true,
[Symbol(pendingSession)]: null,
[Symbol(async_id_symbol)]: 17,
[Symbol(kHandle)]: [TLSWrap],
[Symbol(lastWriteQueueSize)]: 0,
[Symbol(timeout)]: null,
[Symbol(kBuffer)]: null,
[Symbol(kBufferCb)]: null,
[Symbol(kBufferGen)]: null,
[Symbol(kCapture)]: false,
[Symbol(kSetNoDelay)]: false,
[Symbol(kSetKeepAlive)]: true,
[Symbol(kSetKeepAliveInitialDelay)]: 60,
[Symbol(kBytesRead)]: 0,
[Symbol(kBytesWritten)]: 0,
[Symbol(connect-options)]: [Object],
[Symbol(RequestTimeout)]: undefined
},
_header: 'GET /v2/tides?duration=1440&interval=60&latitude=36.888&longitude=-76.1 HTTP/1.1\r\n' +
'Accept: application/json, text/plain, */*\r\n' +
'User-Agent: axios/0.27.2\r\n' +
'Host: api.marea.ooo\r\n' +
'Connection: close\r\n' +
'\r\n',
_keepAliveTimeout: 0,
_onPendingData: [Function: nop],
agent: Agent {
_events: [Object: null prototype],
_eventsCount: 2,
_maxListeners: undefined,
defaultPort: 443,
protocol: 'https:',
options: [Object: null prototype],
requests: [Object: null prototype] {},
sockets: [Object: null prototype],
freeSockets: [Object: null prototype] {},
keepAliveMsecs: 1000,
keepAlive: false,
maxSockets: Infinity,
maxFreeSockets: 256,
scheduling: 'lifo',
maxTotalSockets: Infinity,
totalSocketCount: 1,
maxCachedSessions: 100,
_sessionCache: [Object],
[Symbol(kCapture)]: false
},
socketPath: undefined,
method: 'GET',
maxHeaderSize: undefined,
insecureHTTPParser: undefined,
path: '/v2/tides?duration=1440&interval=60&latitude=36.888&longitude=-76.1',
_ended: true,
res: IncomingMessage {
_readableState: [ReadableState],
_events: [Object: null prototype],
_eventsCount: 4,
_maxListeners: undefined,
socket: [TLSSocket],
httpVersionMajor: 1,
httpVersionMinor: 1,
httpVersion: '1.1',
complete: true,
rawHeaders: [Array],
rawTrailers: [],
aborted: false,
upgrade: false,
url: '',
method: null,
statusCode: 401,
statusMessage: 'Unauthorized',
client: [TLSSocket],
_consuming: false,
_dumped: false,
req: [Circular *1],
responseUrl: 'https://api.marea.ooo/v2/tides?duration=1440&interval=60&latitude=36.888&longitude=-76.1',
redirects: [],
[Symbol(kCapture)]: false,
[Symbol(kHeaders)]: [Object],
[Symbol(kHeadersCount)]: 16,
[Symbol(kTrailers)]: null,
[Symbol(kTrailersCount)]: 0,
[Symbol(RequestTimeout)]: undefined
},
aborted: false,
timeoutCb: null,
upgradeOrConnect: false,
parser: null,
maxHeadersCount: null,
reusedSocket: false,
host: 'api.marea.ooo',
protocol: 'https:',
_redirectable: Writable {
_writableState: [WritableState],
_events: [Object: null prototype],
_eventsCount: 3,
_maxListeners: undefined,
_options: [Object],
_ended: true,
_ending: true,
_redirectCount: 0,
_redirects: [],
_requestBodyLength: 0,
_requestBodyBuffers: [],
_onNativeResponse: [Function (anonymous)],
_currentRequest: [Circular *1],
_currentUrl: 'https://api.marea.ooo/v2/tides?duration=1440&interval=60&latitude=36.888&longitude=-76.1',
[Symbol(kCapture)]: false
},
[Symbol(kCapture)]: false,
[Symbol(kNeedDrain)]: false,
[Symbol(corked)]: 0,
[Symbol(kOutHeaders)]: [Object: null prototype] {
accept: [Array],
'user-agent': [Array],
host: [Array]
}
},
response: {
status: 401,
statusText: 'Unauthorized',
headers: {
'cache-control': 'max-age=0, private, must-revalidate',
'content-length': '40',
'content-type': 'application/json; charset=utf-8',
date: 'Tue, 19 Jul 2022 18:46:46 GMT',
server: 'Caddy',
'x-request-id': 'FwNPaorYW0wySfUApCrB',
connection: 'close'
},
config: {
transitional: [Object],
adapter: [Function: httpAdapter],
transformRequest: [Array],
transformResponse: [Array],
timeout: 0,
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: -1,
maxBodyLength: -1,
env: [Object],
validateStatus: [Function: validateStatus],
headers: [Object],
params: [Object],
method: 'get',
url: 'https://api.marea.ooo/v2/tides',
data: undefined
},
request: <ref *1> ClientRequest {
_events: [Object: null prototype],
_eventsCount: 7,
_maxListeners: undefined,
outputData: [],
outputSize: 0,
writable: true,
destroyed: false,
_last: true,
chunkedEncoding: false,
shouldKeepAlive: false,
maxRequestsOnConnectionReached: false,
_defaultKeepAlive: true,
useChunkedEncodingByDefault: false,
sendDate: false,
_removedConnection: false,
_removedContLen: false,
_removedTE: false,
_contentLength: 0,
_hasBody: true,
_trailer: '',
finished: true,
_headerSent: true,
_closed: false,
socket: [TLSSocket],
_header: 'GET /v2/tides?duration=1440&interval=60&latitude=36.888&longitude=-76.1 HTTP/1.1\r\n' +
'Accept: application/json, text/plain, */*\r\n' +
'User-Agent: axios/0.27.2\r\n' +
'Host: api.marea.ooo\r\n' +
'Connection: close\r\n' +
'\r\n',
_keepAliveTimeout: 0,
_onPendingData: [Function: nop],
agent: [Agent],
socketPath: undefined,
method: 'GET',
maxHeaderSize: undefined,
insecureHTTPParser: undefined,
path: '/v2/tides?duration=1440&interval=60&latitude=36.888&longitude=-76.1',
_ended: true,
res: [IncomingMessage],
aborted: false,
timeoutCb: null,
upgradeOrConnect: false,
parser: null,
maxHeadersCount: null,
reusedSocket: false,
host: 'api.marea.ooo',
protocol: 'https:',
_redirectable: [Writable],
[Symbol(kCapture)]: false,
[Symbol(kNeedDrain)]: false,
[Symbol(corked)]: 0,
[Symbol(kOutHeaders)]: [Object: null prototype]
},
data: { status: 401, error: 'Unauthorized' }
}
}
axios.get() accepts only two parameters...
axios.get(url[, config])
Combine your options and config objects and don't forget to send an actual response.
axios.get(url, { ...options, ...config })
.then(({ data }) => res.json(data))
.catch(next);

How to add emails to contact lists in SendGrid with Node?

I'm working on a React Native app with Firebase Functions. I am unable to add new contacts to a SendGrid list consistently.
This is my function:
exports.addToSendGridMembersList = functions.https.onCall(async (data) => {
const {first, last, email} = data
p(first,last,email)
const axios = require('axios');
let e = JSON.stringify(email)
let f = JSON.stringify(first)
let l = JSON.stringify(last)
p("JSON.stringify: ", e, f, l)
axios({
method: "PUT",
url: "https://api.sendgrid.com/v3/marketing/contacts",
headers:
{ 'content-type': 'application/json',
authorization: 'Bearer ' + SEND_GRID_KEY },
body:
{ "list_ids": [
"eda0bc01-b098-4366-ad58-8bab03ec9b33"
],
"contacts": [
{
"email": "o#gmail.com",
"first_name": "o",
"last_name": "o"
}
]
}
})
.then(function (error, response, body) {
console.log(error)
console.log(response)
console.log(body);
})
});
I at first thought the axios body was unable to read constants that's why I stringified them and was going to insert them in the body (first, last and email) values. This is the response I get in Google Cloud logs
JSON.stringify: "gg#gmail.com" "gg" "gg"
> Unhandled error { Error: Request failed with status code 400 at createError (/workspace/node_modules/axios/lib/core/createError.js:16:15) at settle (/workspace/node_modules/axios/lib/core/settle.js:17:12) at IncomingMessage.handleStreamEnd (/workspace/node_modules/axios/lib/adapters/http.js:260:11) at IncomingMessage.emit (events.js:203:15) at IncomingMessage.EventEmitter.emit (domain.js:466:23) at endReadableNT (_stream_readable.js:1145:12) at process._tickCallback (internal/process/next_tick.js:63:19) config: { url: 'https://api.sendgrid.com/v3/marketing/contacts', method: 'put', headers: { Accept: 'application/json, text/plain, */*', 'Content-Type': 'application/json', authorization: 'Bearer HIDDEN', 'User-Agent': 'axios/0.21.1' }, transformRequest: [ [Function: transformRequest] ], transformResponse: [ [Function: transformResponse] ], timeout: 0, adapter: [Function: httpAdapter], xsrfCookieName: 'XSRF-TOKEN', xsrfHeaderName: 'X-XSRF-TOKEN', maxContentLength: -1, maxBodyLength: -1, validateStatus: [Function: validateStatus], body: { list_ids: [Array], contacts: [Array] }, data: undefined }, request: ClientRequest { domain: Domain { domain: null, _events: [Object], _eventsCount: 3, _maxListeners: undefined, members: [], [Symbol(kWeak)]: WeakReference {} }, _events: [Object: null prototype] { socket: [Function], abort: [Function], aborted: [Function], connect: [Function], error: [Function], timeout: [Function], prefinish: [Function: requestOnPrefinish] }, _eventsCount: 7, _maxListeners: undefined, output: [], outputEncodings: [], outputCallbacks: [], outputSize: 0, writable: true, _last: true, chunkedEncoding: false, shouldKeepAlive: false, useChunkedEncodingByDefault: true, sendDate: false, _removedConnection: false, _removedContLen: false, _removedTE: false, _contentLength: 0, _hasBody: true, _trailer: '', finished: true, _headerSent: true, socket: TLSSocket { _tlsOptions: [Object], _secureEstablished: true, _securePending: false, _newSessionPending: false, _controlReleased: true, _SNICallback: null, servername: 'api.sendgrid.com', alpnProtocol: false, authorized: true, authorizationError: null, encrypted: true, _events: [Object], _eventsCount: 9, connecting: false, _hadError: false, _handle: [TLSWrap], _parent: null, _host: 'api.sendgrid.com', _readableState: [ReadableState], readable: true, domain: [Domain], _maxListeners: undefined, _writableState: [WritableState], writable: false, allowHalfOpen: false, _sockname: null, _pendingData: null, _pendingEncoding: '', server: undefined, _server: null, ssl: [TLSWrap], _requestCert: true, _rejectUnauthorized: true, parser: null, _httpMessage: [Circular], [Symbol(res)]: [TLSWrap], [Symbol(asyncId)]: 81, [Symbol(lastWriteQueueSize)]: 0, [Symbol(timeout)]: null, [Symbol(kBytesRead)]: 0, [Symbol(kBytesWritten)]: 0, [Symbol(connect-options)]: [Object] }, connection: TLSSocket { _tlsOptions: [Object], _secureEstablished: true, _securePending: false, _newSessionPending: false, _controlReleased: true, _SNICallback: null, servername: 'api.sendgrid.com', alpnProtocol: false, authorized: true, authorizationError: null, encrypted: true, _events: [Object], _eventsCount: 9, connecting: false, _hadError: false, _handle: [TLSWrap], _parent: null, _host: 'api.sendgrid.com', _readableState: [ReadableState], readable: true, domain: [Domain], _maxListeners: undefined, _writableState: [WritableState], writable: false, allowHalfOpen: false, _sockname: null, _pendingData: null, _pendingEncoding: '', server: undefined, _server: null, ssl: [TLSWrap], _requestCert: true, _rejectUnauthorized: true, parser: null, _httpMessage: [Circular], [Symbol(res)]: [TLSWrap], [Symbol(asyncId)]: 81, [Symbol(lastWriteQueueSize)]: 0, [Symbol(timeout)]: null, [Symbol(kBytesRead)]: 0, [Symbol(kBytesWritten)]: 0, [Symbol(connect-options)]: [Object] }, _header: 'PUT /v3/marketing/contacts HTTP/1.1\r\nAccept: application/json, text/plain, */*\r\nContent-Type: application/json\r\nauthorization: Bearer HIDDEN\r\nUser-Agent: axios/0.21.1\r\nHost: api.sendgrid.com\r\nConnection: close\r\nContent-Length: 0\r\n\r\n', _onPendingData: [Function: noopPendingOutput], agent: Agent { domain: null, _events: [Object], _eventsCount: 1, _maxListeners: undefined, defaultPort: 443, protocol: 'https:', options: [Object], requests: {}, sockets: [Object], freeSockets: {}, keepAliveMsecs: 1000, keepAlive: false, maxSockets: Infinity, maxFreeSockets: 256, maxCachedSessions: 100, _sessionCache: [Object] }, socketPath: undefined, timeout: undefined, method: 'PUT', insecureHTTPParser: undefined, path: '/v3/marketing/contacts', _ended: true, res: IncomingMessage { _readableState: [ReadableState], readable: false, domain: [Domain], _events: [Object], _eventsCount: 3, _maxListeners: undefined, socket: [TLSSocket], connection: [TLSSocket], httpVersionMajor: 1, httpVersionMinor: 1, httpVersion: '1.1', complete: true, headers: [Object], rawHeaders: [Array], trailers: {}, rawTrailers: [], aborted: false, upgrade: false, url: '', method: null, statusCode: 400, statusMessage: 'Bad Request', client: [TLSSocket], _consuming: false, _dumped: false, req: [Circular], responseUrl: 'https://api.sendgrid.com/v3/marketing/contacts', redirects: [] }, aborted: undefined, timeoutCb: null, upgradeOrConnect: false, parser: null, maxHeadersCount: null, _redirectable: Writable { _writableState: [WritableState], writable: true, domain: [Domain], _events: [Object], _eventsCount: 2, _maxListeners: undefined, _options: [Object], _ended: true, _ending: true, _redirectCount: 0, _redirects: [], _requestBodyLength: 0, _requestBodyBuffers: [], _onNativeResponse: [Function], _currentRequest: [Circular], _currentUrl: 'https://api.sendgrid.com/v3/marketing/contacts' }, [Symbol(isCorked)]: false, [Symbol(outHeadersKey)]: [Object: null prototype] { accept: [Array], 'content-type': [Array], authorization: [Array], 'user-agent': [Array], host: [Array] } }, response: { status: 400, statusText: 'Bad Request', headers: { server: 'nginx', date: 'Mon, 28 Dec 2020 01:39:11 GMT', 'content-type': 'application/json', 'content-length': '50', connection: 'close', 'x-amzn-requestid': '7cec2ea8-620a-4096-af97-c58c3f5f12d2', 'access-control-allow-origin': '*', 'access-control-allow-headers': 'AUTHORIZATION, Content-Type, On-behalf-of, x-sg-elas-acl, X-Recaptcha, X-Request-Source', 'x-amz-apigw-id': 'YPWR7E1GvHcFVXg=', 'access-control-allow-methods': 'PUT,DELETE,OPTIONS', 'access-control-expose-headers': 'Link, Location', 'x-amzn-trace-id': 'Root=1-5fe9373f-69accb7255a34e6321797cf3;Sampled=0', 'x-envoy-upstream-service-time': '93', 'referrer-policy': 'strict-origin-when-cross-origin', 'x-content-type-options': 'nosniff', 'x-ratelimit-limit': '200', 'x-ratelimit-remaining': '199', 'x-ratelimit-reset': '49' }, config: { url: 'https://api.sendgrid.com/v3/marketing/contacts', method: 'put', headers: [Object], transformRequest: [Array], transformResponse: [Array], timeout: 0, adapter: [Function: httpAdapter], xsrfCookieName: 'XSRF-TOKEN', xsrfHeaderName: 'X-XSRF-TOKEN', maxContentLength: -1, maxBodyLength: -1, validateStatus: [Function: validateStatus], body: [Object], data: undefined }, request: ClientRequest { domain: [Domain], _events: [Object], _eventsCount: 7, _maxListeners: undefined, output: [], outputEncodings: [], outputCallbacks: [], outputSize: 0, writable: true, _last: true, chunkedEncoding: false, shouldKeepAlive: false, useChunkedEncodingByDefault: true, sendDate: false, _removedConnection: false, _removedContLen: false, _removedTE: false, _contentLength: 0, _hasBody: true, _trailer: '', finished: true, _headerSent: true, socket: [TLSSocket], connection: [TLSSocket], _header: 'PUT /v3/marketing/contacts HTTP/1.1\r\nAccept: application/json, text/plain, */*\r\nContent-Type: application/json\r\nauthorization: Bearer HIDDEN\r\nUser-Agent: axios/0.21.1\r\nHost: api.sendgrid.com\r\nConnection: close\r\nContent-Length: 0\r\n\r\n', _onPendingData: [Function: noopPendingOutput], agent: [Agent], socketPath: undefined, timeout: undefined, method: 'PUT', insecureHTTPParser: undefined, path: '/v3/marketing/contacts', _ended: true, res: [IncomingMessage], aborted: undefined, timeoutCb: null, upgradeOrConnect: false, parser: null, maxHeadersCount: null, _redirectable: [Writable], [Symbol(isCorked)]: false, [Symbol(outHeadersKey)]: [Object] }, data: { errors: [Array] } }, isAxiosError: true, toJSON: [Function: toJSON] }
Turns out axios was failing. I switched to request and it worked like a charm. Here's my final code:
var request = require("request");
var options = { method: 'PUT',
url: 'https://api.sendgrid.com/v3/marketing/contacts',
headers:
{ 'content-type': 'application/json',
authorization: 'Bearer ' + SEND_GRID_KEY},
body:
{ list_ids: [ 'eda0bc01-b098-4366-ad58-8bab03ec9b33' ],
contacts: [
{
"email": e,
"first_name": f,
"last_name": l
}
]
},
json: true };
request(options, function (error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
You can test out SendGrid's api and generate code here: https://sendgrid.api-docs.io/v3.0/contacts/add-or-update-a-contact

GET https://graph.microsoft.com/v1.0/me returns 401 (Unauthorized) given a valid access token with User.Read permission

I generate an access token using 'simple-oauth2' that looks like this
import { AuthorizationCode } from 'simple-oauth2';
scopes = ['offline_access', 'https://outlook.office.com/IMAP.AccessAsUser.All',
'https://outlook.office.com/SMTP.Send','User.Read'];
async getCredentials(code: string) {
const client = new AuthorizationCode(this.oauthConfig);
let tokenParams = {
code,
redirect_uri: config.MICROSOFT_CREDENTIALS.REDIRECT_URIS[0],
scope: this.scopes.join(' ')
}
return await client.getToken(tokenParams)
};
// Result from getCredentials
AccessToken {
token: {
token_type: 'Bearer',
scope: 'https://outlook.office.com/IMAP.AccessAsUser.All https://outlook.office.com/SMTP.Send https://outlook.office.com/User.Read',
expires_in: 3599,
ext_expires_in: 3599,
access_token: 'eyJ0eXAiOiJKV1QiLCJub25jZSI6I...',
refresh_token: '0.ATUAd-LjmxfEgkWp0wIFCKwhpRA-z-...',
expires_at: 2020-09-25T01:13:08.970Z
}
}
Following this guide, I then pass the access_token field to a GET request to https://graph.microsoft.com/v1.0/me
getUserProfile(accessToken: string) {
return axios.get("https://graph.microsoft.com/v1.0/me", {
headers: {
Authorization: 'Bearer ' + accessToken,
'Content-Type': 'application/json'
}
})
.then((res) => {
return res.data;
})
.catch((reason) => {
console.log("getUserProfile failed");
console.log(reason);
})
};
This fails with the following error
getUserProfile failed
Error: Request failed with status code 401
at createError (C:\Users\me\Desktop\projects\proj\node_modules\axios\lib\core\createError.js:16:15)
at settle (C:\Users\me\Desktop\projects\proj\node_modules\axios\lib\core\settle.js:17:12)
at IncomingMessage.handleStreamEnd (C:\Users\me\Desktop\projects\proj\node_modules\axios\lib\adapters\http.js:236:11)
at IncomingMessage.emit (events.js:323:22)
at IncomingMessage.EventEmitter.emit (domain.js:482:12)
at endReadableNT (_stream_readable.js:1204:12)
at processTicksAndRejections (internal/process/task_queues.js:84:21) {
config: {
url: 'https://graph.microsoft.com/v1.0/me',
method: 'get',
headers: {
Accept: 'application/json, text/plain, */*',
Authorization: 'Bearer eyJ0eXAiOiJKV1QiLCJub25jZSI6IjByZ0t3MFRLOEF...',
'Content-Type': 'application/json',
'User-Agent': 'axios/0.19.2'
},
transformRequest: [ [Function: transformRequest] ],
transformResponse: [ [Function: transformResponse] ],
timeout: 0,
adapter: [Function: httpAdapter],
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: -1,
validateStatus: [Function: validateStatus],
data: undefined
},
request: ClientRequest {
_events: [Object: null prototype] {
socket: [Function],
abort: [Function],
aborted: [Function],
error: [Function],
timeout: [Function],
prefinish: [Function: requestOnPrefinish]
},
_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 {
_tlsOptions: [Object],
_secureEstablished: true,
_securePending: false,
_newSessionPending: false,
_controlReleased: true,
_SNICallback: null,
servername: 'graph.microsoft.com',
alpnProtocol: false,
authorized: true,
authorizationError: null,
encrypted: true,
_events: [Object: null prototype],
_eventsCount: 9,
connecting: false,
_hadError: false,
_parent: null,
_host: 'graph.microsoft.com',
_readableState: [ReadableState],
readable: true,
_maxListeners: undefined,
_writableState: [WritableState],
writable: false,
allowHalfOpen: false,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: undefined,
_server: null,
ssl: [TLSWrap],
_requestCert: true,
_rejectUnauthorized: true,
parser: null,
_httpMessage: [Circular],
[Symbol(res)]: [TLSWrap],
[Symbol(asyncId)]: 1233,
[Symbol(kHandle)]: [TLSWrap],
[Symbol(lastWriteQueueSize)]: 0,
[Symbol(timeout)]: null,
[Symbol(kBuffer)]: null,
[Symbol(kBufferCb)]: null,
[Symbol(kBufferGen)]: null,
[Symbol(kCapture)]: false,
[Symbol(kBytesRead)]: 0,
[Symbol(kBytesWritten)]: 0,
[Symbol(connect-options)]: [Object]
},
connection: TLSSocket {
_tlsOptions: [Object],
_secureEstablished: true,
_securePending: false,
_newSessionPending: false,
_controlReleased: true,
_SNICallback: null,
servername: 'graph.microsoft.com',
alpnProtocol: false,
authorized: true,
authorizationError: null,
encrypted: true,
_events: [Object: null prototype],
_eventsCount: 9,
connecting: false,
_hadError: false,
_parent: null,
_host: 'graph.microsoft.com',
_readableState: [ReadableState],
readable: true,
_maxListeners: undefined,
_writableState: [WritableState],
writable: false,
allowHalfOpen: false,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: undefined,
_server: null,
ssl: [TLSWrap],
_requestCert: true,
_rejectUnauthorized: true,
parser: null,
_httpMessage: [Circular],
[Symbol(res)]: [TLSWrap],
[Symbol(asyncId)]: 1233,
[Symbol(kHandle)]: [TLSWrap],
[Symbol(lastWriteQueueSize)]: 0,
[Symbol(timeout)]: null,
[Symbol(kBuffer)]: null,
[Symbol(kBufferCb)]: null,
[Symbol(kBufferGen)]: null,
[Symbol(kCapture)]: false,
[Symbol(kBytesRead)]: 0,
[Symbol(kBytesWritten)]: 0,
[Symbol(connect-options)]: [Object]
},
_header: 'GET /v1.0/me HTTP/1.1\r\n' +
'Accept: application/json, text/plain, */*\r\n' +
'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJub25jZSI6IjByZ0t...\r\n' +
'Content-Type: application/json\r\n' +
'User-Agent: axios/0.19.2\r\n' +
'Host: graph.microsoft.com\r\n' +
'Connection: close\r\n' +
'\r\n',
_onPendingData: [Function: noopPendingOutput],
agent: Agent {
_events: [Object: null prototype],
_eventsCount: 2,
_maxListeners: undefined,
defaultPort: 443,
protocol: 'https:',
options: [Object],
requests: {},
sockets: [Object],
freeSockets: {},
keepAliveMsecs: 1000,
keepAlive: false,
maxSockets: Infinity,
maxFreeSockets: 256,
maxCachedSessions: 100,
_sessionCache: [Object],
[Symbol(kCapture)]: false
},
socketPath: undefined,
method: 'GET',
insecureHTTPParser: undefined,
path: '/v1.0/me',
_ended: true,
res: IncomingMessage {
_readableState: [ReadableState],
readable: false,
_events: [Object: null prototype],
_eventsCount: 3,
_maxListeners: undefined,
socket: [TLSSocket],
connection: [TLSSocket],
httpVersionMajor: 1,
httpVersionMinor: 1,
httpVersion: '1.1',
complete: true,
headers: [Object],
rawHeaders: [Array],
trailers: {},
rawTrailers: [],
aborted: false,
upgrade: false,
url: '',
method: null,
statusCode: 401,
statusMessage: 'Unauthorized',
client: [TLSSocket],
_consuming: false,
_dumped: false,
req: [Circular],
responseUrl: 'https://graph.microsoft.com/v1.0/me',
redirects: [],
[Symbol(kCapture)]: false
},
aborted: false,
timeoutCb: null,
upgradeOrConnect: false,
parser: null,
maxHeadersCount: null,
reusedSocket: false,
_redirectable: Writable {
_writableState: [WritableState],
writable: true,
_events: [Object: null prototype],
_eventsCount: 2,
_maxListeners: undefined,
_options: [Object],
_redirectCount: 0,
_redirects: [],
_requestBodyLength: 0,
_requestBodyBuffers: [],
_onNativeResponse: [Function],
_currentRequest: [Circular],
_currentUrl: 'https://graph.microsoft.com/v1.0/me',
[Symbol(kCapture)]: false
},
[Symbol(kCapture)]: false,
[Symbol(kNeedDrain)]: false,
[Symbol(corked)]: 0,
[Symbol(kOutHeaders)]: [Object: null prototype] {
accept: [Array],
authorization: [Array],
'content-type': [Array],
'user-agent': [Array],
host: [Array]
}
},
response: {
status: 401,
statusText: 'Unauthorized',
headers: {
'cache-control': 'private',
'content-type': 'application/json',
'request-id': '6026815f-6c31-48c3-9b70-a6eb3cda8e44',
'client-request-id': '6026815f-6c31-48c3-9b70-a6eb3cda8e44',
'x-ms-ags-diagnostic': '{"ServerInfo":{"DataCenter":"West US","Slice":"SliceC","Ring":"5","ScaleUnit":"002","RoleInstance":"AGSFE_IN_13"}}',
'www-authenticate': 'Bearer realm="", authorization_uri="https://login.microsoftonline.com/common/oauth2/authorize", client_id="00000003-0000-0000-c000-000000000000"',
'strict-transport-security': 'max-age=31536000',
date: 'Fri, 25 Sep 2020 00:13:11 GMT',
connection: 'close',
'content-length': '330'
},
config: {
url: 'https://graph.microsoft.com/v1.0/me',
method: 'get',
headers: [Object],
transformRequest: [Array],
transformResponse: [Array],
timeout: 0,
adapter: [Function: httpAdapter],
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: -1,
validateStatus: [Function: validateStatus],
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 /v1.0/me HTTP/1.1\r\n' +
'Accept: application/json, text/plain, */*\r\n' +
'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJub25jZSI6IjByZ0...\r\n' +
'Content-Type: application/json\r\n' +
'User-Agent: axios/0.19.2\r\n' +
'Host: graph.microsoft.com\r\n' +
'Connection: close\r\n' +
'\r\n',
_onPendingData: [Function: noopPendingOutput],
agent: [Agent],
socketPath: undefined,
method: 'GET',
insecureHTTPParser: undefined,
path: '/v1.0/me',
_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: [Object] }
},
isAxiosError: true,
toJSON: [Function]
Documentation for /me and the guide states I just need User.Read for my permissions and that my headers are correct so I do not know why it is failing. The Microsoft account I am using for testing is a Work Account.
I have briefly tried using the Graph SDK but I feel like this approach is 99% of the way there.
Big picture wise I am trying to save the user's email address so I can use the OAuth2 token to connect to O365 through IMAP and SMTP. If I hardcode what I know the email address to be everything works so automating the retrieval of the user's email address through Graphs is the last thing I need.
You should not use a token that does not belong to the api. You are calling the Microsoft graph api, but you are requesting a token for Outlook, so you only need to change the scope to:
scopes = ['offline_access', 'https://graph.microsoft.com/.default'];
Another method is keeping your current scopes and call GET https://outlook.office365.com/api/v2.0/me/ to get the signed-in user's information.

Method: spreadsheets.values.append TypeError: Converting circular structure to JSON

I've been using the Google Sheets API successfully. I've managed to use the spreadsheets.values.update, and spreadsheets.values.get methods with no errors. Today I've been trying to use the method: spreadsheets.values.append. This method simply appends a row of data to the end of the table. In the developer portal, you can "try this api", and when I do I get a 200 response.
However, when I run exactly the same method (including parameters!) in my NodeJS/Express app I get the error:
"TypeError: Converting circular structure to JSON",
Yet, when I look at the Google Sheet, the data has successfully been appended. This is what my code looks like:
function postValid(req, res) {
const data = req.body;
console.log('received validate post');
sheets.spreadsheets.values.append( {
auth: jwtClient,
spreadsheetId: ssId,
range: 'Valid!A:C',
resource: {
values: [
[1, 2, 3]
]
},
valueInputOption: 'USER_ENTERED',
}, (err, response) => {
if (err) {
res.status(500);
res.send('The API returned an error: ' + err);
}
res.send(response)
})
}
I could ignore the error, as the data does get sent, but I'd really like to know what is causing this circular structure error. How can I go about debugging this?
Like I said the get and update methods with almost the same structure works fine so it isn't the {auth: jwtClient, spreadsheetId: ssId, } parts, and the rest is pretty standard JSON. I just don't get it.
Has anyone run into the same problem?
UPDATE:
I've narrowed down the issue. If I disable Express's JSON body parser, then I can view the full response. Here it is below, you'll see the circular reference is part of the Request, but this request is done via the googleapi methods, is this a possible bug with the googleapi library?
{ status: 200,
statusText: 'OK',
headers:
{ 'content-type': 'application/json; charset=UTF-8',
vary: 'X-Origin, Referer, Origin,Accept-Encoding',
date: 'Tue, 30 Oct 2018 12:22:09 GMT',
server: 'ESF',
'cache-control': 'private',
'x-xss-protection': '1; mode=block',
'x-frame-options': 'SAMEORIGIN',
'alt-svc': 'quic=":443"; ma=2592000; v="44,43,39,35"',
'accept-ranges': 'none',
connection: 'close' },
config:
{ adapter: [Function: httpAdapter],
transformRequest: { '0': [Function: transformRequest] },
transformResponse: { '0': [Function: transformResponse] },
timeout: 0,
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: 2147483648,
validateStatus: [Function],
headers:
{ Accept: 'application/json, text/plain, */*',
'Content-Type': 'application/json;charset=utf-8',
Authorization:
<REMOVED>,
'User-Agent': 'google-api-nodejs-client/1.6.1',
'Content-Length': 29 },
method: 'post',
url:
'https://sheets.googleapis.com/v4/spreadsheets/<REMOVED>/values/Valid!A:C:append',
paramsSerializer: [Function],
data: '{"values":[[null,null,null]]}',
params: { valueInputOption: 'USER_ENTERED' } },
request:
ClientRequest {
_events:
{ socket: [Function],
abort: [Function],
aborted: [Function],
error: [Function],
timeout: [Function],
prefinish: [Function: requestOnPrefinish] },
_eventsCount: 6,
_maxListeners: undefined,
output: [],
outputEncodings: [],
outputCallbacks: [],
outputSize: 0,
writable: true,
_last: true,
chunkedEncoding: false,
shouldKeepAlive: false,
useChunkedEncodingByDefault: true,
sendDate: false,
_removedConnection: false,
_removedContLen: false,
_removedTE: false,
_contentLength: null,
_hasBody: true,
_trailer: '',
finished: true,
_headerSent: true,
socket:
TLSSocket {
_tlsOptions: [Object],
_secureEstablished: true,
_securePending: false,
_newSessionPending: false,
_controlReleased: true,
_SNICallback: null,
servername: 'sheets.googleapis.com',
alpnProtocol: false,
authorized: true,
authorizationError: null,
encrypted: true,
_events: [Object],
_eventsCount: 8,
connecting: false,
_hadError: false,
_handle: null,
_parent: null,
_host: 'sheets.googleapis.com',
_readableState: [ReadableState],
readable: false,
_maxListeners: undefined,
_writableState: [WritableState],
writable: false,
allowHalfOpen: false,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: undefined,
_server: null,
ssl: null,
_requestCert: true,
_rejectUnauthorized: true,
parser: null,
_httpMessage: [Circular], //<--HERE IS ONE ISSUE
write: [Function: writeAfterFIN],
[Symbol(res)]: [TLSWrap],
[Symbol(asyncId)]: 78,
[Symbol(lastWriteQueueSize)]: 0,
[Symbol(timeout)]: null,
[Symbol(kBytesRead)]: 575,
[Symbol(kBytesWritten)]: 517,
[Symbol(connect-options)]: [Object] },
connection:
TLSSocket {
_tlsOptions: [Object],
_secureEstablished: true,
_securePending: false,
_newSessionPending: false,
_controlReleased: true,
_SNICallback: null,
servername: 'sheets.googleapis.com',
alpnProtocol: false,
authorized: true,
authorizationError: null,
encrypted: true,
_events: [Object],
_eventsCount: 8,
connecting: false,
_hadError: false,
_handle: null,
_parent: null,
_host: 'sheets.googleapis.com',
_readableState: [ReadableState],
readable: false,
_maxListeners: undefined,
_writableState: [WritableState],
writable: false,
allowHalfOpen: false,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: undefined,
_server: null,
ssl: null,
_requestCert: true,
_rejectUnauthorized: true,
parser: null,
_httpMessage: [Circular], //<--Again another problem
write: [Function: writeAfterFIN],
[Symbol(res)]: [TLSWrap],
[Symbol(asyncId)]: 78,
[Symbol(lastWriteQueueSize)]: 0,
[Symbol(timeout)]: null,
[Symbol(kBytesRead)]: 575,
[Symbol(kBytesWritten)]: 517,
[Symbol(connect-options)]: [Object] },
_header:
'POST /v4/spreadsheets/<REMOVED>/values/Valid!A:C:append?valueInputOption=USER_ENTERED HTTP/1.1\r\nAccept: application/json, text/plain, */*\r\nContent-Type: application/json;charset=utf-8\r\nAuthorization: <REMOVED> User-Agent: google-api-nodejs-client/1.6.1\r\nContent-Length: 29\r\nHost: sheets.googleapis.com\r\nConnection: close\r\n\r\n',
_onPendingData: [Function: noopPendingOutput],
agent:
Agent {
_events: [Object],
_eventsCount: 1,
_maxListeners: undefined,
defaultPort: 443,
protocol: 'https:',
options: [Object],
requests: {},
sockets: [Object],
freeSockets: {},
keepAliveMsecs: 1000,
keepAlive: false,
maxSockets: Infinity,
maxFreeSockets: 256,
maxCachedSessions: 100,
_sessionCache: [Object] },
socketPath: undefined,
timeout: undefined,
method: 'POST',
path:
'/v4/spreadsheets/<REMOVED>/values/Valid!A:C:append?valueInputOption=USER_ENTERED',
_ended: true,
res:
IncomingMessage {
_readableState: [ReadableState],
readable: false,
_events: [Object],
_eventsCount: 3,
_maxListeners: undefined,
socket: [TLSSocket],
connection: [TLSSocket],
httpVersionMajor: 1,
httpVersionMinor: 1,
httpVersion: '1.1',
complete: true,
headers: [Object],
rawHeaders: [Array],
trailers: {},
rawTrailers: [],
aborted: false,
upgrade: false,
url: '',
method: null,
statusCode: 200,
statusMessage: 'OK',
client: [TLSSocket],
_consuming: true,
_dumped: false,
req: [Circular], //<--Again another circular reference
responseUrl:
'https://sheets.googleapis.com/v4/spreadsheets/<REMOVED>/values/Valid!A:C:append?valueInputOption=USER_ENTERED',
redirects: [] },
aborted: undefined,
timeoutCb: null,
upgradeOrConnect: false,
parser: null,
maxHeadersCount: null,
_redirectable:
Writable {
_writableState: [WritableState],
writable: true,
_events: [Object],
_eventsCount: 2,
_maxListeners: undefined,
_options: [Object],
_redirectCount: 0,
_redirects: [],
_requestBodyLength: 29,
_requestBodyBuffers: [],
_onNativeResponse: [Function],
_currentRequest: [Circular], //<-- Again!!
_currentUrl:
'https://sheets.googleapis.com/v4/spreadsheets/<REMOVED>/values/Valid!A:C:append?valueInputOption=USER_ENTERED' },
[Symbol(isCorked)]: false,
[Symbol(outHeadersKey)]:
{ accept: [Array],
'content-type': [Array],
authorization: [Array],
'user-agent': [Array],
'content-length': [Array],
host: [Array] } },
data:
{ spreadsheetId: <REMOVED>,
tableRange: 'Valid!A1:C8',
updates:
{ spreadsheetId: <REMOVED>,
updatedRange: 'Valid!A9' } } }
This is indeed coming from Google api response. I also seen it when calling other api such as https://cloud.google.com/bigquery/docs/reference/rest/v2/jobs/query
You have to make sure to call only the relevant part of the response and not attempt to convert it to JSON in order to avoid the circular error messags

node.js express middleware redirect if user not logged in

If a user tries to navigate to http://www.example.com/news.html (or any other html page that is not the login page ), if the user is not logged in, I need to redirect him to the login page.
I tried the following code but once I am inside the if's true code block the res.render or the res.redirect is not working at all. If i console.log something there it works properly. So I guess there's something wrong with the res object.
app.use(function(req, res, next) {
if (req.session.user == undefined) {
// if user is not logged-in redirect back to login page //
res.render('es/login', {
title: 'Hello - Please Login To Your Account'
});
} else {
next();
}
});
If I console.log(res) I get:
{ domain: null,
_events: { finish: [Function], header: [Function] },
_maxListeners: 10,
output: [],
outputEncodings: [],
writable: true,
_last: false,
chunkedEncoding: false,
shouldKeepAlive: true,
useChunkedEncodingByDefault: true,
sendDate: true,
_headerSent: false,
_header: '',
_hasBody: true,
_trailer: '',
finished: false,
_hangupClose: false,
socket:
{ _connecting: false,
_handle:
{ fd: 24,
writeQueueSize: 0,
owner: [Circular],
onread: [Function: onread],
reading: true },
_readableState:
{ highWaterMark: 16384,
buffer: [],
length: 0,
pipes: null,
pipesCount: 0,
flowing: false,
ended: false,
endEmitted: false,
reading: true,
calledRead: true,
sync: false,
needReadable: true,
emittedReadable: false,
readableListening: false,
objectMode: false,
defaultEncoding: 'utf8',
ranOut: false,
awaitDrain: 0,
readingMore: false,
decoder: null,
encoding: null },
readable: true,
domain: null,
_events:
{ end: [Object],
finish: [Function: onSocketFinish],
_socketEnd: [Function: onSocketEnd],
drain: [Object],
timeout: [Function],
error: [Function],
close: [Object] },
_maxListeners: 10,
_writableState:
{ highWaterMark: 16384,
objectMode: false,
needDrain: false,
ending: false,
ended: false,
finished: false,
decodeStrings: false,
defaultEncoding: 'utf8',
length: 0,
writing: false,
sync: false,
bufferProcessing: false,
onwrite: [Function],
writecb: null,
writelen: 0,
buffer: [],
errorEmitted: false },
writable: true,
allowHalfOpen: true,
onend: [Function],
destroyed: false,
bytesRead: 3233,
_bytesDispatched: 306029,
_pendingData: null,
_pendingEncoding: '',
server:
{ domain: null,
_events: [Object],
_maxListeners: 10,
_connections: 6,
connections: [Getter/Setter],
_handle: [Object],
_usingSlaves: false,
_slaves: [],
allowHalfOpen: true,
httpAllowHalfOpen: false,
timeout: 120000,
_connectionKey: '4:0.0.0.0:3000' },
_idleTimeout: 120000,
_idleNext:
{ _connecting: false,
_handle: [Object],
_readableState: [Object],
readable: true,
domain: null,
_events: [Object],
_maxListeners: 10,
_writableState: [Object],
writable: true,
allowHalfOpen: true,
onend: [Function],
destroyed: false,
bytesRead: 2662,
_bytesDispatched: 272567,
_pendingData: null,
_pendingEncoding: '',
server: [Object],
_idleTimeout: 120000,
_idleNext: [Object],
_idlePrev: [Circular],
_idleStart: 1426765947031,
_monotonicStartTime: 121119709,
parser: [Object],
ondata: [Function],
_paused: false,
_httpMessage: null },
_idlePrev: { _idleNext: [Circular], _idlePrev: [Object] },
_idleStart: 1426765947035,
_monotonicStartTime: 121119713,
parser:
{ _headers: [],
_url: '',
onHeaders: [Function: parserOnHeaders],
onHeadersComplete: [Function: parserOnHeadersComplete],
onBody: [Function: parserOnBody],
onMessageComplete: [Function: parserOnMessageComplete],
socket: [Circular],
incoming: [Object],
maxHeaderPairs: 2000,
onIncoming: [Function] },
ondata: [Function],
_paused: false,
_httpMessage: [Circular] },
connection:
{ _connecting: false,
_handle:
{ fd: 24,
writeQueueSize: 0,
owner: [Circular],
onread: [Function: onread],
reading: true },
_readableState:
{ highWaterMark: 16384,
buffer: [],
length: 0,
pipes: null,
pipesCount: 0,
flowing: false,
ended: false,
endEmitted: false,
reading: true,
calledRead: true,
sync: false,
needReadable: true,
emittedReadable: false,
readableListening: false,
objectMode: false,
defaultEncoding: 'utf8',
ranOut: false,
awaitDrain: 0,
readingMore: false,
decoder: null,
encoding: null },
readable: true,
domain: null,
_events:
{ end: [Object],
finish: [Function: onSocketFinish],
_socketEnd: [Function: onSocketEnd],
drain: [Object],
timeout: [Function],
error: [Function],
close: [Object] },
_maxListeners: 10,
_writableState:
{ highWaterMark: 16384,
objectMode: false,
needDrain: false,
ending: false,
ended: false,
finished: false,
decodeStrings: false,
defaultEncoding: 'utf8',
length: 0,
writing: false,
sync: false,
bufferProcessing: false,
onwrite: [Function],
writecb: null,
writelen: 0,
buffer: [],
errorEmitted: false },
writable: true,
allowHalfOpen: true,
onend: [Function],
destroyed: false,
bytesRead: 3233,
_bytesDispatched: 306029,
_pendingData: null,
_pendingEncoding: '',
server:
{ domain: null,
_events: [Object],
_maxListeners: 10,
_connections: 6,
connections: [Getter/Setter],
_handle: [Object],
_usingSlaves: false,
_slaves: [],
allowHalfOpen: true,
httpAllowHalfOpen: false,
timeout: 120000,
_connectionKey: '4:0.0.0.0:3000' },
_idleTimeout: 120000,
_idleNext:
{ _connecting: false,
_handle: [Object],
_readableState: [Object],
readable: true,
domain: null,
_events: [Object],
_maxListeners: 10,
_writableState: [Object],
writable: true,
allowHalfOpen: true,
onend: [Function],
destroyed: false,
bytesRead: 2662,
_bytesDispatched: 272567,
_pendingData: null,
_pendingEncoding: '',
server: [Object],
_idleTimeout: 120000,
_idleNext: [Object],
_idlePrev: [Circular],
_idleStart: 1426765947031,
_monotonicStartTime: 121119709,
parser: [Object],
ondata: [Function],
_paused: false,
_httpMessage: null },
_idlePrev: { _idleNext: [Circular], _idlePrev: [Object] },
_idleStart: 1426765947035,
_monotonicStartTime: 121119713,
parser:
{ _headers: [],
_url: '',
onHeaders: [Function: parserOnHeaders],
onHeadersComplete: [Function: parserOnHeadersComplete],
onBody: [Function: parserOnBody],
onMessageComplete: [Function: parserOnMessageComplete],
socket: [Circular],
incoming: [Object],
maxHeaderPairs: 2000,
onIncoming: [Function] },
ondata: [Function],
_paused: false,
_httpMessage: [Circular] },
app:
{ [Function: app]
use: [Function],
handle: [Function],
listen: [Function],
setMaxListeners: [Function: setMaxListeners],
emit: [Function: emit],
addListener: [Function: addListener],
on: [Function: addListener],
once: [Function: once],
removeListener: [Function: removeListener],
removeAllListeners: [Function: removeAllListeners],
listeners: [Function: listeners],
route: '/',
stack:
[ [Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object] ],
init: [Function],
defaultConfiguration: [Function],
engine: [Function],
param: [Function],
set: [Function],
path: [Function],
enabled: [Function],
disabled: [Function],
enable: [Function],
disable: [Function],
configure: [Function],
get: [Function],
post: [Function],
put: [Function],
head: [Function],
delete: [Function],
options: [Function],
trace: [Function],
copy: [Function],
lock: [Function],
mkcol: [Function],
move: [Function],
propfind: [Function],
proppatch: [Function],
unlock: [Function],
report: [Function],
mkactivity: [Function],
checkout: [Function],
merge: [Function],
'm-search': [Function],
notify: [Function],
subscribe: [Function],
unsubscribe: [Function],
patch: [Function],
all: [Function],
del: [Function],
render: [Function],
request: {},
response: {},
cache: {},
settings:
{ 'x-powered-by': true,
env: 'development',
views: '/Users/jaitor/Documents/f1racing/app/server/views',
'jsonp callback name': 'callback',
'json spaces': 2,
port: 3000,
'view engine': 'jade' },
engines: {},
viewCallbacks: [],
_events: { mount: [Function] },
_router:
{ map: [Object],
params: {},
_params: [],
caseSensitive: false,
strict: false,
middleware: [Function: router] },
routes: { get: [Object], post: [Object] },
router: [Getter],
locals: { [Function: locals] settings: [Object], pretty: true },
_usedRouter: true },
_headers: { 'x-powered-by': 'Express' },
_headerNames: { 'x-powered-by': 'X-Powered-By' },
req:
{ _readableState:
{ highWaterMark: 16384,
buffer: [],
length: 0,
pipes: null,
pipesCount: 0,
flowing: false,
ended: true,
endEmitted: true,
reading: false,
calledRead: true,
sync: false,
needReadable: true,
emittedReadable: false,
readableListening: false,
objectMode: false,
defaultEncoding: 'utf8',
ranOut: false,
awaitDrain: 0,
readingMore: false,
decoder: null,
encoding: null },
readable: false,
domain: null,
_events: { data: [Object], readable: [Function], end: [Object] },
_maxListeners: 10,
socket:
{ _connecting: false,
_handle: [Object],
_readableState: [Object],
readable: true,
domain: null,
_events: [Object],
_maxListeners: 10,
_writableState: [Object],
writable: true,
allowHalfOpen: true,
onend: [Function],
destroyed: false,
bytesRead: 3233,
_bytesDispatched: 306029,
_pendingData: null,
_pendingEncoding: '',
server: [Object],
_idleTimeout: 120000,
_idleNext: [Object],
_idlePrev: [Object],
_idleStart: 1426765947035,
_monotonicStartTime: 121119713,
parser: [Object],
ondata: [Function],
_paused: false,
_httpMessage: [Circular] },
connection:
{ _connecting: false,
_handle: [Object],
_readableState: [Object],
readable: true,
domain: null,
_events: [Object],
_maxListeners: 10,
_writableState: [Object],
writable: true,
allowHalfOpen: true,
onend: [Function],
destroyed: false,
bytesRead: 3233,
_bytesDispatched: 306029,
_pendingData: null,
_pendingEncoding: '',
server: [Object],
_idleTimeout: 120000,
_idleNext: [Object],
_idlePrev: [Object],
_idleStart: 1426765947035,
_monotonicStartTime: 121119713,
parser: [Object],
ondata: [Function],
_paused: false,
_httpMessage: [Circular] },
httpVersion: '1.1',
complete: true,
headers:
{ host: 'localhost:3000',
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:36.0) Gecko/20100101 Firefox/36.0',
accept: '*/*',
'accept-language': 'es-ES,es;q=0.8,en-US;q=0.5,en;q=0.3',
'accept-encoding': 'gzip, deflate',
'x-requested-with': 'XMLHttpRequest',
referer: 'http://localhost:3000/es/myteam.html?community=54e07946e4b0dff6d40bde1c',
cookie: 's_fid=79F1544C1E84B837-2BDACE625059FB4C; s_lv=1422809809979; connect.sid=s%3AFVYUZZh5S6Qj1qV8Zu964p9z.gwbNG3tC0qzr8llFHlpaUjURED%2Bm26lGZ3vYYu%2BloOM',
connection: 'keep-alive' },
trailers: {},
_pendings: [],
_pendingIndex: 0,
url: '/getraces?community=54e07946e4b0dff6d40bde1c',
method: 'GET',
statusCode: null,
client:
{ _connecting: false,
_handle: [Object],
_readableState: [Object],
readable: true,
domain: null,
_events: [Object],
_maxListeners: 10,
_writableState: [Object],
writable: true,
allowHalfOpen: true,
onend: [Function],
destroyed: false,
bytesRead: 3233,
_bytesDispatched: 306029,
_pendingData: null,
_pendingEncoding: '',
server: [Object],
_idleTimeout: 120000,
_idleNext: [Object],
_idlePrev: [Object],
_idleStart: 1426765947035,
_monotonicStartTime: 121119713,
parser: [Object],
ondata: [Function],
_paused: false,
_httpMessage: [Circular] },
_consuming: true,
_dumped: false,
httpVersionMajor: 1,
httpVersionMinor: 1,
upgrade: false,
originalUrl: '/getraces?community=54e07946e4b0dff6d40bde1c',
_parsedUrl:
{ protocol: null,
slashes: null,
auth: null,
host: null,
port: null,
hostname: null,
hash: null,
search: '?community=54e07946e4b0dff6d40bde1c',
query: 'community=54e07946e4b0dff6d40bde1c',
pathname: '/getraces',
path: '/getraces?community=54e07946e4b0dff6d40bde1c',
href: '/getraces?community=54e07946e4b0dff6d40bde1c' },
query: { community: '54e07946e4b0dff6d40bde1c' },
app:
{ [Function: app]
use: [Function],
handle: [Function],
listen: [Function],
setMaxListeners: [Function: setMaxListeners],
emit: [Function: emit],
addListener: [Function: addListener],
on: [Function: addListener],
once: [Function: once],
removeListener: [Function: removeListener],
removeAllListeners: [Function: removeAllListeners],
listeners: [Function: listeners],
route: '/',
stack: [Object],
init: [Function],
defaultConfiguration: [Function],
engine: [Function],
param: [Function],
set: [Function],
path: [Function],
enabled: [Function],
disabled: [Function],
enable: [Function],
disable: [Function],
configure: [Function],
get: [Function],
post: [Function],
put: [Function],
head: [Function],
delete: [Function],
options: [Function],
trace: [Function],
copy: [Function],
lock: [Function],
mkcol: [Function],
move: [Function],
propfind: [Function],
proppatch: [Function],
unlock: [Function],
report: [Function],
mkactivity: [Function],
checkout: [Function],
merge: [Function],
'm-search': [Function],
notify: [Function],
subscribe: [Function],
unsubscribe: [Function],
patch: [Function],
all: [Function],
del: [Function],
render: [Function],
request: {},
response: {},
cache: {},
settings: [Object],
engines: {},
viewCallbacks: [],
_events: [Object],
_router: [Object],
routes: [Object],
router: [Getter],
locals: [Object],
_usedRouter: true },
res: [Circular],
next: [Function: next],
body: {},
files: {},
secret: undefined,
cookies:
{ s_fid: '79F1544C1E84B837-2BDACE625059FB4C',
s_lv: '1422809809979',
'connect.sid': 's:FVYUZZh5S6Qj1qV8Zu964p9z.gwbNG3tC0qzr8llFHlpaUjURED+m26lGZ3vYYu+loOM' },
signedCookies: {},
sessionStore: { sessions: [Object], generate: [Function], _events: [Object] },
sessionID: 'FVYUZZh5S6Qj1qV8Zu964p9z',
pipe: [Function],
addListener: [Function: addListener],
on: [Function: addListener],
pause: [Function],
resume: [Function],
read: [Function],
session: { cookie: [Object] },
originalMethod: 'GET',
locale: 'es',
rawLocale:
{ code: 'es',
language: 'es',
normalized: 'es',
score: 1,
defaulted: false } },
viewCallbacks: [],
locals: [Function: locals],
end: [Function] }
{ domain: null,
_events: { finish: [Function], header: [Function] },
_maxListeners: 10,
output: [],
outputEncodings: [],
writable: true,
_last: false,
chunkedEncoding: false,
shouldKeepAlive: true,
useChunkedEncodingByDefault: true,
sendDate: true,
_headerSent: false,
_header: '',
_hasBody: true,
_trailer: '',
finished: false,
_hangupClose: false,
socket:
{ _connecting: false,
_handle:
{ fd: 24,
writeQueueSize: 0,
owner: [Circular],
onread: [Function: onread],
reading: true },
_readableState:
{ highWaterMark: 16384,
buffer: [],
length: 0,
pipes: null,
pipesCount: 0,
flowing: false,
ended: false,
endEmitted: false,
reading: true,
calledRead: true,
sync: false,
needReadable: true,
emittedReadable: false,
readableListening: false,
objectMode: false,
defaultEncoding: 'utf8',
ranOut: false,
awaitDrain: 0,
readingMore: false,
decoder: null,
encoding: null },
readable: true,
domain: null,
_events:
{ end: [Object],
finish: [Function: onSocketFinish],
_socketEnd: [Function: onSocketEnd],
drain: [Object],
timeout: [Function],
error: [Function],
close: [Object] },
_maxListeners: 10,
_writableState:
{ highWaterMark: 16384,
objectMode: false,
needDrain: false,
ending: false,
ended: false,
finished: false,
decodeStrings: false,
defaultEncoding: 'utf8',
length: 0,
writing: false,
sync: false,
bufferProcessing: false,
onwrite: [Function],
writecb: null,
writelen: 0,
buffer: [],
errorEmitted: false },
writable: true,
allowHalfOpen: true,
onend: [Function],
destroyed: false,
bytesRead: 4333,
_bytesDispatched: 312302,
_pendingData: null,
_pendingEncoding: '',
server:
{ domain: null,
_events: [Object],
_maxListeners: 10,
_connections: 6,
connections: [Getter/Setter],
_handle: [Object],
_usingSlaves: false,
_slaves: [],
allowHalfOpen: true,
httpAllowHalfOpen: false,
timeout: 120000,
_connectionKey: '4:0.0.0.0:3000' },
_idleTimeout: 120000,
_idleNext:
{ _connecting: false,
_handle: [Object],
_readableState: [Object],
readable: true,
domain: null,
_events: [Object],
_maxListeners: 10,
_writableState: [Object],
writable: true,
allowHalfOpen: true,
onend: [Function],
destroyed: false,
bytesRead: 3763,
_bytesDispatched: 289060,
_pendingData: null,
_pendingEncoding: '',
server: [Object],
_idleTimeout: 120000,
_idleNext: [Object],
_idlePrev: [Circular],
_idleStart: 1426765947154,
_monotonicStartTime: 121119832,
parser: [Object],
ondata: [Function],
_paused: false,
_httpMessage: null },
_idlePrev: { _idleNext: [Circular], _idlePrev: [Object] },
_idleStart: 1426765947654,
_monotonicStartTime: 121120332,
parser:
{ _headers: [],
_url: '',
onHeaders: [Function: parserOnHeaders],
onHeadersComplete: [Function: parserOnHeadersComplete],
onBody: [Function: parserOnBody],
onMessageComplete: [Function: parserOnMessageComplete],
socket: [Circular],
incoming: [Object],
maxHeaderPairs: 2000,
onIncoming: [Function] },
ondata: [Function],
_paused: false,
_httpMessage: [Circular] },
connection:
{ _connecting: false,
_handle:
{ fd: 24,
writeQueueSize: 0,
owner: [Circular],
onread: [Function: onread],
reading: true },
_readableState:
......... continues....}
Express version I am using: "3.4.4"
EDIT 14/07/2015. My problem still remains and I am writing more code to see if someone can help me...
My main app.js code:
var express = require('express');
var http = require('http');
var app = express();
app.configure(function(){
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/app/server/views');
app.set('view engine', 'jade');
app.locals.pretty = true;
// app.use(express.favicon());
// app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.session({ secret: 'Whateverpass',cookie:{maxAge:30 * 24 * 60*60*1000}}));
app.use(express.methodOverride());
app.use(require('stylus').middleware({ src: __dirname + '/app/public' }));
app.use(express.static(__dirname + '/app/public'));
});
if ('development' == app.get('env')) {
}
app.configure('development', function(){
app.use(express.errorHandler());
});
require('./app/server/router')(app);
var httpserver = http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
My router.js located in ('./app/server/router'):
var locale = require("locale");
var supported = new locale.Locales(["en", "es"]);
module.exports = function(app) {
app.use(locale(supported));
app.use(function(req, res, next) {
if (req.session.user == undefined) {
// if user is not logged-in redirect back to login page //
res.render('es/login', {
title: 'Hello - Please Login To Your Account'
});
} else {
next();
}
});
app.get('/', function(req, res){
[...]
});
app.post('/', function(req, res){
[...]
});
[...]
}
Try using return before your res.render or res.redirect
app.use(function(req, res, next) {
if (req.session.user == undefined) {
return res.render('es/login', { title: 'Hello - Please Login To Your Account' });
}
else {
next();
}
});
Try writing your return statement like so:
return (
res.render('es/login', {
title: 'Hello - Please Login To Your Account'
});
);

Resources