How to modify response headers with express-http-proxy - javascript

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)

Related

Javascript `http-proxy-middleware` onProxyRes and onProxyReq signature parameters

I'm new to Javascript, and it's a mind bending world to me.
I have a [web app] that talks to a [proxy] that talks to a [web service].
In the signature, onProxyRes(proxyRes, req, res), where do each of the parameters originate? It seems like all documentation assumes you already know how it works.
So far, it seems obvious to me req was the original request, does this mean res is the original response? If I am trying to inject headers, should I be updating proxyRes?
I'm having a CORS error, I believe I just need to inject the header...
'Access-Control-Allow-Origin', '*'
https://www.npmjs.com/package/http-proxy-middleware
indicates how to use this feature.
function onProxyRes(proxyRes, req, res) {
proxyRes.headers['Access-Control-Allow-Origin'] = '*';
}
should work.
However, I haven't gotten my example to work yet, so I am hoping another reply will come in, or you have it figured out now.

How do I grab an object from a website using Javascript/Node.js?

So let me first explain what I'm trying to achieve even though it's probably not the right way to go about this.
I make discord bots and my goal is to have the bot check with the website before starting/running commands. I (for obvious reasons) don't want to put the true/false in the code in the event I need to stop a bot from starting remotely.
I set something up on my Express app so that when the specific section of the response matches the client ID in the array, then grab the piece from the response where it says true or false. Act on it if it doesn't and do nothing if the object is equal to true. I have this part down, however the part that I don't know how to do is access this "object" from the bot.
Does anybody know how to do this?
app.get('/botAuthentication/getToken', (req, res) => {
if(['7838193829389238'].includes(req.query.authorization)) {
res.status(200)
res.send({
botAuth: true
})
} else {
return res
.status(401)
.send( { code: 401, message: "You can't view this page."})
}
});
This code returns the shown object when opened in the browser.
TLDR; How do I grab that object from the website using some sort of library or method?
I know this might not be the proper way to do this; I am new to web development.
Thank you in advance!
In your bot I suggest you use axios as it is a very easy to use fetch library, but you can use node-fetch, request or pick from many others....
const axios = require('axios')
// Somewhere in your bot...
axios.get('https://my-bot-command-and-control.example.com/botAuthentication/getToken', {
params: : {
authorization: '7838193829389238'
}
}).then((response) => {
if (response.botAuth) {
// do bot stuff
}
})
A couple of points... As a security perspective, it is imperative that you keep the secret authorization code a secret. That means no putting it in git and outside of your development environment, you must deploy the express server behind SSL termnination so the connection between your bot and the API is encrypted. Otherwise you will be transmitting the authorization code in plaintext.

Node.js and https certificate error handling

To make a long story short:
I'm building node app which making a request with https (the secure version of http). Whenever I miss-configure my request options, I'm having this error:
Node.js Hostname/IP doesn't match certificate's altnames
Great... except of the fact that the entire request code is wrapped with a valid try..catch block (which works just fine.. checked that already). The code is basically something like this:
try
{
https.request(options, (response) =>
{
// no way I making it so far this that error
}).end();
}
catch(ex)
{
// for some reason.. I'm not able to get here either
}
What I intend to do is to simply handle that error within my try..catch block
After reading some posts I've learned that this behavior is mainly because the tls module is automatically process the request and therefore making this error - this is a nice piece of information but it doesn't really help me to handle the exception.
Some other suggested to use this option:
rejectUnauthorized: false // BEWARE: security hazard!
But I rather not... so.. I guess my questions are:
Handling an error with a try..catch block should work here..right?
If not - is this behavior is by-design in node?
Can I wrap the code in any other way to handle this error?
Just to be clear - I'm not using any third-party lib (so there is no one to blame)
Any kind of help will be appreciated
Thanks
You need to add an 'error' event handler on the request object returned by https.request() to handle that kind of error. For example:
var req = https.request(options, (response) => {
// ...
});
req.on('error', (err) => {
console.log('request error', err);
});
req.end();
See this section in the node.js documentation about errors for more information.

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

Starting with Node.js and CouchDB without libraries like nano or cradle [duplicate]

This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Getting ' bad_request invalid_json' error when trying to insert document into CouchDB from Node.js
The highest voted answer on
CouchDB and Node.js - What module do you recommend?
recommends not to use libraries such as nano or cradle for starting with Node.js and CouchDB.
However I haven't found any tutorial on how to perform standard operations for all DBMSes like create database, create table, add and view data etc. programmatically.
EDIT: (partial answer) after installing and starting CouchDB go to http://localhost:5984/_utils/script/couch.js.
You should start by reading the CouchDB book.
No idea why you don't want to use a module: I think you took an answer out of context (an answer that is probably one year old) and made your decision not to use a module.
That is not likely to be helpful to get stuff done. :) You are just repeating work that is done, and issues that have been fixed, etc.
If you want to learn CouchDB, read the book. You can read nano's source as it maps really closely to the API and should be easy to read, but the book is the full way to go.
If by any reason you decide you still want to implement your own module to do what others already do well, go for it :)
If instead you are looking for resources on using nano there are quite a few:
readme: github
screencast: couchdb and nano
article: nano - a minimalistic couchdb client for nodejs
article: getting started with node.js and couchdb
article: document update handler support
article: nano 3
article: securing a site with couchdb cookie authentication using node.js and nano
article: adding copy to nano
article: how to update a document with nano
article: mock http integration testing in node.js using nock and specify
article: mock testing couchdb in node.js with nock and tap
Thanks to Ruben Verborgh, I compiled micro-tutorial from several sources myself.
var http = require('http')
var sys = require('sys')
var couchdbPath = 'http://localhost:5984/'
request = require('request')
h = {accept: 'application/json', 'content-type': 'application/json'}
request(
{uri: couchdbPath + '_all_dbs', headers:h},
function(err, response, body) { console.log(sys.inspect(JSON.parse(body))); }
)
// add database
request(
{uri: couchdbPath + 'dbname', method:'PUT', headers:h},
function (err, response, body) {
if (err)
throw err;
if (response.statusCode !== 201)
throw new Error("Could not create database. " + body);
}
)
// Modify existing document
var options = {
host: "localhost",
port: 5984,
path: "/dbname",
headers: {"content-type": "application/json"},
method: "PUT"
};
var req = http.request(options, function(res) {
console.log('STATUS: ' + res.statusCode);
//console.log('HEADERS: ' + JSON.stringify(res.headers));
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log('BODY: ' + chunk);
});
});
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
});
// write data to request body
req.write(JSON.stringify({
"_id":"rabbit",
"_rev":"4-8cee219da7e61616b7ab22c3614b9526",
"Subject":"I like Plankton"
}));
req.end();
I used following documentation:
http.request()
CouchDB Complete HTTP API Reference
Here are a few hands-on examples, thoughts and code-snippets which should help in your study
Simple Blog with Coffeescript, Express and CoudbDB
Thoughts on development using CouchDB and Nodejs
Bind CouchDB and Node.js
Getting Started with Node.js, Express and CouchDB - this link does not seem to be accessible now, but it seems a temporary issue.
Here's one on testing CouchDB - Mock testing CouchDB using Node.js
Hope it helps.
CouchDB is not an SQL database engine. It's in the family of the "NoSQL" ones.
You don't do select, you don't create tables, etc.
It's completely different.
It's actually using a REST API to work. Like, to access all the documents, you access them using an HTTP GET on the following URL: http://some.server/someDbName/_all_docs
For a more thorough introduction, I suggest looking for "CouchDB tutorial" on Google.
You'll find good links like this one or this one. (I'm not vouching for any, they just look good as an introduction.)
To make an http request in node.js, you can use the request method of the built-in http module. A shortcut method is http.get, which you can use like this:
var http = require( 'http' );
http.get( 'http://some.url/with/params', function( res ) {
// res has the values returned
});
Edit after reading your code:
Firstly, the doc you're using if outdated. Node is at v0.8, not 0.4.
Secondly, your request = require('request') must give some problems (does the module exist?). I don't think the first part is even executed.
Thirdly, just try a GET request for now. Something like:
var http = require( 'http' );
http.get( 'http://localhost:5984/_all_dbs', function( res ) {
console.log( res );
});
See if it's working. If it is, you already know how to use couchdb ;)
Lastly, your request at the end doesn't seem wrong. Maybe it's related to require('request') though, so I don't know.

Categories