Node Express - empty query after form submit - forms

I would like to pars url after form submit.
I have simple form:
form(method='post', action='/recipe/create')
hr
div
div.input.text
label(for='recipeTitle') Tytuł przepisu:
input(type='text', name='recipeTitle', id='recipeTitle')
div.input.text
label(for='photoFileName') Nazwa zdjęcia:
input(type='text', name='photoFileName', id='photoFileName')
After submit this code is executed.
exports.create = function(req, res){
var url = require('url');
var url_parts = url.parse(req.url, true);
console.log(url_parts);
My question is why console shows empty query
{ protocol: null,
slashes: null,
auth: null,
host: null,
port: null,
hostname: null,
hash: null,
search: '',
query: {},
pathname: '/recipe/create',
path: '/recipe/create',
href: '/recipe/create' }

This happens because you're posting to an URL which doesn't have a query string - /recipe/create.
Also, you seem to be using Express, which will give you the current query string already parsed:
// GET /search?q=tobi+ferret
req.query.q
// => "tobi ferret"
// GET /shoes?order=desc&shoe[color]=blue&shoe[type]=converse
req.query.order
// => "desc"
req.query.shoe.color
// => "blue"
req.query.shoe.type
// => "converse"
Reference

Related

How to display a UUID in pg-promise without dashes

As per the stackoverflow question HERE postgres column does not store dashes for the UUID data type
Yet when I load the value of any UUID column using pg-promise it always shows dashes
How do I retrieve these UUIDs without dashes using pg-promise
Code sample illustrating the problem
var pgPromise = require("pg-promise"),
pgp = pgPromise({}),
db = pgp({
database: "mydatabase",
host: "localhost",
password: "somepass",
port: 5432,
ssl: false,
user: "myuser"
});
pgp.pg.types.setTypeParser(20, parseInt);
db.query("CREATE TABLE test(myid uuid not null primary key)")
.then((e => {
var r = require("crypto").createHash("md5").update("test data").digest("hex");
return db.query("INSERT INTO test(myid) VALUES($1) ON CONFLICT DO NOTHING", [r])
}))
.then((e => db.query("SELECT * FROM test")))
.then((e => (console.log(e), db.query("DROP TABLE test"))))
.then((() => console.log("test success!")))
.catch((e => console.error(e)));
This line did the trick
pgp.pg.types.setTypeParser(pgp.pg.types.builtins.UUID, (val) => {
val === null ? null : val.replace(/-/g, '')
});
Thank you for your suggestions #vitaly-t and #Bergi

Serverless Framework and DynamoDB: Unexpected token in JSON at JSON.parse

Hi I followed this Serverless + AWS REST API tutorial and it went great, I got it to work.
Now, I'm trying to modify it but have hit a wall while trying to submit data into the DynamoDB table.
Using Postman to submit a valid JSON object I get a 502 response. If I test the function in Lambda, I get the following error:
{
"errorType": "SyntaxError",
"errorMessage": "Unexpected token o in JSON at position 1",
"trace": [
"SyntaxError: Unexpected token o in JSON at position 1",
" at JSON.parse (<anonymous>)",
" at Runtime.module.exports.submit [as handler] (/var/task/api/interview.js:11:28)",
" at Runtime.handleOnce (/var/runtime/Runtime.js:66:25)",
" at process._tickCallback (internal/process/next_tick.js:68:7)"
]
}
After searching for solutions, what I found out is that it seem like the event that is being passed as JSON.parse(event)is undefined.
Here's the serverless.yml:
service: interview
frameworkVersion: ">=1.1.0 <2.0.0"
provider:
name: aws
runtime: nodejs10.x
stage: dev
region: us-east-1
environment:
INTERVIEW_TABLE: ${self:service}-${opt:stage, self:provider.stage}
INTERVIEW_EMAIL_TABLE: "interview-email-${opt:stage, self:provider.stage}"
iamRoleStatements:
- Effect: Allow
Action:
- dynamodb:Query
- dynamodb:Scan
- dynamodb:GetItem
- dynamodb:PutItem
Resource: "*"
resources:
Resources:
CandidatesDynamoDbTable:
Type: 'AWS::DynamoDB::Table'
DeletionPolicy: Retain
Properties:
AttributeDefinitions:
-
AttributeName: "id"
AttributeType: "S"
KeySchema:
-
AttributeName: "id"
KeyType: "HASH"
ProvisionedThroughput:
ReadCapacityUnits: 1
WriteCapacityUnits: 1
StreamSpecification:
StreamViewType: "NEW_AND_OLD_IMAGES"
TableName: ${self:provider.environment.INTERVIEW_TABLE}
functions:
interviewSubmission:
handler: api/interview.submit
memorySize: 128
description: Submit interview information and starts interview process.
events:
- http:
path: interviews
method: post
and the interview.js
'use strict';
const uuid = require('uuid');
const AWS = require('aws-sdk');
AWS.config.setPromisesDependency(require('bluebird'));
const dynamoDb = new AWS.DynamoDB.DocumentClient();
module.exports.submit = (event, context, callback) => {
const requestBody = JSON.parse(event);
const fullname = requestBody.fullname;
const email = requestBody.email;
const test = requestBody.test;
const experience = requestBody.experience;
if (typeof fullname !== 'string' || typeof email !== 'string' || typeof experience !== 'number') {
console.error('Validation Failed');
callback(new Error('Couldn\'t submit interview because of validation errors.'));
return;
}
submitInterviewP(interviewInfo(fullname, email, experience, test))
.then(res => {
callback(null, {
statusCode: 200,
body: JSON.stringify({
message: `Sucessfully submitted interview with email ${email}`,
interviewId: res.id
})
});
})
.catch(err => {
console.log(err);
callback(null, {
statusCode: 500,
body: JSON.stringify({
message: `Unable to submit interview with email ${email}`
})
})
});
};
const submitInterviewP = interview => {
console.log('Submitting interview');
const interviewInfo = {
TableName: process.env.INTERVIEW_TABLE,
Item: interview,
};
return dynamoDb.put(interviewInfo).promise()
.then(res => interview);
};
const interviewInfo = (fullname, email, experience,test) => {
const timestamp = new Date().getTime();
return {
id: uuid.v1(),
fullname: fullname,
email: email,
experience: experience,
test: test,
submittedAt: timestamp,
updatedAt: timestamp,
};
};
If I replace the event param for a valid JSON object and then deploy again. I'm able to successfully insert the object into dynamoDB.
Any clues? Please let me know if there's anything I missing that could help.
Thanks!
API Gateway stringify the request body in event's body property.
Currently you are trying to parse event object const requestBody = JSON.parse(event); which is wrong. You need to parse event.body property:
const requestBody = JSON.parse(event.body);

StrongLoop query/stored procedure with Postgres?

Per the docs, StrongLoop doesn't support running custom sql statements.
https://docs.strongloop.com/display/public/LB/Executing+native+SQL
How anyone thinks you can build an enterprise app with just simple joins is beyond me, but I did find this post which says you can do it:
Execute raw query on MySQL Loopback Connector
But this is for MySql. When I try it with Postgres I get the error: "Invalid value for argument 'byId' of type 'object': 0. Received type was converted to number." And it returns no data. Here is my code:
module.exports = function(account) {
account.byId = function(byId, cb){
var ds=account.dataSource;
var sql = "SELECT * FROM account where id > ?";
ds.connector.execute(sql, [Number(byId)], function(err, accounts) {
if (err) console.error(err);
console.info(accounts);
cb(err, accounts);
});
};
account.remoteMethod(
'byId',
{
http: {verb: 'get'},
description: "Get accounts greater than id",
accepts: {arg: 'byId', type: 'integer'},
returns: {arg: 'data', type: ['account'], root: true}
}
);
};
For the part [Number(byId)], I've also tried [byId] and just byId. Nothing works.
Any ideas? So far I really like StrongLoop, but it looks like the Postgresql connector is not ready for production. I'll be doing a prototype with Sails next if this doesn't work. :-(
Here's the thing arg is of type 'integer' which is not a valid Loopback Type. Use `Number instead. Check the corrected code below:
module.exports = function(account) {
account.byId = function(byId, cb){
var ds = account.dataSource;
var sql = "SELECT * FROM account WHERE id > $1";
ds.connector.execute(sql, byId, function(err, accounts) {
if (err) console.error(err);
console.info(accounts);
cb(err, accounts);
});
};
account.remoteMethod(
'byId',
{
http: {verb: 'get'},
description: "Get accounts greater than id",
accepts: {arg: 'byId', type: 'Number'},
returns: {arg: 'data', type: ['account'], root: true} //here 'account' will be treated as 'Object'.
}
);
};
Note: MySQL's prepared statements natively use ? as the parameter placeholder, but PostgreSQL uses $1, $2 etc.
Hope this works for you. Else try with [byId] instead of byId as per the docs.

OData Jaydata - odata update request returns error 404 (SAPUI5, node)

I'm building a web application with SAPUI5 which makes available a list of services, that are stored in a MongoDB and available as OData.
I followed this guide jaydata-install-your-own-odata-server-with-nodejs-and-mongodb and these are my model.js:
$data.Class.define("marketplace.Service", $data.Entity, null, {
Id: {type: "id", key: true, computed: true, nullable: false},
Name: {type: "string", nullable: false, maxLength: 50},
}, null);
$data.Class.defineEx("marketplace.Context", [$data.EntityContext, $data.ServiceBase], null, {
Services: {type: $data.EntitySet, elementType: marketplace.Service}
});
exports = marketplace.Context;
and server.js:
var c = require('express');
require('jaydata');
window.DOMParser = require('xmldom').DOMParser;
require('q');
require('./model.js');
var app = c();
app.use(c.query());
app.use(c.bodyParser());
app.use(c.cookieParser());
app.use(c.methodOverride());
app.configure(function() {app.use(app.router);});
app.use(c.session({secret: 'session key'}));
app.use("/marketplace", $data.JayService.OData.Utils.simpleBodyReader());
app.use("/marketplace", $data.JayService.createAdapter(marketplace.Context, function (req, res) {
return new marketplace.Context({
name: "mongoDB",
databaseName: "marketplace",
address: "localhost",
port: 27017
});
}));
app.use("/", c.static(__dirname));
app.use(c.errorHandler());
app.listen(8080);
The client is developed by using SAPUI5 and these are the parts of the code relative to the odata model creation:
oModel = sap.ui.model.odata.ODataModel("http://localhost:8080/marketplace", false); // connection to the odata endpoint
oModel.setDefaultBindingMode(sap.ui.model.BindingMode.TwoWay);
sap.ui.getCore().setModel(oModel);
The various services are correctly showed in a SAPUI5 table and I'm easily able to insert a new service by using the POST OData.request in this way:
OData.request({
requestUri: "http://localhost:8080/marketplace/Services",
method: "POST",
data: newEntry // json object with the new entry
},
function(insertedItem) {
// success notifier
},
function(err) {
// error notifier
}
);
and delete a service by using the SAPUI5 function oModel.remove() in this way (oParams is a json object which contains the alert notification functions):
var serviceId = oTable.getRows()[selectedIndex].getCells()[0].getText();
oModel.remove("/Services('" + serviceId + "')", oParams);
Everything works fine but the update request for a single service. I've tried with the functions provided by SAPUI5 (oModel.update or oModel.submitChanges), by using OData.request ("method: PUT"), by creating an ajax PUT request, I also tried to craft PUT request with Fiddler.
I always get error 404:
Request URL:http://localhost:8080/marketplace/Services('NTMzZDM3M2JlNjY2YjY3ODIwZjlmOTQ0')
Request Method:PUT
Status Code:404 Not Found
Where can be the problem?
I tried with Chrome, IE, and Firefox; same problem...
Thanks
Try to update with MERGE verb and pass the modified fields in JSON format inside the BODY

Urlencoded Form in Express/nodejs (formidable)

I'm using node-formidable for handling form data in Express/Nodejs app. I'm sending POST vars from POSTman Chrome Extension. (btw, http://httpbin.org/post works fine)
If i use multipart/form-data, everything is fine.
If i use urlencoded, form.parse's callback never triggers, and blocks all response. it simply locks the post method.
required:
var formidable = require('formidable');
var http = require('http');
var util = require('util');
post method:
app.post("/items",function(req,res){
var form = new formidable.IncomingForm();
form.parse(req,function(err,fields,files){
console.log(fields);
res.send("posted");
});
});
express settings:
app.use(express.json());
app.use(express.urlencoded());
app.use(express.multipart());
app.use(express.cookieParser());
app.use(express.static(__dirname + '/public'));
app.use(express.cookieSession({secret:"wow_so_secret_such_code_gud_layers"}));
app.use(passport.initialize());
app.use(passport.session());
app.use(express.methodOverride());
is there any trick for using urlencoded?
might be important;
{
domain: null,
_events: {},
_maxListeners: 10,
error: null,
ended: false,
maxFields: 1000,
maxFieldsSize: 2097152,
keepExtensions: false,
uploadDir: '/var/folders/pl/xnl7cxpj075chytyf_t7f1480000gn/T/',
encoding: 'utf-8',
headers: null,
type: null,
hash: false,
bytesReceived: null,
bytesExpected: null,
_parser: null,
_flushing: 0,
_fieldsSize: 0,
openedFiles: []
}
both urlencoded and multipart returns null.