BISON encode/decode middleware for socket.io? - javascript

Is there any way to tamper with the data that socket.io sends just before it is sent/received? I was thinking about something like an express middleware.
So that I could encode data after the normal .emit() method is called and before socket.on(...) is called.
In express I would imagine it to look somewhat like this to BISON decode all incoming request:
app.use(function(req, res, next) {
req.body = BISON.decode(req.body);
next();
});
Now how could that be done with socket.io in a way that requests being sent also get encoded automatically?
I know that socket.io supports middlewares in a similar form to express, but that is only for the actual http request that socket.io sends to create the websocket connection...
io.use(function(socket, next) {
//...
next();
});
so I doubt that this would be of any help here..

You can intercept (and change) data by listening for packet events, and similarly use the flush event to intercept outgoing messages:
io.use(function(socket, next) {
socket.conn.on('packet', function(packet) {
...change `packet.data` here...
});
socket.conn.on('flush', function(packets) { // array of packets
...
});
next();
});
But to be honest, I'm having a hard time finding documentation on how packet.data is encoded, so I can't provide a full example.
EDIT: socket.io-parser has decodeString() which is used to parse the payload. Sadly, it's not exported (and the methods that are exported are all async, which doesn't combine well with event handlers).

Related

Clone/relay exact request to another URL (nodejs)

I'd like to clone/relay the exact request to another URL in native NodeJs. For example, if you send a POST request to my site "example.com", it will send the exact same request you sent to another URL "example2.com" (data, headers etc). How could I achieve that?
You can use proxy middleware to duplicate the request. For example http-proxy-middleware will allow you to proxy the request to another server, but from what I can tell, you can only modify the response. Which isn't optimal if you don't want to wait on the proxy. You might just grab the main proxy library itself, something like:
const httpProxy = require('http-proxy');
const proxyMiddleware = httpProxy.createProxyMiddleware({
target: 'http://www.example2.com',
selfHandleResponse: true
});
const customProxyMiddleware = (req, res, next) => {
proxy.web(req, res);
next();
};
// This passes all incoming requests to the proxy but does not handle
// any of them. It simply passes it along.
app.use('/', customProxyMiddleware);
This code may not work exactly as intended but it should be a good starting point for what you are attempting.

How to use get and post both in app.use middleware

I wish to know how can I have both get and post request handled by app.use the way I do it using app.route
app.use('/', (req, res, next) => {
if (isLaunched) {
return next()
}
// You can also render if you want
res.render('coming-soon')
});
How can I handle a post request to this?
According to https://expressjs.com/en/guide/using-middleware.html the syntax you already have is used for any type of HTTP request - including GET and POST. You can detect the method via req.method.
app.use() already handles ALL http methods, including GET and POST. You can see exactly which method it is for any given request by checking req.method.
If you had trouble with some GET or POST when doing this, then please show the specific code and the specific request that it didn't work for. If you didn't try it yet, then just try it as it should work just fine.
Middlewares are mounted using app.use(<middleware-name>) so, you can add it to all routes like you do for bodyParser/CORS etc.
If you want to mount for specific routes you can use
app.post("/example" , middleware, (req,res)=>{
res.send("Hello world")
})
Refer to Use middleware on specific routes

GET vs HEAD methods in Express. EXAMPLE

How to implement HEAD method in Node.js with Express server-side for a given GET method?
Can someone provide an example of usage of HEAD mehod vs GET method?
I mean code like:
Index.js
app.get ("/root", function (req, res) {
//some code
})
app.head ("/root", function (req, res) {
//some code
})
Http Head request is only used to request HTTP headers from the server and server must not return a body in it.
app.head("/root",(req,res)=>{
res.set('x-user', 'abcd')
})
Http get request is only used to get some request some body and additional headers(if needed)
app.get("/root",(req,res)=>{
res.json({email:'test'})
})
Please note: Both the type of request should not change the state in the system. For changing the state use POST, PUT, PATCH or DELETE methods

How to modify response headers with express-http-proxy

Background
I'm using express-http-proxy to proxy a handful of requests between my SPA (single page application) and a CouchDB instance. I'm doing this proxy on a per call basis, NOT creating a proxy server (this will be important in a moment).
example of current use
app.use(`some/url`, proxy(dburl, {
forwardPath: req => {return 'some/url'+require('url').parse(req.url).path;}
}) );
Which means I am NOT using httpProxy.createServer. I want to send some snippet of text data along with my responses as a header. After looking through the documentation I've come to the conclusion that what I want will be using intercept. Unfortunately I've not quite managed to grasp how to use it, and the only related questions I've found so far appear to be based on httpProxy.createServer which appears (from my limited understanding) to work differently.
We are using individual request proxying because we wish to proxy different requests to different micro-services, and found this to be the most concise way (that we knew of & at the time) of doing that.
The Question
Given the code
const text = 'asdf';
app.use(`some/url`, proxy(dburl, {
forwardPath: req => {return 'some/url'+require('url').parse(req.url).path;},
intercept: function(rsp, data, req, res, callback) {
//SUSPECT LOCATION
}
}) );
Is there some code at SUSPECT LOCATION which would allow me to place text on the header for the final response without further affects to the (currently otherwise working) proxy?
Additional Notes
Headers and network requests in general are not very familiar to me, my apologies if the answer seems self evident.
Bonus points for a link to a resource that helps explain either the finer points of using this library for proxying, a similar library for proxying, or the underlying technologies which would make it clear how to use this library for proxying. AKA I'd rather spend some of my own time looking further into this and not come back for further questions.
I am not entirely confident that the place for my code will be SUSPECT LOCATION and I will happily listen if it needs to go somewhere else, or if we need to approach this problem in a different way.
The accepted answer is now outdated.
Intercept does not exist anymore.
Instead, use your own middleware before the proxy function
router.route('/my-route').get((req, res, next) => {
res.set('My-Header', 'my-header-value');
next();
}, proxyFunction);
It follows express.js methods on req, res objects.
Within the intercept function body, set the response headers using the following express format.
res.set('hola', 'amigos!!!');
Refer below link:
http://expressjs.com/en/4x/api.html#res.set
The best way to understand a library when there is no documentation is to follow its test suite. If there is no test suite don't use that library.
This is the test suite for the express-http-proxy intercept function
https://github.com/villadora/express-http-proxy/blob/master/test/intercept.js
This is the test case
it('can modify the response headers', function(done) {
var app = express();
app.use(proxy('httpbin.org', {
intercept: function(rsp, data, req, res, cb) {
res.set('x-wombat-alliance', 'mammels');
res.set('content-type', 'wiki/wiki');
cb(null, data);
}
}));
request(app)
.get('/ip')
.end(function(err, res) {
if (err) { return done(err); }
assert(res.headers['content-type'] === 'wiki/wiki');
assert(res.headers['x-wombat-alliance'] === 'mammels');
done();
});
});
If you want to undetstand in and out of proxying, the best resource is haproxy
http://cbonte.github.io/haproxy-dconv/1.7/intro.html
But before that you need to understand http more (a constructive comment)

Hide an API key (in an environment variable perhaps?) when using Angular

I'm running a small Angular application with a Node/Express backend.
In one of my Angular factories (i.e. on the client side) I make a $http request to Github to return user info. However, a Github-generated key (which is meant to be kept secret) is required to do this.
I know I can't use process.env.XYZ on the client side. I'm wondering how I could keep this api key a secret? Do I have to make the request on the back end instead? If so, how do I transfer the returned Github data to the front end?
Sorry if this seems simplistic but I am a relative novice, so any clear responses with code examples would be much appreciated. Thank you
Unfortunately you have to proxy the request on your backend to keep the key secret. (I am assuming that you need some user data that is unavailable via an unauthenticated request like https://api.github.com/users/rsp?callback=foo because otherwise you wouldn't need to use API keys in the first place - but you didn't say specifically what you need to do so it is just my guess).
What you can do is something like this: In your backend you can add a new route for your frontend just for getting the info. It can do whatever you need - using or not any secret API keys, verify the request, process the response before returning to your client etc.
Example:
var app = require('express')();
app.get('/github-user/:user', function (req, res) {
getUser(req.params.user, function (err, data) {
if (err) res.json({error: "Some error"});
else res.json(data);
});
});
function getUser(user, callback) {
// a stub function that should do something more
if (!user) callback("Error");
else callback(null, {user:user, name:"The user "+user});
}
app.listen(3000, function () {
console.log('Listening on port 3000');
});
In this example you can get the user info at:
http://localhost:3000/github-user/abc
The function getUser should make an actual request to GitHub and before you call it you can change if that is really your frontend that is making the request e.g. by cheching the "Referer" header or other things, validate the input etc.
Now, if you only need a public info then you may be able to use a public JSON-P API like this - an example using jQuery to make things simple:
var user = prompt("User name:");
var req = $.getJSON('https://api.github.com/users/'+user);
req.then(function (data) {
console.log(data);
});
See DEMO

Categories