Structure of object is being modified during POST request - node.js

So I send a post request using needle with the following object as body:
{ time: 1533725993910,
rconPort: 52940,
rconPassword: 'muqrxllv',
serverPort: 38950,
unique: 795571399,
publicIP: 'localhost',
mods:
[ { modName: 'clusterio_1.0.0.zip',
hash: '341feb6c60918c83f7f3a6a14a4a308aef18dda6' },
{ modName: 'clusterio_1.13.1.zip',
hash: '6124bb9d3896b030fafbef07c971314f4640759f' },
{ modName: 'clusterio_1.13.0.zip',
hash: '3dde5199f63d87e3e6ea6ef7f522e0df5842dee4' },
{ modName: 'hotpatch-multimod_1.1.4.zip',
hash: '0a780e23c42452bd51ecc5ce808b65842e77dc85' },
{ modName: 'creative-mode_0.0.1.zip',
hash: '9af437c10d3f39f1f3ffb57c942c3a51d3786f0f' },
{ modName: 'clusterio_1.12.0.zip',
hash: '959c82380cad1a6f039de401a98dd70e13ca2224' } ],
instanceName: 'test',
playerCount: '0' }
When I console.log(req.body) in the Express handler I get
{ time: '1533722833600',
rconPort: '52940',
rconPassword: 'muqrxllv',
serverPort: '38950',
unique: '795571399',
publicIP: 'localhost',
mods: [ { modName: [Array], hash: [Array] } ],
instanceName: 'test',
playerCount: '0',
mac: '00-FF-8C-0F-21-F0' }
Upon closer inspection it turns out that the "mods" field now looks like this:
"mods":[{
"modName":[
"clusterio_1.0.0.zip",
"clusterio_1.13.0.zip",
"clusterio_1.13.1.zip",
"hotpatch-multimod_1.1.4.zip",
"creative-mode_0.0.1.zip",
"clusterio_1.12.0.zip"
],"hash":[
"341feb6c60918c83f7f3a6a14a4a308aef18dda6",
"3dde5199f63d87e3e6ea6ef7f522e0df5842dee4",
"6124bb9d3896b030fafbef07c971314f4640759f",
"0a780e23c42452bd51ecc5ce808b65842e77dc85",
"9af437c10d3f39f1f3ffb57c942c3a51d3786f0f",
"959c82380cad1a6f039de401a98dd70e13ca2224"
]}]
For logging the data on the server side I use
var app = express();
app.use(bodyParser.json());
app.use((req,res,next) => {
if(req.originalUrl == "/api/getID"){
console.log(req.body)
}
next()
});
On the client side I do
console.log(payload);
needle.post('localhost:8080/api/getID', payload, needleOptionsWithTokenAuthHeader, function (err, response, body) {
At first I suspected this was an issue with middleware, but as I am logging before all the middleware gets loaded I am not too sure about that anymore.
I have never experienced anything like this, and any help would be appreciated.

Have you tried to use the function JSON.stringify (doc) ?
Formating POST request with tables can be tricky.
To send an object like {a:1, b:{c:2, d:[3, 4]}, e:[5,6]} you have to format your parameters to fit an array associative, so the parameters will be like this:
a=1
b[c]=2
b[d][0]=3
b[d][1]=4
e[0]=5
e[1]=6
To fill a non-associative array you can try the e[]=7 notation.

Related

How to get the Authorization code in the node OIDC provider

I implemented node-OIDC-Provider in Node JS I got Id-token but I need authorize-code. So, when I hit this Api(http://localhost:3000/auth?client_id=oidcCLIENT&response_type=code&scope=openid&redirect_uri=http://localhost:3000) it throwing an error('http://localhost:3000/?error=invalid_request&error_description=Authorization%20Server%20policy%20requires%20PKCE%20to%20be%20used%20for%20this%20request'). How to fix this error and get the authorization code
Sample.js
const { Provider } = require('oidc-provider');
var express = require('express')
var app = express()
const oidc = new Provider('http://localhost:3000', {
clients: [
{
client_id: 'oidcCLIENT',
client_secret: '...',
grant_types: ['refresh_token', 'authorization_code'],
redirect_uris: ['http://localhost:3000'],
}
],
interactions: {
url(ctx, interaction) { // eslint-disable-line no-unused-vars
return `/interaction/${interaction.uid}`;
},
},
cookies: {
keys: ['some secret key', 'and also the old rotated away some time ago', 'and one more'],
},
claims: {
address: ['address'],
email: ['email', 'email_verified'],
phone: ['phone_number', 'phone_number_verified'],
profile: ['birthdate', 'family_name', 'gender', 'given_name', 'locale', 'middle_name', 'name',
'nickname', 'picture', 'preferred_username', 'profile', 'updated_at', 'website', 'zoneinfo'],
},
features: {
devInteractions: { enabled: false }, // defaults to true
deviceFlow: { enabled: true }, // defaults to false
revocation: { enabled: true }, // defaults to false
},
jwks: {
keys: [
{
d: 'VEZOsY07JTFzGTqv6cC2Y32vsfChind2I_TTuvV225_-0zrSej3XLRg8iE_u0-3GSgiGi4WImmTwmEgLo4Qp3uEcxCYbt4NMJC7fwT2i3dfRZjtZ4yJwFl0SIj8TgfQ8ptwZbFZUlcHGXZIr4nL8GXyQT0CK8wy4COfmymHrrUoyfZA154ql_OsoiupSUCRcKVvZj2JHL2KILsq_sh_l7g2dqAN8D7jYfJ58MkqlknBMa2-zi5I0-1JUOwztVNml_zGrp27UbEU60RqV3GHjoqwI6m01U7K0a8Q_SQAKYGqgepbAYOA-P4_TLl5KC4-WWBZu_rVfwgSENwWNEhw8oQ',
dp: 'E1Y-SN4bQqX7kP-bNgZ_gEv-pixJ5F_EGocHKfS56jtzRqQdTurrk4jIVpI-ZITA88lWAHxjD-OaoJUh9Jupd_lwD5Si80PyVxOMI2xaGQiF0lbKJfD38Sh8frRpgelZVaK_gm834B6SLfxKdNsP04DsJqGKktODF_fZeaGFPH0',
dq: 'F90JPxevQYOlAgEH0TUt1-3_hyxY6cfPRU2HQBaahyWrtCWpaOzenKZnvGFZdg-BuLVKjCchq3G_70OLE-XDP_ol0UTJmDTT-WyuJQdEMpt_WFF9yJGoeIu8yohfeLatU-67ukjghJ0s9CBzNE_LrGEV6Cup3FXywpSYZAV3iqc',
e: 'AQAB',
kty: 'RSA',
n: 'xwQ72P9z9OYshiQ-ntDYaPnnfwG6u9JAdLMZ5o0dmjlcyrvwQRdoFIKPnO65Q8mh6F_LDSxjxa2Yzo_wdjhbPZLjfUJXgCzm54cClXzT5twzo7lzoAfaJlkTsoZc2HFWqmcri0BuzmTFLZx2Q7wYBm0pXHmQKF0V-C1O6NWfd4mfBhbM-I1tHYSpAMgarSm22WDMDx-WWI7TEzy2QhaBVaENW9BKaKkJklocAZCxk18WhR0fckIGiWiSM5FcU1PY2jfGsTmX505Ub7P5Dz75Ygqrutd5tFrcqyPAtPTFDk8X1InxkkUwpP3nFU5o50DGhwQolGYKPGtQ-ZtmbOfcWQ',
p: '5wC6nY6Ev5FqcLPCqn9fC6R9KUuBej6NaAVOKW7GXiOJAq2WrileGKfMc9kIny20zW3uWkRLm-O-3Yzze1zFpxmqvsvCxZ5ERVZ6leiNXSu3tez71ZZwp0O9gys4knjrI-9w46l_vFuRtjL6XEeFfHEZFaNJpz-lcnb3w0okrbM',
q: '3I1qeEDslZFB8iNfpKAdWtz_Wzm6-jayT_V6aIvhvMj5mnU-Xpj75zLPQSGa9wunMlOoZW9w1wDO1FVuDhwzeOJaTm-Ds0MezeC4U6nVGyyDHb4CUA3ml2tzt4yLrqGYMT7XbADSvuWYADHw79OFjEi4T3s3tJymhaBvy1ulv8M',
qi: 'wSbXte9PcPtr788e713KHQ4waE26CzoXx-JNOgN0iqJMN6C4_XJEX-cSvCZDf4rh7xpXN6SGLVd5ibIyDJi7bbi5EQ5AXjazPbLBjRthcGXsIuZ3AtQyR0CEWNSdM7EyM5TRdyZQ9kftfz9nI03guW3iKKASETqX2vh0Z8XRjyU',
use: 'sig',
}, {
crv: 'P-256',
d: 'K9xfPv773dZR22TVUB80xouzdF7qCg5cWjPjkHyv7Ws',
kty: 'EC',
use: 'sig',
x: 'FWZ9rSkLt6Dx9E3pxLybhdM6xgR5obGsj5_pqmnz5J4',
y: '_n8G69C-A2Xl4xUW2lF0i8ZGZnk_KPYrhv4GbTGu5G4',
},
],
},
});
// express/nodejs style application callback (req, res, next) for use with express apps, see /examples/express.js
app.get('/sample', function (req, res) {
res.send('hello world')
})
app.use(oidc.callback())
// or just expose a server standalone, see /examples/standalone.js
const server = app.listen(3000, () => {
console.log('oidc-provider listening on port 3000, check http://localhost:3000/.well-known/openid-configuration');
});
How to set authorization server policy in the OIDC using node(Authorization Server policy requires PKCE to be used for this request')
I believe you need to set these options:
pkce: {
required: true
},
token_endpoint_auth_method: "none"
Also, if using PKCE, you should be sending the standard code_challenge and code_verifier methods as in steps 4 and 8 of my blog post.

Console.log(err) is crashing my website

I'm currently a student studying Web Development with Node. I recently was reviewing RESTful routes. I was building a blog site to do so. I was setting up a route to show a specific blog "/blogs/:id" which lets you see all the contents of a blog. Here's the route:
app.get("/blogs/:id", function(req, res){
blog.findById(req.params.id, function(err, blog){
if(err){
console.log(err)
} else{
res.render("show", {body: blog});
}
})
})
When I access the route using the browser, it loads forever and I get the following error in the terminal:
{ CastError: Cast to ObjectId failed for value "app.css" at path "_id" for model "blog"
at MongooseError.CastError (/home/ubuntu/workspace/RESTful/node_modules/mongoose/lib/error/cast.js:29:11)
at ObjectId.cast (/home/ubuntu/workspace/RESTful/node_modules/mongoose/lib/schema/objectid.js:158:13)
at ObjectId.SchemaType.applySetters (/home/ubuntu/workspace/RESTful/node_modules/mongoose/lib/schematype.js:724:12)
at ObjectId.SchemaType._castForQuery (/home/ubuntu/workspace/RESTful/node_modules/mongoose/lib/schematype.js:1113:15)
at ObjectId.SchemaType.castForQuery (/home/ubuntu/workspace/RESTful/node_modules/mongoose/lib/schematype.js:1103:15)
at ObjectId.SchemaType.castForQueryWrapper (/home/ubuntu/workspace/RESTful/node_modules/mongoose/lib/schematype.js:1082:15)
at cast (/home/ubuntu/workspace/RESTful/node_modules/mongoose/lib/cast.js:303:32)
at Query.cast (/home/ubuntu/workspace/RESTful/node_modules/mongoose/lib/query.js:3355:12)
at Query._castConditions (/home/ubuntu/workspace/RESTful/node_modules/mongoose/lib/query.js:1327:10)
at Query._findOne (/home/ubuntu/workspace/RESTful/node_modules/mongoose/lib/query.js:1552:8)
at process.nextTick (/home/ubuntu/workspace/RESTful/node_modules/kareem/index.js:333:33)
at _combinedTickCallback (internal/process/next_tick.js:73:7)
at process._tickCallback (internal/process/next_tick.js:104:9)
message: 'Cast to ObjectId failed for value "app.css" at path "_id" for model "blog"',
name: 'CastError',
stringValue: '"app.css"',
kind: 'ObjectId',
value: 'app.css',
path: '_id',
reason: undefined,
model:
{ [Function: model]
hooks: Kareem { _pres: [Object], _posts: [Object] },
base:
Mongoose {
connections: [Object],
models: [Object],
modelSchemas: [Object],
options: [Object],
_pluralize: [Function: pluralize],
plugins: [Object] },
modelName: 'blog',
model: [Function: model],
db:
NativeConnection {
base: [Object],
collections: [Object],
models: [Object],
config: [Object],
replica: false,
options: null,
otherDbs: [],
relatedDbs: {},
states: [Object],
_readyState: 1,
_closeCalled: false,
_hasOpened: true,
_listening: false,
_connectionOptions: [Object],
client: [Object],
name: 'restful_routing_revision',
'$initialConnection': [Object],
db: [Object] },
discriminators: undefined,
'$appliedMethods': true,
'$appliedHooks': true,
schema:
Schema {
obj: [Object],
paths: [Object],
aliases: {},
subpaths: {},
virtuals: [Object],
singleNestedPaths: {},
nested: {},
inherits: {},
callQueue: [],
_indexes: [],
methods: {},
methodOptions: {},
statics: {},
tree: [Object],
query: {},
childSchemas: [],
plugins: [Object],
s: [Object],
_userProvidedOptions: {},
options: [Object],
'$globalPluginsApplied': true,
_requiredpaths: [] },
collection:
NativeCollection {
collection: [Object],
opts: [Object],
name: 'blogs',
collectionName: 'blogs',
conn: [Object],
queue: [],
buffer: false,
emitter: [Object] },
Query: { [Function] base: [Object] },
'$__insertMany': [Function],
'$init': Promise { [Object], catch: [Function] } } }
But for some reason, when I change the callback to be the following:
app.get("/blogs/:id", function(req, res){
blog.findById(req.params.id, function(err, blog){
if(err){
res.redirect("/")
} else{
res.render("show", {body: blog});
}
})
})
The website works perfectly fine. I also tried removing the header from the show.ejs(the file being rendered when accessing the route) while keeping the console.log(err) and it also solved the problem. I tried removing the header because the header contains the tag that links the app.css file which I saw mentioned in the error. I would like to know what's wrong in console.log(err) with the css file.
p.s. I am using Expres for the routes and mongoose to access the MongoDB database. "blog" is the array of blogs. Incase you want to take a look at my show.ejs file, here it is:
<% include partials/header %>
<h1><%= body.title%></h1>
<img src="<%=body.image%>">
<p><%=body.body%></p>
<div><%=body.created%></div>
<% include partials/footer %>
And if you want to take a look at the app.css file, here it is:
img{
max-width: 600px;
width: 600px;
}
And if you want to take a look at the header.ejs file, here it si:
<!DOCTYPE html>
<html>
<head>
<title>Blogs Website</title>
<link rel="stylesheet" type="text/css" href="app.css">
</head>
<body>
Here is the full app.js file (the file containing the routes):
var express = require("express"),
app = express(),
mongo = require("mongoose"),
bodyParser = require("body-parser"),
expressSanitizer = require("express-sanitizer"),
methodOverride = require("method-override");
mongo.connect("mongodb://localhost/restful_routing_revision");
app.use(bodyParser.urlencoded({extended: true}));
app.use(expressSanitizer());
app.set("view engine", "ejs");
app.use(express.static("public"));
app.use(methodOverride('_method'));
var blogSchema = new mongo.Schema({
title: String,
body: String,
image: String,
created: {type: Date, default: Date.now}
});
var blog = mongo.model("blog", blogSchema);
app.get("/", function(req, res){
res.render("landing");
});
app.get("/blogs", function(req, res){
blog.find({}, function(err, body){
if(err){
console.log(err)
}else{
res.render("index", {blogs: body})
}
})
})
app.get("/dogs/new", function(req, res){
res.render("new");
})
app.post("/dogs", function(req, res){
var blogBody = req.body.blog;
blog.create(blogBody, function(err, body){
if(err){
console.log(err)
}else{
res.redirect("/blogs")
}
})
})
app.get("/blogs/:id", function(req, res){
blog.findById(req.params.id, function(err, blog){
if(err){
// res.redirect("/")
console.log(err)
} else{
res.render("show", {body: blog});
}
})
})
// blog.findById(req.params.id, function(err, blog){
// if(err){
// res.redirect("/");
// } else {
// res.render("show", {body: blog});
// }
// });
// });
app.listen(process.env.PORT, process.env.IP, function(){
console.log("The Server has Started!!!!");
})
There are alot of npm packages on top that I'm planning to use later. And I know that the blog Schema isn't well formatted. I also tried doing console.log(err) and res.redirect("/") at the same time, I arrive to the show page but still get the same error.
Just use absolute path /style.css instead of relative path style.css.
Explanation:
You are using app.use(express.static("public")); which will make the route app.get("/blogs/:id", function(req, res){...}); when triggered it tries to render style.css in your html link tag because it meets the route path as /blogs/style.css since your public folder is in the same level with blogs, so by putting / in front of style.css makes it an absolute path, so execution will start the path from the seed, and not continue down from blogs.
Another solution is to just handle triggering the route blogs/style.css by actually creating a route for it as follows:
app.get('/campgrounds/app.css', function(req, res) {
break;
});
Make sure to put it before the route app.get("/blogs/:id", function(req, res){...}); to be executed first, if triggered.
I hope this helps.
Regarding the CastError, I don't know what is going on in the underlying ejs code that causes it to try to run a Mongo query with the css filename, but this post explains how to fix your syntax (read the answer's comments about using a relative path for the css name):
NodeJS error when rendering page:Cast to ObjectId failed for value "styles.css" at path "_id"
I think that will get rid of the error in your endpoint.
For the headline question about crashing the server and the observation that:
When I access the route using the browser, it loads forever
is because the endpoint does not ever issue a response to the client when you get an error. All endpoints need to respond to the client in some way. In your case, the documented1 recommendation is to call the Express middleware function next:
blog.findById(req.params.id, function(err, blog){
if(err){
console.log(err);
next(err);
} else{
The next function will return an error result to the client browser. You need to use next because the .find function of your Mongoose model is asynchronous and Expresses next function is designed to deal with this correctly.
A separate detail, from what you posted, your Express server is most likely not crashing. It is logging the console message with an error just like you asked then continuing on waiting for new requests (logging an error to the console is perfectly ok!). If it crashed, you would likely get a 500 error page in the browser and the node process would terminate. I mention this in hopes to help future debugging. I think if you had searched on the client issue of the endpoint not returning, you would likely have found an existing answer about endpoints that never return to the client (this is a common issue to run into when getting started). I hope that helps!
Express Error Handling Doc
You have to put this line at the end
In app.js file
cut this line and paste it at the end:
app.use(express.static("public"));

jwt config secret file push on git

I work on an node, express mongoose API with JWT (json web token). I don't push my config.js file to keep secret my key (.gitignore -> config.js) but when travis run my test with mocha it return the error : Cannot find module './config'.
I try to mock it but it doesn't work, so :
I can push my config.js file, it's not unsafe ?
How can i mock my require dependency config.js ?
You should push config.js in repo. But you should make it like this:
/*jshint esversion: 6 */
'use strict';
module.exports = function () {
return {
SERVER_HOST: process.env.HOST,
OTP: {
LENGTH: 6,
DURATION: 300000, //ms
},
TWILIO: {
ACCOUNT_SID: process.env.TWILIO_ACCOUNT_SID,
AUTH_TOKEN: process.env.TWILIO_AUTH_TOKEN,
MESSAGE_FROM: process.env.TWILIO_MESSAGE_FROM
},
JWT: {
SECRET: process.env.JWT_SECRET,
ALGORITHM: 'HS512',
ISSUER: 'GOHAN'
},
BCRYPT: {
SALT_ROUNDS: 10
},
EMAIL: {
USER: process.env.EMAIL_USER,
PASSWORD: process.env.EMAIL_PASSWORD
},
REDIS: {
HOST: process.env.REDIS_HOST,
PORT: process.env.REDIS_PORT
},
AWS: {
ACCESS_KEY_ID: process.env.AWS_ACCESS_KEY_ID,
SECRET_ACCESS_KEY: process.env.AWS_SECRET_ACCESS_KEY,
S3: {
PROFILE_PIC_BUCKET: process.env.AWS_S3_PROFILE_PIC_BUCKET,
VOICE_MESSAGES_BUCKET: process.env.AWS_S3_VOICE_MESSAGES_BUCKET,
REGION: process.env.AWS_S3_REGION,
SIGNED_URL_EXPIRY: 900
}
},
TCP_SERVER: {
PASSWORD: process.env.TCP_SERVER_PASSWORD
},
GOOGLE_API_KEY: process.env.GOOGLE_API_KEY,
APN: {
CONNECTION: {
production: (process.env.NODE_ENV === 'production'),
cert: process.env.APN_CERT,
passphrase: process.env.APN_PASSPHRASE,
key: process.env.APN_CERT
},
FEEDBACK: {
address: process.env.APN_FEEDBACK_ADDRESS,
cert: process.env.APN_CERT,
key: process.env.APN_CERT,
passphrase: process.env.APN_PASSPHRASE,
interval: process.env.APN_INTERVAL,
batchFeedback: process.env.APN_BATCHFEEDBACK
}
},
FCM: {
API_KEY: process.env.FCM_API_KEY,
RETRY_LIMIT: 3
}
};
};
All the code should be independent of the environment, this is the purpose of environment variables. Not to ensure safety.
You can load up the environment variables before running your app.
You can have different .env files for testing, dev and prod environments also.
EDIT:
The above config.js is from a project of mine.

nodejs i18next is not translating string

I have this err:authentication:invalid_token in json file. folder is setup as locales/vi_VN/mynamespace-vi_VN.json. However, it's not translating in the console.log below.
Any idea why?
i18n.init({
debug: true,
preload: ['vi_VN'],
resGetPath: 'locales/__lng__/__ns__-__lng__.json',
lng: 'en_GB',
ns: 'mynamespace',
sendMissingTo: 'fallback',
fallbackLng: 'en_GB'
}, function(err, t) {
console.log('i18n is initialized.')
console.log('Translation on:', t('err:authentication:invalid_token', {
lng: 'vi_VN'
}))
})
My bad, i was using colon : in identifier. I need to change it to something else or put it in appropriate namespace

ExpressJS res.render() error (JSON.stringify can't work on circular reference)

What's wrong here?
res.render('/somepage', {user:req.session.user})
It leads to Converting circular structure to JSON errors, (results in session element that has a circular user reference.)
exports.home = function (req, res) {
var entityFactory = new require('../lib/entity-factory.js').EntityFactory();
entityFactory.get_job_task_lists({
callback : function (err, job_task_lists) {
res.render('home.jade', {
locals:{
title: 'Logged in.',
user:req.session.user, // does not work
job_task_lists:job_task_lists || []
}
});
}
});
};
I added some logging in node_modules/express/node_modules/connect/lib/middleware/session/memory.js
MemoryStore.prototype.set = function(sid, sess, fn){
var self = this;
process.nextTick(function(){
console.log(sess); //this is giving the output listed
self.sessions[sid] = JSON.stringify(sess);
...
This is what I expect the session to look like, in terms of structure:
{ lastAccess: 1330979534026,
cookie:
{ path: '/',
httpOnly: true,
_expires: Tue, 06 Mar 2012 00:32:14 GMT,
originalMaxAge: 14399999 },
user: // this is the object I added to the session
{ id: 1,
username: 'admin',
password: '8e3f8d3a98481a9073d2ab69f93ce73b',
creation_date: Mon, 05 Mar 2012 18:08:55 GMT } }
But here's what I find:
{ lastAccess: 1330979534079, // new session
cookie:
{ path: '/',
httpOnly: true,
_expires: Tue, 06 Mar 2012 00:32:14 GMT,
originalMaxAge: 14399999 },
user: // but here it is again, except now it's a mashup,
// containing members it shouldn't have, like locals,
// and, well, everything but the first 4 properties
{ id: 1,
username: 'admin',
password: '8e3f8d3a98481a9073d2ab69f93ce73b',
creation_date: '2012-03-05T18:08:55.701Z',
locals:
{ title: 'Logged in.',
user: [Circular], //and now it's circular
job_task_lists: [Object] },
title: 'Logged in.',
user: [Circular],
job_task_lists: [ [Object], [Object], [Object], getById: [Function] ],
attempts: [ '/home/dan/development/aqp/views/home.jade' ],
scope: {},
parentView: undefined,
root: '/home/dan/development/aqp/views',
defaultEngine: 'jade',
settings:
{ env: 'development',
hints: true,
views: '/home/dan/development/aqp/views',
'view engine': 'jade' },
app:
{ stack: [Object],
connections: 6,
allowHalfOpen: true,
_handle: [Object],
_events: [Object],
httpAllowHalfOpen: false,
cache: [Object],
settings: [Object],
redirects: {},
isCallbacks: {},
_locals: [Object],
dynamicViewHelpers: {},
errorHandlers: [],
route: '/',
routes: [Object],
router: [Getter],
__usedRouter: true },
partial: [Function],
hint: true,
filename: '/home/dan/development/aqp/views/home.jade',
layout: false,
isPartial: true } }
node.js:201
throw e; // process.nextTick error, or 'error' event on first tick
^
TypeError: Converting circular structure to JSON
at Object.stringify (native)
at Array.0 (/home/dan/development/aqp/node_modules/express/node_modules/connect/lib/middleware/session/memory.js:77:31)
at EventEmitter._tickCallback (node.js:192:40)
See how the user object is nested?
Note that this time I did not send values in explicitly with 'locals' but it ended up in one (thats the source of the circular reference.
It looks like the session is being used to transfer objects to the view.
Here's my only middleware (it only reads from the session):
function requiresAuthentication(req, res, next){
if (req.session.user){
next();
} else {
next(new Error('Unauthorized. Please log in with a valid account.'))
}
}
and the only time I modify the req.session is in this route:
app.post('/home', function (req,res,next) {
var auth = require('./lib/authentication');
auth.authenticate_user(req.body.user, function (user) {
if (user){
req.session.user = user;
console.log('authenticated');
res.redirect(req.body.redir || '/home');
//next();
} else {
console.log('not authenticated');
res.render('logins/new.jade', {title: 'Login Failed', redir:''})
}
});
});
I don't have much else going on in my application yet, as it's still quite young. I know I'm not mangling the session anywhere myself; I checked.
I did some more testing, and it appears this is only an issue when I then try to use the local variable on a page. For instance, here is my view home.jade
div(data-role="page")
div(data-role="header")
a(href='/logout', data-icon='delete', data-ajax="false") Log out
h1= title
a(href='/account', data-icon='info', data-ajax="false") Account
!= partial('user', user)
each jtl in job_task_lists
div(id=jtl.name, class = 'draggable_item', style='border:2px solid black;')
#{jtl.name} - #{jtl.description}
a(data-icon='plus')
div(data-role="footer")
h3 footer
script(src="/javascripts/home.js")
If I comment out the user partial, it renders, else I get this Converting circular structure to JSON issue.
UPDATE
So after hooking up eclipse and the v8 debugger, I have been stepping through the code and I know where the mashup of session and user objects is occurring,
in node_modules/connect/lib/middleware/session/session.js
utils.union ends up mashing the members of the user object into the session, causing the circular reference. I'm just not sure why (admittedly probably my code)
This was a problem with session data being modified in a view.
After much digging, I found that it was a bug in the way partials are handled in 2.5.8. I submitted an issue, and subsequently a patch. (in case anyone needs this info at a future date) as npm is still serving up Express 2.5.8 AFAIK.
Thanks for your help #freakish and #Ryan

Resources