Parsing JSON in node express - ends up with \n between delimiters? - javascript

I'm sending an Ajax request to an express endpoint, like so:
var postData = {
method: "POST",
url: "/order/address",
data: { order: JSON.stringify(addressFields) },
cache: false
};
updateAjax = $.ajax(postData).done(function(data) {
The address object being sent is a JSON array. I have confirmed it is not already stringified prior to doing this in the post data object.
It posts to a server running node express, with a path of /order/address.
The express route is as follows, only showing up to the point the json gets parsed, as it's the only relevant parts of this:
router.route('/')
.post(function (req, res, next) {
// prevents caching of customer information
res.header('Cache-Control', 'private, no-cache, no-store, must-revalidate');
const addresses = JSON.parse(req.body.order);
Prior to being parsed, req.body.order is :
[{\"isDefaultShipping\":true,\"firstName\":\"\",\"lastName\":\"\",\"street1\":\"\",\"street2\":\"\",\"city\":\"\",\"postcode\":\"\",\"region\":\"\",\"country\":\"GB\",\"phone\":\"\",\"isDefaultBilling\":true}]
And, here is the problem I'm having, after parsing it ends up as an invalid JSON object:
[\n {\n isDefaultShipping: true,\n firstName: '',\n lastName: '',\n street1: '',\n street2: '',\n city: '',\n postcode: '',\n region: '',\n country: 'GB',\n phone: '',\n isDefaultBilling: true\n }\n]
I have been unable to remove the line breaks - and I guess there's line breaks that are not visible, within the stringified data that is being parsed - but I can't for the life of me remove them?
EDIT: Someone has kindly pointed out my stupidity (politely), that the output above, with the \n linebreaks, is my logger, so ignore that part.
Leaving it in there - well, because it would be rude to remove this part of my question that I got an answer on.
Postman shows the following issue as it hits the JSON.parse line in the route:
SyntaxError: Unexpected token u in JSON at position 0\n at JSON.parse (<anonymous>)

Just replace \n
router.route('/')
.post(function (req, res, next) {
// prevents caching of customer information
res.header('Cache-Control', 'private, no-cache, no-store, must-revalidate');
const addresses = JSON.parse(req.body.order).replace(\[\n]+\, '');

Related

sending value of my textarea with graphql

I hope you all have a great day. I am coding my own personal website and I have a section called to contact me. The problem I have with this section is that I am trying to send my client email to my email and when I am trying to send their message to my server through Graphql I get this error
[
{
"message": "Syntax Error: Unterminated string.",
"locations": [
{
"line": 3,
"column": 123
}
]
}
]
the request I sent to my server is
'\n mutation{\n sendEmail(EmailInput: {name: "Test name", email: "Test#email.com",
subject: "this is test subject", message: "\n
this is the first line \nthis is the second line\nwhen I have multiple lines I have these problem\n
"}) {\n success\n message\n }\n }\n '
I don't know how to fix it I don't know why I get this error.
I used fetch to send my code backend :
const emailMutationQuery = `
mutation{
sendEmail(EmailInput: {name: "${senderName.value}", email: "${senderEmail.value}", subject: "${senderSubject.value}", message: "
${senderMessage.value}
"}) {
success
message
}
}
`;
const result = await fetch("http://localhost:2882/graphql", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
query: emailMutationQuery,
}),
});
const convertedResult = await result.json();
GraphQL supports variables, which can be used to supply input data separately from the query. The variables are just a separate JSON-encoded object. This avoids syntactic difficulties (and potential security risks!) from trying to embed the inputs directly in the query.
For this you'd write a fixed query, that declares and uses the variable, but doesn't depend on the per-request inputs
const emailMutationQuery = `
mutation SendEmail($emailInput: SendEmailInput!) {
sendEmail(EmailInput: $emailInput) {
success
message
}
}
`;
You'd then create a second object containing the variable(s). The top-level keys match what you declare in the GraphQL operation line, and their content matches the corresponding GraphQL input types.
const variables = {
emailInput: {
name: senderName.value,
email: senderEmail.value,
subject: senderSubject.value,
message: senderMessage.value
}
};
Note that this is an ordinary Javascript object, and we haven't quoted or escaped anything here.
Now when we make the request, we send the query and variables together
const result = await fetch("http://localhost:2882/graphql", {
...,
body: JSON.stringify({
query: emailMutationQuery,
variables: variables
})
});
Things like newlines in the message content will be escaped in the variables block, and get passed through correctly to the underlying GraphQL engine.
I actually find a solution for it but feel free to share your answers here. The solution I found for this problem was that you have to use JSON.stringify() for the textarea. you have to pass your textarea value to this function and js will take care of the rest. my code now looks like this
const emailMutationQuery = `
mutation{
sendEmail(EmailInput: {name: "${senderName.value}", email: "${senderEmail.value}", subject: "${senderSubject.value}",
message:${JSON.stringify(senderMessage.value)}}) {
success
message
}
}
`;
I hope this help you guys.

mongoose Model.save() only returns { _id, __v }

I know this question has been asked before but I feel like I'm doing everything right and I'm still having an issue. I want to save an item from a form into my mongodb collection using mongoose.
My schema:
// stationmodel.js
export const StationSchema = new mongoose.Schema({
"FDID": String,
"Fire dept name": String,
"HQ addr1": String,
"HQ city": String,
"HQ state": String,
"HQ zip": Number,
"HQ phone": String,
"Dept Type": String,
"Organization Type": String,
"Website": String,
"Number Of Stations": Number,
"Primary agency for emergency mgmt": Boolean,
}, {collection: "FEMA_stations"})
In my express app:
// in routes.js
const StationSchema = require('./stationmodel')
const Station = mongoose.model('Station', StationSchema, 'FEMA_stations')
const addstation = (req, res) => {
console.log(req.body)
const newStation = new Station(req.body)
newStation.save( function(err){
if (err) { console.error(err) }
console.log('newStation after save', newStation)
})
}
const routes = app => {
app.route('/api/addstation')
.post(addstation)
}
export default routes
// in index.js
import routes from './routes'
app.use(bodyParser.urlencoded({ extended: true }))
app.use(bodyParser.json())
routes(app)
In my front end code, calling to the backend in a redux action:
fetch('/api/addstation', {
method: "POST",
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(stationToAdd)
})
When I console.log(req.body) on my back end, I get the data I'm expecting. It looks something like this:
{
FDID: '202020',
'Fire dept name': 'Some Fire Department',
'HQ addr1': 'Some address',
'HQ city': 'San Dimas',
'HQ state': 'CA',
'HQ zip': 99999,
'HQ phone': '5555555555',
'Dept Type': 'Career',
'Organization Type': 'State',
Website: '',
'Number Of Stations': 0,
'Primary agency for emergency mgmt': true,
}
But when I console.log my newStation that I'm trying to .save(), all I get is a response like this:
{ _id: 5efe29911ea067248f3c39a0, __v: 0 }
I know other people had issues with their schema, their model, making sure that they're truly connected to their mongodb collection, or making sure that the request is made with the application/json header, but I feel I have all those things right. The code was pieced together from a much more modularized app to try to cut the fat and present the core issue, so let me know if I'm missing any glaring information.
What might be going wrong here? Why is the data from req.body not making it into my new document that I'm trying to save to the collection? Thanks for reading.
You are mixing es6 module import/export with Node.js CommonJS require.
In stationmodel.js You are using a "named export"
export const StationSchema = new mongoose.Schema(...
But in routes.js you are using CommonJS require
const StationSchema = require('./stationmodel')
Which is likely to be an empty object. So the following line will create a model with an "empty" schema
const Station = mongoose.model('Station', StationSchema, 'FEMA_stations')
The solution
use named import instead
import { StationSchema } from './stationmodel'
TIP:
Since you are already name the file stationmodel.js, which suggests it's a model. You can put the following in stationmodel.js directly to prevent the model from getting incorrect schema
export const Station = mongoose.model('Station', StationSchema, 'FEMA_stations')

Emails with attachments come up empty using Nodemailer

I'm trying to send an e-mail with an attachment using Nodemailer. No matter what I do, if I specify an attachments property, the e-mail comes up empty (no attachments, no html, no text). Sending an e-mail without any attachments works as expected. Here's the code I have so far:
transporter.sendMail({
to: `${toTitleCase(i.nome)} <${i.email}>`,
subject: 'Treinamentos',
text: 'hello!',
html: `Embedded image: <img src="cid:nyan#example.com"/>`,
attachments: [
{
filename: 'newimg.jpg',
path: __dirname + '/src/img/newimg.jpg',
cid: 'nyan#example.com'
}
]
}, (err, info )=> {
console.log(err);
console.log(info);
});
I have also tried using content instead of path, same result. I should also note that the err callback is empty.
I figured it out. I had set 'Content-type': 'text/html; charset=UTF-8' as the header on the transporter object. Removing that line fixed the issue.

Node requestify fails when body includes special chars

Im using node.js and a library called requestify.
The code looks like this:
console.log('body');
console.log(body);
return new Promise(function (f, r) {
requestify.request(myurl, {
method: 'POST',
body : body,
headers : {
"Content-Type" : "application/json; charset=utf-8"
}
})
.then(function (response) {
f({messge : "Success"});
}, function (err) {
console.log(err);
err.code == 405 ? r(err.body) : r({ success: false, message: err });
});
});
When the request contains special characters (in this case swedish characters) then it throws an error.
Sending exactly the same request without the swedish characters, the request succedes.
I dont really have access to the server that is handling the request that's why it is hard to debug.
But I print the body before sending the request and I cannot see any strange things in it.
Here are the 2 different body-requests:
//FAILURE
{ eventType: 'createUser',
eventId: '1e2ca3b4-0f6b-4ed9-ae79-2e112c8d693c',
version: '0.1',
date: 2016-10-07T06:42:26.209Z,
attributes:
{ userName: 'akeandersson#gmail.se',
email: 'akeandersson#gmail.se',
firstName: 'Åke',
lastName: 'Andresson',
phoneNumber: '1',
identifier: '198509120328',
assignment: 'se.me',
role: [ 'se.me.role.user' ] },
metadata: {} }
//SUCCESS
{ eventType: 'createUser',
eventId: '1e2ca3b4-0f6b-4ed9-ae79-2e112c8d693c',
version: '0.1',
date: 2016-10-07T06:44:09.857Z,
attributes:
{ userName: 'akeandersson212#gmail.se',
email: 'akeandersson212#gmail.se',
firstName: 'Ake',
lastName: 'Andresson',
phoneNumber: '9',
identifier: '196606095823',
assignment: 'se.me',
role: [ 'se.me.role.user' ] },
metadata: {} }
I also put "; charset=utf-8" in the header's content-type (by default it is already utf-8 according to requestify documentation).
But still the same result. Any idea how I could debug this?
This is what the server returns when the request fails:
{
code: 400,
headers:
{ connection: 'close',
'content-type': 'text/plain',
'content-length': '244',
date: 'Fri, 07 Oct 2016 06:42:27 GMT' },
body: 'Unexpected end-of-input: expected close marker for OBJECT (from [Source: ServletInputStreamImpl#75eb88e4; line: 1, column: 0])\n at [Source: ServletInputStreamImpl#75eb88e4; line: 1, column: 767]' }
I guess, you need to upload your requestify module to the most recent version. I use version 0.2.3 which doesn't throw me any error.
Assuming that you encounter an error while trying to read a norwegian (or) swedish character, I have tried reading a website which has norwegian characters in it, and with the below code, I'm able to output it to the console without any error. Same with a swedish page too. I'm using 0.2.3 version though (which is the most recent version). I have not set the encoding to UTF-8 too.
var requestify = require('requestify');
requestify.get('http://www.norwegian4people.com/lesson.php?id=41').then(function(response) {
// Get the response body
console.log(response.getBody());
});
Hope this helps!

Expressjs How to properly pass an array from the client and utilize it?

I have an object that look like this:
editinvite: {
_id: '',
title: '',
codes_list: []
}
The problem is that I can't access codes_list in my NodeJS app. It shows as 'undefined' (other non-array variables work fine though)
router.post('/inviteEdit', function (req, res) {
...
console.log(req.body.codes_list);
// Output:
undefined
Note that I'm trying to use codes_list as it is, I mean I want to pass it directly to my update parameters:
var update = {
title: req.body.title,
codes_list: req.body.codes_list,
};
(extra info) Output of console.log(req.body):
{ _id: '565981a16a75a7522afdcc8b',
title: 'as',
'codes_list[0][code]': '0EHC',
'codes_list[0][_id]': '565981a16a75a7522afdcc8c',
'codes_list[0][used]': 'false',
'codes_list[1][code]': 'VDQ2',
'codes_list[1][_id]': '565981a16a75a7522afdcc8d',
'codes_list[1][used]': 'false' }
(extra info) editinvite object before sending, looks like this on FF debugger:
(extra info) My ajax call:
$.ajax({
type: 'post',
url: this.server + '/inviteEdit',
dataType: 'json',
data: this.editinvite,
crossDomain: true,
success: function (data, status, jqXHR) {
...
(extra info) I'm using these parameters in node app
app.use(bodyParser.urlencoded({
extended: false
}));
app.use(bodyParser.json());
Quoting from body-parser documentation:
bodyParser.urlencoded(options) returns middleware that only parses
urlencoded bodies. This parser accepts only UTF-8 encoding of the body and supports automatic inflation of gzip and deflate encodings.
A new body object containing the parsed data is populated on the
request object after the middleware (i.e. req.body). This object will
contain key-value pairs, where the value can be a string or array
(when extended is false), or any type (when extended is true).
So basically if you just want string or array to be parsed you can set extended to false, for other types (like in your case array of objects) you need to set it to true.

Categories