How to check the content of Koa's ctx.query? - node.js

For a Koa-based API server, I want to check what parameters the URL query contains.
My setup looks as simple as this:
const Koa = require('koa')
const app = new Koa()
const Router = require('koa-router')
router = new Router()
router.get('/', ctx => {
console.log(ctx.query)
})
app.use(router.routes())
app.use(router.allowedMethods())
app.listen(3000)
It seems that ctx.query has a structure like an object but doesn't work as one.
Methods like ctx.query.hasOwnProperty() or ctx.query.toString() result in an error saying that it is not a function.
Though, Object.keys(ctx.query) gives an array of the keys—which is confusing to me because it apparently is an object and should have above methods.
What is ctx.query exactly? How can I make the failing methods from above working?

ctx.query is the return from Node.js' querystring.parse() method. From the documentation:
The object returned by the querystring.parse() method does not
prototypically inherit from the JavaScript Object. This means that
typical Object methods such as obj.toString(), obj.hasOwnProperty(),
and others are not defined and will not work.
You can check Koa's request implementation.

Related

TypeError: register.route(...).use is not a function

I'm using express.Router() whenever i try use method it gives the following error
TypeError: register.route(...).use is not a function
Code
/server/routes
const express = require('express');
const register = express.Router();
const account = require("../controller/AccountController");
const Middleware = require("../utils/middlewares");
register.route('/')
.post(Middleware.checkUser)
.post(account.user_register)
register.route('/verify/:token')
.get(Middleware.verifyEmail)
register.route('/resend/:email')
.use(Middleware.sendVerification)
module.exports = register;
Server.js
server.use('/register', register);
When i use a method like get there is no error. But i don't want to use any method since the middleware just sends an email
As stated in documentation, route all method is intended for route-specific middleware, it could be:
register.route('/resend/:email')
.all(Middleware.sendVerification)
If the route is expected to be requested with GET only and may not make sense for other verbs, it should be narrowed down to supported verbs:
register.route('/resend/:email')
.get(Middleware.sendVerification)
In this case sendVerification seems to be route handler and not a middleware. It's suitable to specify it only for get if /resend/ is expected to be requested with GET.

Having control flow issue with mongoose model's find

I'm completely new to node and it's frameworks Koa and express. I've a mongoose model called Drawing and a router module for that.
Problem is with express routers I was able the get the data from database using Drawing.find method but with Koa, control is not even going into Drawing.find. And I'm not able to get the data at all. Please find the following related code and help me understand the things better.
This is my router module
import * as Router from "koa-router";
import Drawing from "../../models/drawing";
function getRoutesForDrawing(): Router {
console.log("Inside getRoutes for drawing");
let route = new Router();
route.get("/drawing", function(context,next) {
console.log("Inside /drawing");
Drawing.find(function(err,drawings) {
console.log("Not gettig executed");
context.body = "Welcome";
});
//context.body = "Welcome";
});
}
export default getRoutesForDrawing();
And the model is
import mongoose = require("mongoose");
export interface IDrawing extends mongoose.Document {
drawingId:Number,
drawingName:String,
updatedOn:Date,
updatedBy:Number
};
export const DrawingSchema = new mongoose.Schema({
drawingId:Number,
drawingName:String,
updatedOn:Date,
updatedBy:Number
});
const Drawing = mongoose.model<IDrawing>('Drawing', DrawingSchema);
export default Drawing;
As you can see in my router module, the control is actually coming for /drawing and it's printing in console "Inside /drawing" but then control isn't coming to Drawing.find. I'm getting difficulty in understanding this.
It's a little bit hard to figure out what's going on because it looks like you have problems all over the place. Let me point out the things that stand out:
getRoutesForDrawing is declared to return a router and doesn't return anything
Koa routes are not like express. In particular they are not callback based. They take either generator functions (Koa 1.x) or async functions (Koa 2.x). You seem to expect that it's wanting a callback function which won't work. Assuming koa 2.x, its router.get('/drawing', async(context) => {...});
Assuming koa 2.x, you need to await the result of the mongoose methods, e.g. context.body = await Drawing.find({})

What doesn't nodejs relate 'this' as the object that encapsulates the function?

I wrote the following code in nodejs:
var express = require('express');
var app = express();
app.message = "helloworld";
app.get('/check', function (req,res) {
res.end("GET request OK");
console.log(this.message);
});
app.listen(4000);
When I run the code and send a GET request, the line:
console.log(this.message);
prints "undefined".
However, when I change it to:
console.log(app.message)
I get "helloworld".
I thought that this variable should represent the object that invoked the function. If so, why doesn't this object include the attribute .message ?
this can be whatever the author of the library intends it to be. It could be the app instance or it could be the global object.
In this case, it appears it's the global object.
As a sidenote too, it's not recommended to add expando properties to an existing library like that.

Where are get, post methods defined in ExpressJS?

I'm unable to find the code of get or post methods. I haven't found them in expressjs lib folder, so it's probably that they are present in one of the js files the Router requires.
var express = require('express');
var router = express.Router();
var Blah = require('../modules/Blah');
router.post('/', function(req, res, next) {
Blah.foo(req, res);
});
I need it to find out where the next parameter is passed to that callback function above, because it has to be done by ExpressJS framework under the hood.
Express uses the methods module to dynamically attach http verbs to the router :
lib/router/index.js :
// create Router#VERB functions
methods.concat('all').forEach(function(method){
  proto[method] = function(path){
    var route = this.route(path)
    route[method].apply(route, slice.call(arguments, 1));
    return this;
  };
});
See the answer by KeatsPeeks for more details. Here are some links to specific parts of the source code that might be helpful:
get and post methods are defined in the methods module here:
https://github.com/jshttp/methods/blob/master/index.js#L14-L15
Here in lib/applciation.js the .METHOD calls for them are delegated to router.METHOD:
https://github.com/strongloop/express/blob/master/lib/application.js#L471-L484
The rest is in lib/router/index.js:
https://github.com/strongloop/express/blob/master/lib/router/index.js#L506-L513
And in lib/router/route.js - search for "methods" in:
https://github.com/strongloop/express/blob/master/lib/router/route.js

Updating the prototype of ServerRequest in an express/node configuration

I'd like to augment the prototype of the request object in expressjs, but it isn't clear where this request is defined? I think it is http.ServerRequest, but I can't find that definition either.
What's the right way to do the following...
http.ServerRequest.prototype.redirect = function(path) { }
Express itself adds it's utility methods to http.IncomingMessage.prototype, using this pattern in 2.*:
var http = require('http'),
req = http.IncomingMessage.prototype;
req.foo = function(bar) {
// Do cool stuff
};
And this pattern in 3.*:
var http = require('http');
var req = exports = module.exports = {
__proto__: http.IncomingMessage.prototype
};
It's wise to be careful with monkey patching though, as Vadim Baryshev warns in his answer.
Look at Connect framework and his middleware libs. Every middleware extends request and response objects after their creation. Changing prototype of core objects not the best way because this can lead to unpredictable behavior in other modules.

Resources