iCurious
iCurious

Reputation: 8313

NodeError: write after end in NodeJS

I am starting to learn NodeJS and started to make a small application that encrypts and decrypts a file upon user click request. The below code works fine on first encryption request but crashes on another.

App.js

var fs = require('fs')
var crypto = require('crypto')
const express = require('express')
const app = express()
const port = 3000
var key = '1bd';
var cipher = crypto.createCipher('aes-256-cbc', key);
var decipher = crypto.createDecipher('aes-256-cbc', key);


app.use(express.static('public'))


app.get('/', (req, res) => {
    res.sendFile('/enc-dec.html', { root: __dirname })
})

app.post('/encrypt', (req, res) => {
    fs.createReadStream('input.txt')
    .pipe(cipher)
    .pipe(fs.createWriteStream('input.txt.enc'))
    .on('finish', function() {
        res.end("Encrypted")
    });
})

app.listen(port, () => console.log(`App listening on port ${port}!`))

Error:

NodeError: write after end
    at writeAfterEnd (_stream_writable.js:237:12)
    at Cipher.Writable.write (_stream_writable.js:287:5)
    at ReadStream.ondata (_stream_readable.js:646:20)
    at ReadStream.emit (events.js:180:13)
    at addChunk (_stream_readable.js:269:12)
    at readableAddChunk (_stream_readable.js:256:11)
    at ReadStream.Readable.push (_stream_readable.js:213:10)
    at fs.read (fs.js:2123:12)
    at FSReqWrap.wrapper [as oncomplete] (fs.js:680:17)
Emitted 'error' event at:
    at Cipher.onerror (_stream_readable.js:670:12)
    at Cipher.emit (events.js:180:13)
    at writeAfterEnd (_stream_writable.js:239:10)
    at Cipher.Writable.write (_stream_writable.js:287:5)
    [... lines matching original stack trace ...]
    at fs.read (fs.js:2123:12)

I am not expert in that but it seems issue with fs. Any help would be greatly appreciated. Thanks!

Upvotes: 3

Views: 2227

Answers (1)

RyanZim
RyanZim

Reputation: 7004

Your problem is that you're reusing the same cipher multiple times. After it's used in a stream once, it cannot be reused; a new one must be created.

You should create your cipher in the request handler, like this:

app.post('/encrypt', (req, res) => {
    var cipher = crypto.createCipher('aes-256-cbc', key);
    fs.createReadStream('input.txt')
    .pipe(cipher)
    .pipe(fs.createWriteStream('input.txt.enc'))
    .on('finish', function() {
        res.end("Encrypted")
    });
})

It doesn't look like you have the decrypt functionality done yet, but when you build that, you'll also need to move var decipher = crypto.createDecipher('aes-256-cbc', key); down into the request handler, because deciphers can't be reused either.

Upvotes: 1

Related Questions