khmub
khmub

Reputation: 112

nodejs with express make internal route call

I have gone through few stackoverflow question. Still unable to under where my concept is wrong. Background: nodejs app I'm learning works as I want it to be. It can make GET or POST request from CURL, fill in data to mongodb. My app is also listening on socket. When ws.on('message')... I would like to call same Web API route internally to my app. But that doesn't seems to invoke. "Final goal is to get the socket message and GET/POST to my internal /api route. Below I have my app code:

server.js

var express = require('express');  
var http = ('http'); const mongoose = ('mongoose'); 
const WebSocket = ('ws');
var routes = require('./routes/index'); var api = ('./routes/api');
var app = express();
app.use('/', routes);
app.use('/api', api);
mongoose.Promise = global.Promise;

// catch 404 and forward to error handler
app.use(function (req, res, next) {
 var err = new Error('Not Found');
 err.status = 404;
 next(err);
} );

// connect to database
mongoose.connect('mongodb://localhost/mdb')
.then(() => console.log('db connection successful'))
.catch((err) => console.error(err));

    http.createServer(app).listen(8080);

    //Create a websocket to receive notification

    const ws = new WebSocket('ws://localhost:8031');
    ws.on('open', function open() {

        console.log('ws connection successful');
    });

    //get or post message to webapi /api/v1 path
    ws.on('message', function incoming(data) {
        //this route seems never been called
        app.get('api/v1', function (res) {
            res.send('hello');
        });
        console.log('Socket message: ' + data);
    });
   module.exports = app;

api.js

    var express = require('express');
    var router = express.Router();
    const mogoose = require('mongoose');
    const Data = require('../models/dbModel');
    const TempData = require('../models/TempModel');


    /* GET data for listing. */
    router.get('/v1/', function (req, res, next) {
        Data.find(function (err, data)
        {
            if (err) return next(err);
            res.json(data);
        });
    });

package.json

      "dependencies": {
    "body-parser": "~1.8.1",
    "cookie-parser": "~1.3.3",
    "debug": "~2.0.0",
    "express": "^4.9.8",
    "express-controller": "^0.3.2",
    "jade": "~1.6.0",
    "mongodb": "^3.0.1",
    "mongoose": "^5.0.2",
    "morgan": "~1.3.0",
    "request": "^2.83.0",
    "serve-favicon": "~2.1.3",
    "stylus": "0.42.3",
    "ws": "^4.0.0"
  },
  "main": "server.js"

Please fill in your comments and hints. Have been stuck with this issue for 1.5 days.

Upvotes: 1

Views: 4761

Answers (4)

Brisstone
Brisstone

Reputation: 61

I was able to solve this easily by making socket.io available on all routes by default: passing it as a default middleware

import socketIo from 'socket.io';
const server = http.createServer(app);
const io = socketIo(server, { cors: { origin: "http://frontendUrL" } 
});

app.use(bodyParser.json());
app.use((req, res, next) => {
req.io = io;
return next();
});

Call socket io from any route using

req.io.sockets.emit('broadcast',  {message: 'You have a new Visitor', url 
: url});

Upvotes: 0

Rahul Sharma
Rahul Sharma

Reputation: 10111

Why you want call route, just perform the same operation on socket event

// api.js
var handler = function (cb) {
    // Do some stuff
    Data.find(cb);
}
router.get('/v1/', (req, res, next) => {
    handler(function (err, data) {
        if (err) return next(err);
        res.json(data);
    });
});

module.exports = {
    handler
};

// server.js
var appJs = require('./app');
ws.on('message', function incoming(data) {
    /* No need to call route perform whatever operation route is doing */
    appJs.handler(function (err, data) {
        console.log('Socket message: ' + data);
        // Do some stuff
    });
});

Upvotes: 0

Faizuddin Mohammed
Faizuddin Mohammed

Reputation: 4328

You can use supertest and make calls to your own API.

const app = require('./server.js');
const request = require('supertest');

request(app)
  .get('/api/v1')
  .expect(200)
  .end(function(err, res) {
    if (err) throw err;
    else console.log(res);
  });

Ref: https://github.com/visionmedia/supertest

You can also create a function like this:

router.get('/v1/', function (req, res, next) {
    exports.findData(function(results){
        res.json(results);
    })
});

exports.findData = function(callback) {
    Data.find(function (err, data) {
        if (err) return next(err);
        callback(data);
    });
}

And in your WebSockets:

const findData = require('./router').findData;

// ...
ws.on('message', function incoming(data) {
    findData(function () {
        console.log('Socket message: ' + data);
    })
});

Upvotes: 1

t3__rry
t3__rry

Reputation: 2849

From ws's docs

const WebSocket = require('ws');

const ws = new WebSocket('ws://www.host.com/path');

ws.on('open', function open() {
  ws.send('something');
});

ws.on('message', function incoming(data) {
  console.log(data);
});

It seems like a config issue, see: const ws = new WebSocket('ws://www.host.com/path');

Upvotes: 0

Related Questions