h2non/rocky

Changing request URL randomly fails to get any response

ZzZombo opened this issue · 0 comments

I'm trying to create a proxy that by default simply forwards all requests to server the client originally intended to, so it looks like client -> server from the client's point of view, even tho there is proxy between them, but also is able to change request parameters, like headers and URL if configured to do so. I've written code to redirect /favicon.ico GET requests to a different .ICO on a different domain from what is requested (say, mysite.net/favicon.ico to example.com/icons/icon.ico), and the problem is that I seemingly randomly get the correct resource back from example.com, but other times I get no response at all, silently.

Example log of events as recorded by the proxy, the format is: first morgan line before request is examined and maybe modified, then it's details, then morgan line after all possible actions; the first part is the failed request, while the other, identical to the first, goes through successfully:

::ffff:127.0.0.1 - GET http://127.0.0.1/favicon.ico HTTP/1.1 - - - - ms
Proxy request: http://findicons.com/files/icons/2619/social_icons/77/github.png to host findicons.com
{ host: 'findicons.com',
  'proxy-connection': 'keep-alive',
  pragma: 'no-cache',
  'cache-control': 'no-cache',
  'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.111 Safari/537.36 Vivaldi/1.8.770.44',
  accept: 'image/webp,image/*,*/*;q=0.8',
  dnt: '1',
  'accept-encoding': 'gzip, deflate, sdch, br',
  'accept-language': 'ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4',
  'x-forwarded-for': '192.168.0.0',
  'x-real-ip': '192.168.0.0' }
::ffff:127.0.0.1 - GET http://findicons.com/files/icons/2619/social_icons/77/github.png HTTP/1.1 - - - - ms

::ffff:127.0.0.1 - GET http://127.0.0.1/favicon.ico HTTP/1.1 - - - - ms
Proxy request: http://findicons.com/files/icons/2619/social_icons/77/github.png to host findicons.com
{ host: 'findicons.com',
  'proxy-connection': 'keep-alive',
  pragma: 'no-cache',
  'cache-control': 'no-cache',
  'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.111 Safari/537.36 Vivaldi/1.8.770.44',
  accept: 'image/webp,image/*,*/*;q=0.8',
  dnt: '1',
  'accept-encoding': 'gzip, deflate, sdch, br',
  'accept-language': 'ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4',
  'x-forwarded-for': '192.168.0.0',
  'x-real-ip': '192.168.0.0' }
::ffff:127.0.0.1 - GET http://findicons.com/files/icons/2619/social_icons/77/github.png HTTP/1.1 - - - - ms
Proxy response: http://127.0.0.1/favicon.ico with status 200
{ server: 'nginx/1.1.19',
  date: 'Wed, 29 Mar 2017 04:33:07 GMT',
  'content-type': 'image/png',
  'content-length': '9850',
  'last-modified': 'Sun, 19 Aug 2012 06:35:42 GMT',
  connection: 'close',
  'accept-ranges': 'bytes' }

My code for the proxy:

'use strict';
const url=require('url');
const compression = require('compression');
const morgan = require('morgan');
const xpress = require('express');
const server=xpress();
const rocky = require('rocky');
const proxy = rocky();

const port=3128;

console.log('Running...');
proxy.options(
{
	timeout:1000,
	proxyTimeout:1000,
	ws:true,
	preserveHeaderKeyCase: true,
}).useForward(morgan('short',{immediate:true}),(req,res,next) =>
{
	if(!req.headers.host)
	{
		console.error('Protocol error, missing the Host header.');
		return true;
	}
	let new_url;
	if(req.url.endsWith('/favicon.ico'))
	{
		new_url='http://findicons.com/files/icons/2619/social_icons/77/github.png';
	}
	const parsedURL=url.parse(new_url || req.url);
	const proto=parsedURL.protocol+'//',host=proto+req.headers.host;
	if(new_url)
	{
		const target_url=url.parse(url.resolve(host,new_url));
		req.rocky.options.target = proto+target_url.hostname;
		req.headers.host=target_url.hostname;
		req.url=req.originalUrl=target_url.href;
	}
	else
	{
		req.rocky.options.target = host;
	}
	console.log(`Proxy request: ${req.url} to host ${req.headers.host}`);
	console.dir(req.headers);
	next();
},morgan('short',{immediate:true}),compression());
proxy.useResponse((req,res,next) =>
{
	console.log('Proxy response:',req.url,'with status',res.statusCode);
	console.dir(res._headers);
	next();
},compression());

proxy.on('error',(err,req,res) =>
{
	res.writeHead(500,
	{
		'Content-Type': 'text/plain'
	});
	res.end('Something went wrong with your request.\n'+err.toString());
});
proxy.listen(port);
console.log(`Proxy-server running at http://127.0.0.1:${port}/`);

server.use(morgan('tiny'));
server.use(xpress.static("public"));
server.on('clientError',(err, socket) =>
{
  socket.end('HTTP/1.1 400 Bad Request (S)\r\n\r\nSomething went wrong.\n'+err.toString());
});
server.listen(80);

Am I doing this wrong? Why does it work occasionally?