Search code examples
node.jshttprequestresponseget-requestsharp

Sharp keeps sending response. How to stop it?


I'm trying to resize an image using Sharp module and then render it on GET request path.

    fs.readFile(`${imageDir}${filename}.jpg`, (err, img) => {
      if (err) { // File name doesn't match existing images
        res.send('Error: No image found');
      }
      // Resizing image and saving it on file system
      sharp(img)
      .resize(Number(width), Number(height))
      .toFile(`${thumbDir}${filename}-${width}-${height}.jpg`) // ---> THIS HERE DOES res.end() or res.send()
      .then(info => {
        // Rendering image on page
        fs.readFile(`${thumbDir}${filename}-${width}-${height}.jpg`,(err, img) => {
          if (err) throw err;
          res.end(img); // -----> THIS ONE DOESN'T WORK
        });
      });
    });

I want to stop sharp().resize().toFile() from "send" or "end" the response so I can "end" with resized image.

I can't remember what I did but something made res.end(img) line work and I got an error that I can't set header after response is sent.

P.S. I'm so sorry for any badly explained sections, please feel free to ask for any clarification.


Solution

  • Even without knowing all of the context, I would recommend switching to the fs/promises APIs so you don't need to mix fs's callback-style asynchronicity with Sharp's promises. Then you can make your request handler async:

    const fsp = require("fs/promises");
    
    app.get("...", async (req, res) => {
      // (... read width, height, filename here...)
      try {
        const img = await fsp.readFile(`${imageDir}${filename}.jpg`);
        const thumbName = `${thumbDir}${filename}-${width}-${height}.jpg`;
        await sharp(img).resize(Number(width), Number(height)).toFile(thumbName);
        const thumb = await fsp.readFile(thumbName);
        // TODO: add correct content-type, etc. headers
        res.end(thumb);
      } catch (err) {
        // TODO: improve error handling
        console.error(err);
        res.status(400).end("Error processing file");
      }
    });
    

    PS: be sure to sanitize filename, width and height if they're user inputs; the above code is currently wide open to various file system traversal vulnerabilities.