I have KOA Like below :
var koa = require('koa'),
bodyParser = require('koa-body-parser'),
router = require('koa-router'),
app = koa();
app.use(router(app));
app.use(bodyParser());
app.post('http://localhost/get',getit);
function *getit(){
console.log(this.req.body); //undefined
}
and then send a post reqeust via jquery ajax :
var xhr = $.ajax({
type: 'POST',
dataType: 'json',
contentType: 'application/json',
url: 'http://localhost/getit',
data: {"name":"me"},
success: function(response) {
}
});
but in koa and in this.req i cant find my data. in google chrome developer tools i can see the header and everything send ok but i cant see it in koa.
Update
the correct is :
function *getit(){
console.log(this.request.body); //undefined
}
Interesting, I came across the same error, but my issue was the ordering of app.use() statements. The below does NOT work for me, and returns 'undefined' for this.request.body:
var koa = require('koa');
var router = require('koa-router');
var bodyParser = require('koa-body-parser');
var app = koa();
app.use(router(app));
app.use(bodyParser());
app.post('/login', function *() {
this.response.body = this.request.body;
});
app.listen(3000);
However, if I reverse the order of the two app.use() statements to the following:
app.use(bodyParser());
app.use(router(app));
I can then see the elements in this.request.body. I'm using koa v0.5.5, koa-body-parser v1.0.0, koa-router v3.1.2, and node v0.11.12.
I would use the co-body module instead (the same module used internally by koa-body-parser). The code should looks like:
var koa = require('koa');
var _ = require('koa-route');
var parse = require('co-body');
var app = koa();
app.use(function* (next) {
this.req.body = yield parse(this);
yield next;
});
app.use(_.post('/login', function* () {
this.body = this.req.body;
}));
app.listen(3000);
The var body = yield parse(this); line does the trick, the parse method will try to parse any request but you can replace it with parse.json, parse.form or parse.text in case you need more control
koa uses middleware in the order you initialized them. so if you insert the router before the bodyparser it will not work. since your request wont pass to the parser before it gets to the router middleware, the request wont be parsed and koa will ignore the request.body. so the ordering is really important.
Solution
Acording to comment , the correct for me is this.request.body and this.req.body is not correct.
Related
I'm working on a SPA website with node.js, jQuery, mongoose and MongoDB for a shopping website.
The ajax requests and responses work perfectly when starting from the index.html file. So for example begining on http://localhost:3000 and someone clicks on a link called 'products' I send an ajax request to the the server and the server sends the necessary product information back asynchronously which lead to http://localhost:3000/products. But the problem is that if someone types http://localhost:3000/products directly in the search bar it will show the json representation of the products.
This is my code:
script.js
function redirect (link) {
$.ajax({
type: 'GET',
url: 'http://localhost:3000/' + link,
contentType: 'application/json',
data: {
link
},
success: function (res) {
let container = $('#contentToSwap');
container.html('');
res.products.forEach(function (products_) {
...
});
}
});
}
app.js
var Product = require('./models/product');
var mongoose = require('mongoose');
var bodyParser = require('body-parser');
var path = require('path');
var express = require('express');
var app = express();
mongoose.connect('mongodb://localhost:27017/shopping');
var PORT = process.env.PORT || 3000;
app.use(express.static(path.join(__dirname, 'public')));
app.use(bodyParser.json());
app.get('*', function(req, res) {
Product.find(function(err, docs) {
let productChunks = [];
let chunksize = 4;
let display = [];
for (var i = 0; i < docs.length; i++) {
if (docs[i].productType == req.query.link) display.push(docs[i]);
}
for (var i = 0; i < display.length; i += chunksize) {
productChunks.push(display.slice(i, i + chunksize));
}
res.send({ products: productChunks });
});
});
app.listen(PORT, function () {
console.log('Listening on port ' + PORT);
});
So I need some sort of frontend routing if the user doesn't start at the index.html file. I know that I could write my own router to route the urls correctly and that I could route all requests back to the index.html like
app.get('*', function(req, res) {
res.sendFile(__dirname + '/public/index.html');
});
But then I cannot load all the necessary product information from the server when someone clicks a link. So I'm a little bit confused on hwo to tackle this issue. Any help is appreciated
This is usually achieved by separating api routes from normal ones by adding specific url prefixes such as /api for all routes that return json data. What you can do is to specify /api/whatever-you-want, make it the target for your ajax call and place it above app.get('*' ....
Since routes and middleware functions are resolved top to bottom, it will be matched by your ajax call only, leaving the /products unaffected.
answer to question -- Is it possible to redirect user from /api/products to /product if the request wasn't generated by ajax?
Yes, it is possible by adding request query parameter to ajax call which will not be present on normal call and then check those on the server side and decided what to do if it (that specific query parameter) is missing or not.
Let's assume some client side JS that generates ajax call.
fetch('/api/products?api=true')
.then((data) => data.json())
.then((json) => console.log(json));
Notice the request url - /api/products?api=true
Now assume a normal call from html file.
products
These two calls differ in that api query parameter (ajax call has it, the other one doesn't).
And for the server side part of the task -- request query parameters object can be accessed via query property on request object (req.query).
app.get('/api/products', (req, res) => {
if (!req.query.api) {
// if get request doesn't contain api param. then
// handle it accordingly, e.g. do redirect
return res.redirect('/products');
}
// request comming from ajax call, send JSON data back
res.json({ randomStuff: 'abcd' });
});
I am currently using crypto.js module to hash things. It was working for a while then I started getting this error:
Here is the foundation of my server:
process.stdout.write('\033c'); // Clear the console on startup
var
express = require("express"),
app = express(),
http = require("http").Server(app),
io = require("socket.io")(http),
path = require("path"),
colorworks = require("colorworks").create(),
fs = require("fs"),
crypto = require("crypto");
function md5(msg){
return crypto.createHash("md5").update(msg).digest("base64");
}
function sha256(msg) {
return crypto.createHash("sha256").update(msg).digest("base64");
}
http.listen(443, function(){
// Create the http server so it can be accessed via 127.0.0.1:443 in a web browser.
console.log("NJ project webserver is running on port 443.");
// Notify the console that the server is up and running
});
app.use(express.static(__dirname + "/public"));
app.get("/", function(request, response){
response.sendFile(__dirname + "/public/index.html");
});
I am aware that these functions are creating the problem:
function md5(msg){
return crypto.createHash("md5").update(msg).digest("base64");
}
function sha256(msg) {
return crypto.createHash("sha256").update(msg).digest("base64");
}
The problem being, if these functions don't work (which they don't anymore), roughly 200 lines of code will go to waste.
This error is triggered by attempting to hash a variable that does not exist:
function md5(msg){
return crypto.createHash("md5").update(msg).digest("base64");
}
function sha256(msg) {
return crypto.createHash("sha256").update(msg).digest("base64");
}
md5(non_existent); // This variable does not exist.
What kind of data are you trying to hash ? Where does it come from ?
I would check the value of msg first then I would try :
crypto.createHash('md5').update(msg.toString()).digest('hex');
You could also use these packages instead:
https://www.npmjs.com/package/md5
https://www.npmjs.com/package/js-sha256
I wanted to send code to some node application and I use the postman with post message and in the body I put the following:
module.exports = function() {
var express = require('express'),
app = express();
app.set('port', process.env.PORT || 3000);
return app;
}
in the header of the request I put
content-Type application/text/enriched
in the node code I use the following
module.exports = function (app) {
fs = require('fs');
var bodyParser = require('body-parser');
...
app.post('/bb',function(req,res){
var fileContent = req.body
and the file content is empty ,I was able to see that it works since it stops in debug
If you want to add a custom content type then you need to keep two things in mind:
Content type couldn't be "application/text/enriched", in other hand "application/text-enriched" is ok. Max two "words".
You must provide a custom accept header on body parser configuration BUT body parser return you a buffer when you use custom header
See the example:
var express = require('express')
var app = express()
var bodyParser = require('body-parser')
app.use(bodyParser.raw({ type: 'application/text-enriched' }))
app.post('/demo', function(req, res) {
console.log('POST DATA')
console.log('STREAM', req.body)
console.log('STREAM to STRING', req.body.toString())
res.status(200).send('ok');
});
app.listen(3000);
You can test in your console with curl:
curl 'http://localhost:3000/demo' -d 'name=john&surname=doe' -H 'Content-Type: application/text-enriched'
I recommend you try to not use a custom content type header because things are easier. I hope that my explanation help you.
Recently I started learning a little bit about Node.js and it's capabilities and tried to use it for some web services.
I wanted to create a web service which will serve as a proxy for web requests.
I wanted my service to work that way:
User will access my service -> http://myproxyservice.com/api/getuserinfo/tom
My service will perform request to -> http://targetsite.com/user?name=tom
Responded data would get reflected to the user.
To implement it I used the following code:
app.js:
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
var proxy = require('./proxy_query.js')
function makeProxyApiRequest(name) {
return proxy.getUserData(name, parseProxyApiRequest);
}
function parseProxyApiRequest(data) {
returned_data = JSON.parse(data);
if (returned_data.error) {
console.log('An eror has occoured. details: ' + JSON.stringify(returned_data));
returned_data = '';
}
return JSON.stringify(returned_data);
}
app.post('/api/getuserinfo/tom', function(request, response) {
makeProxyApiRequest('tom', response);
//response.end(result);
});
var port = 7331;
proxy_query.js:
var https = require('https');
var callback = undefined;
var options = {
host: 'targetsite.com',
port: 443,
method: 'GET',
};
function resultHandlerCallback(result) {
var buffer = '';
result.setEncoding('utf8');
result.on('data', function(chunk){
buffer += chunk;
});
result.on('end', function(){
if (callback) {
callback(buffer);
}
});
}
exports.getUserData = function(name, user_callback) {
callback = user_callback
options['path'] = user + '?name=' + name;
var request = https.get(options, resultHandlerCallback);
request.on('error', function(e){
console.log('error from proxy_query:getUserData: ' + e.message)
});
request.end();
}
app.listen(port);
I wish I didn't screwed this code because I replaced some stuff to fit my example.
Anyway, the problem is that I want to post the response to the user when the HTTP request is done and I cant find how to do so because I use express and express uses asynchronous calls and so do the http request.
I know that if I want to do so, I should pass the makeProxyApiRequest the response object so he would be able to pass it to the callback but it is not possible because of asyn problems.
any suggestions?
help will be appreciated.
As you're using your functions to process requests inside your route handling, it's better to write them as express middleware functions, taking the specific request/response pair, and making use of express's next cascade model:
function makeProxyApiRequest(req, res, next) {
var name = parseProxyApiRequest(req.name);
res.locals.userdata = proxy.getUserData(name);
next();
}
function parseProxyApiRequest(req, res, next) {
try {
// remember that JSON.parse will throw if it fails!
data = JSON.parse(res.locals.userdata);
if (data .error) {
next('An eror has occoured. details: ' + JSON.stringify(data));
}
res.locals.proxyData = data;
next();
}
catch (e) { next("could not parse user data JSON."); }
}
app.post('/api/getuserinfo/tom',
makeProxyApiRequest,
parseProxyApiRequest,
function(req, res) {
// res.write or res.json or res.render or
// something, with this specific request's
// data that we stored in res.locals.proxyData
}
);
Even better would be to move those middleware functions into their own file now, so you can simply do:
var middleware = require("./lib/proxy_middleware");
app.post('/api/getuserinfo/tom',
middleware.makeProxyApiRequest,
middleware.parseProxyApiRequest,
function(req, res) {
// res.write or res.json or res.render or
// something, with this specific request's
// data that we stored in res.locals.proxyData
}
);
And keep your app.js as small as possible. Note that the client's browser will simply wait for a response by express, which happens once res.write, res.json or res.render etc is used. Until then the connection is simply kept open between the browser and the server, so if your middleware calls take a long time, that's fine - the browser will happily wait a long time for a response to get sent back, and will be doing other things in the mean time.
Now, in order to get the name, we can use express's parameter construct:
app.param("name", function(req, res, next, value) {
req.params.name = value;
// do something if we need to here, like verify it's a legal name, etc.
// for instance:
var isvalidname = validator.checkValidName(name);
if(!isvalidname) { return next("Username not valid"); }
next();
});
...
app.post("/api/getuserinfo/:name", ..., ..., ...);
Using this system, the :name part of any route will be treated based on the name parameter we defined using app.param. Note that we don't need to define this more than once: we can do the following and it'll all just work:
app.post("/api/getuserinfo/:name", ..., ..., ...);
app.post("/register/:name", ..., ..., ... );
app.get("/api/account/:name", ..., ..., ... );
and for every route with :name, the code for the "name" parameter handler will kick in.
As for the proxy_query.js file, rewriting this to a proper module is probably safer than using individual exports:
// let's not do more work than we need: http://npmjs.org/package/request
// is way easier than rolling our own URL fetcher. In Node.js the idea is
// to write as little as possible, relying on npmjs.org to find you all
// the components that you need to glue together. If you're writing more
// than just the glue, you're *probably* doing more than you need to.
var request = require("request");
module.exports = {
getURL: function(name, url, callback) {
request.get(url, function(err, result) {
if(err) return callback(err);
// do whatever processing you need to do to result:
var processedResult = ....
callback(false, processedResult);
});
}
};
and then we can use that as proxy = require("./lib/proxy_query"); in the middleware we need to actually do the URL data fetching.
I am using a express framework on node and I want to change the value(increase or decrease) of a variable in my testing module each time the module is run. Is there a way to know if the file has been executed and keep it in memory so that next time the file is run again, the value changes again? I want to increase the variableToChange each time the module is executed.
Here is my code:
'use strict';
var util = require('util');
var makeApiCall = require('proc-utils').makeApiCall;
var baseUrl = 'http://localhost:' + (require('../../config').port || 3000);
var url = {
endpoint: '/patients/register',
method: 'post'
};
var ct = {
test: function (data, cb) {
var options = {
type: 'form',
data: data,
baseUrl: baseUrl
};
makeApiCall(url.endpoint, url.method, options, cb);
}
};
module.exports = ct;
//-- Test Code ----------------------------------------------------------
var variableToChange=0;
if (require.main === module) {
(function () {
var data = {
first_name:'John',
last_name:'Doe',
email:'shnsdfn'+variableToChange+'b#sh.com',
password:'John1234'
};
ct.test(data, console.log);
})();
}
One solution is storing the information you need in the cookie session:
var cookieParser = require('cookie-parser');
var session = require('express-session');
express().use(cookieParser()) // include the cookies middleware to parse and manage sessions
.use(session({secret : 'mysecret'}))//set up the session with minimal config (secret)
.use(function(req,res,next){
req.session.variableToSave = 0; // initialize variable you want to save
next(); // starts next middleware
});
But this is for storing informations for browser that connects to the server.
Other Solution is maintaining the log file by appending the desired values with other relevant informations to it.
Check app.locals in Express API reference: http://expressjs.com/api.html#app.locals