Gzip not working - node.js

I am trying to handle gzip.
My sources: zlib,compression,https(article by Rob W)
Server-Side:
app.get('*', function (req, res, next) {
if (req.headers['x-forwarded-proto'] != 'https') {
res.setHeader('Content-Type', 'text/event-stream')
res.setHeader('Cache-Control', 'no-cache')
// send a ping approx every 2 seconds
var timer = setInterval(function () {
res.write('data: ping\n\n')
// !!! this is the important part
res.flush()
}, 2000)
res.on('close', function () {
clearInterval(timer)
})
res.redirect('https://...herokuapp.com' + req.url)//req.connection.remoteAddress
}
else {
next();
}
})
Error:
events.js:85
throw er; // Unhandled 'error' event
^
Error: write after end
at ServerResponse.OutgoingMessage.write (_http_outgoing.js:413:15)
at ServerResponse.res.write (...\index.js:80:17)
at null. (...\app.js:63:17)
at wrapper [as _onTimeout] (timers.js:265:14)
at Timer.listOnTimeout (timers.js:110:15)
Process finished with exit code 1
Client side request:
<link rel="stylesheet" type="text/css" href="../.../.../....min.css.gz">

You can't res.write() after res.redirect(). The latter ends the response.
You might consider creating a dedicated route for your Server-Sent Events stream instead.

Related

node reciving an unhandled error event need some insite?

I've searched Hi and Low through web sites and docs, and I've yet to figure out why Im getting this error. Yes I'm new to node. I thought id ask here as a last resort.
the error I'm receiving is:
events.js:292
throw er; // Unhandled 'error' event
^
Error [ERR_STREAM_WRITE_AFTER_END]: write after end
at writeAfterEnd (_http_outgoing.js:668:15)
at ServerResponse.end (_http_outgoing.js:789:7)
at Server.<anonymous> (/mnt/sdc/opt/codeWork/ReactBuilds/be_full-stack/app.js:10:9)
at Server.emit (events.js:315:20)
at parserOnIncoming (_http_server.js:874:12)
at HTTPParser.parserOnHeadersComplete (_http_common.js:126:17)
Emitted 'error' event on ServerResponse instance at:
at writeAfterEndNT (_http_outgoing.js:727:7)
at processTicksAndRejections (internal/process/task_queues.js:81:21) {
code: 'ERR_STREAM_WRITE_AFTER_END'
}
Here's my code I'm running node v14.16.0
const http = require('http')
const server = http.createServer((req, res)=>{
if(req.url === '/') {
res.end('Welcome to our home page')
}
if(req.url === '/about') {
res.end('Here is our short history')
}
res.end(`
<h1>Ooops</h1>
<p>This is not the page you are looking for</p>
backHome
`)
})
server.listen(5000)
any incites are very welcome
Thanks
You should introduce early returns in your code so that you don't call res.end multiple times when one of the conditions evaluates to true with your request handler still handling 404:
const server = http.createServer((req, res) => {
if (req.url === "/") {
return res.end("Welcome to our home page");
}
if (req.url === "/about") {
return res.end("Here is our short history");
}
res.end(`
<h1>Ooops</h1>
<p>This is not the page you are looking for</p>
backHome
`);
});

NodeJS -> Error: write after end (only after first request)

In my express app i have the route below:
router.get('/generatedData', function (req, res) {
res.setHeader('Connection' , 'Transfer-Encoding');
res.setHeader('Content-Type' , 'text/html; charset=utf-8');
res.setHeader('Transfer-Encoding' , 'chunked');
var Client = someModule.client;
var client = Client();
client.on('start', function() {
console.log('start');
});
client.on('data', function(str) {
console.log('data');
res.write(str);
});
client.on('end', function(msg) {
client.stop();
res.end();
});
client.on('err', function(err) {
client.stop();
res.end(err);
});
client.on('end', function() {
console.log('end');
});
client.start();
});
On first call everything works fine (console)
We've got ourselves a convoy on port 3000
start
data
data
data
data
data
...
data
end
GET /generatedData 200 208.426 ms - -
I get all the data and res.end() is being called and successfully closes the request.
The problem starts after first request. I make the exact same request (new one of course) and i get the following error (console):
start
data
data
data
events.js:160
throw er; // Unhandled 'error' event
^
Error: write after end
at ServerResponse.OutgoingMessage.write (_http_outgoing.js:439:15)
at Client.<anonymous> (/Users/xxxx/projects/xxxx/routes/index.js:33:17)
at emitOne (events.js:96:13)
at Client.emit (events.js:188:7)
at FSWatcher.<anonymous> (/Users/xxxx/projects/xxxx/lib/someModule.js:116:32)
at emitTwo (events.js:106:13)
at FSWatcher.emit (events.js:191:7)
at FSEvent.FSWatcher._handle.onchange (fs.js:1412:12)
[nodemon] app crashed - waiting for file changes before starting...
This happens without res.end() being called.
I manage to get some data before the crash.
How can i get this error without res.end() being called at all?
Do i somehow save the previous res instance?
Thanks,
Asaf
Have the same problem. My module was extened by EventEmitter and each time i catch event in router - it stays there, end on second call there are two eventlisteners not one. Setting "once" instead of "on" - worked for me.
client.once('start', function() {
console.log('start');
});
instead of
client.on('start', function() {
console.log('start');
});

How to test a function that throws an error asynchronously, using tape?

I am attempting to test this module (receiver.js) for an error thrown:
var request = require('request')
module.exports = function(url){
request({
url: url,
method: 'POST'
}, function(error) {
if(error){
throw error
}
})
}
using this test (test.js):
var test = require('tape')
test('Receiver test', function(t){
var receiver = require('./receiver')
t.throws(function(){
receiver('http://localhost:9999') // dummy url
}, Error, 'Should throw error with invalid URL')
t.end()
})
but tape runs the assertion before the error is thrown, resulting in the following error message:
TAP version 13
# Receiver test
not ok 1 Should throw error with invalid URL
---
operator: throws
expected: |-
[Function: Error]
actual: |-
undefined
at: Test.<anonymous> (/path/to/tape-async-error-test/test.js:5:4)
...
/path/to/receiver.js:9
throw error
^
Error: connect ECONNREFUSED 127.0.0.1:9999
at Object.exports._errnoException (util.js:856:11)
at exports._exceptionWithHostPort (util.js:879:20)
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1062:14)
Is there a way around this?
Generally, using tape, you have to ensure you call assert.end() after the async call has completed. Using promises (would require request-promise and returning the promise):
test('Receiver test', function(t){
// Tells tape to expec a single assertion
t.plan(1);
receiver('http://localhost:9999')
.then(() => {
t.fail('request should not succeed')
})
.catch(err => {
t.ok(err, 'Got expected error');
})
.finally({
t.end();
});
});
Using async/await:
test('Receiver test', async function(t) {
try {
await receiver('http://localhost:9999');
assert.fail('Should not get here');
} catch (err) {
assert.ok(err, 'Got expected error');
}
t.end();
});
The above example is mostly correct but here's a complete working example that compares async to synchronous side by side and also shows how to check for the error message in a manner similar to the tape examples given on tape's README.md.
test('ensure async function can be tested to throw', async function(t) {
// t.throw works synchronously
function normalThrower() {
throw(new Error('an artificial synchronous error'));
};
t.throws(function () { normalThrower() }, /artificial/, 'should be able to test that a normal function throws an artificial error');
// you have to do this for async functions, you can't just insert async into t.throws
async function asyncThrower() {
throw(new Error('an artificial asynchronous error'));
};
try {
await asyncThrower();
t.fail('async thrower did not throw');
} catch (e) {
t.match(e.message,/asynchronous/, 'asynchronous error was thrown');
};
});

Get HTML page by URL

Here is my code:
utilitesRouter.route('/url')
.post(function(request, response) {
console.log(request.body.uri);
var urlOpts = { host: request.body.uri, path: '/', port: '80', method: 'GET' };
var re = /(<\s*title[^>]*>(.+?)<\s*\/\s*title)>/gi;
http.get(urlOpts, function (response) {
response.on('data', function (chunk) {
var str=chunk.toString();
console.log(str);
var match = re.exec(str);
if (match && match[2]) {
console.log(match[2]);
}
});
});
response.json({ url: request.body.uri });
});
If I use POST request with this JSON {"uri":"google.ru" } I get:
302 Moved
google.ru
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
here.
</BODY></HTML>
If I use POST requiet with JSON {"uri":"http://google.ru" } I get the error message:
events.js:85
throw er; // Unhandled 'error' event
^
Error: getaddrinfo ENOTFOUND http://google.ru
at errnoException (dns.js:44:10)
at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:94:26)
I can open http://google.ru in my browser.
How can I get the HTML using node.js ?
You may want to request to do that. It just pretty easy.
var request = require("request");
router.get('/proxy', function(req, res, next){
request.get( req.body.uri, function(error, response, body){
if( error )
return next(error);
res.send(body);
});
});
request also support streaming and other cool features too.
You get the error because in your urlOpts the attribute host has to be a domain name, like google.ru or www.google.ru. As you are putting a URL into it, it can't be resolved to an IP via DNS, that's why you get the error at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:94:26).
If you want to use http.get() like the way you do, you would always have to extract the domain part out of your passed uri, i.e. getting google.ru out of http://google.ru to use it as host.

gulp.watch error: write after end

I am getting different results for different gulp.watch instruction
When I execute my watch task and change an .html file, everything works correctly (tasks defined below)
But when I change any other files (.coffee, .less, etc) I get this error:
stream.js:94
throw er; // Unhandled stream error in pipe.
^
Error: write after end
at writeAfterEnd (/Users/oclement/Documents/phoenix/MedifastCerBrokenDown/MedifastWeb/AppSource/node_modules/gulp-filter/node_modules/through2/node_modules/readable-stream/lib/_stream_writable.js:145:12)
at Transform.Writable.write (/Users/oclement/Documents/phoenix/MedifastCerBrokenDown/MedifastWeb/AppSource/node_modules/gulp-filter/node_modules/through2/node_modules/readable-stream/lib/_stream_writable.js:193:5)
at Stream.ondata (stream.js:51:26)
at Stream.emit (events.js:95:17)gulp.watch`
Watch Task
gulp.task('watch', function() {
isWatching = true;
run('build', 'index', function() {
g.util.log(g.util.colors.green('Starting to Watch'));
gulp.watch('./app/**/*.html', ['templates']);
gulp.watch('./app/**/*.coffee', ['phnxjs']);
...
});
});
Template Task
gulp.task('templates', function(done) {
g.util.log(g.util.colors.green('---TEMPLATES---'));
sourceStreams.templates()
.pipe(buildWatchPipe()())
.pipe(g.ngHtml2js(options.templates))
.pipe(g.concat(destinations.templates.bundleName))
.pipe(g.if(isProd, transformScriptsProd()))
.pipe(destinations.templates.target())
.pipe(g.if(isWatching, g.livereload()));
done();
});
Phnxjs Task
gulp.task('phnxjs', function(done) {
g.util.log(g.util.colors.green('---PHNXJS---'));
var wrapException = g.filter('!**/tags-input.js');
sourceStreams.phoenixScripts()
.pipe(buildWatchPipe()())
.pipe(filters.coffee)
.pipe(g.coffee(options.coffee))
.on('error', g.util.log)
.pipe(filters.coffee.restore())
.pipe(wrapException)
.pipe(iffeWrapper())
.pipe(wrapException.restore())
.pipe(g.if(!isProd, g.angularFilesort()))
.pipe(g.if(isProd, transformScriptsProd()))
.pipe(g.if(isProd, g.concat(destinations.phoenixScripts.bundleName)))
.pipe(destinations.phoenixScripts.target())
.pipe(g.if(isWatching, g.livereload()));
done();
});

Resources