Refactor routes

These options look neat but, following the route we're doing, it will probably be a mess to create all the path possibilities. We're also narrowing on the image names as we're creating virtual prefixes for these image manipulations options.

Let's make a change while we're at the beginning. Instead of using route parameters, let's use query parameters. They can be added in the order we want, and don't affect the path. We could also use request headers, but these would be harder to test both on the browser and using fetching modules such as request.

So, before we add our neat image manipulations, let's refactor our code to use query parameters. Express handles and decodes query parameters automatically, so we just need to change our download image function:

function download_image(req, res) {
fs.access(req.localpath, fs.constants.R_OK , (err) => {
if (err) return res.status(404).end();

let image = sharp(req.localpath);
let width = +req.query.width;
let height = +req.query.height;
let greyscale = (req.query.greyscale == "y");

if (width > 0 && height > 0) {
image.ignoreAspectRatio();
}

if (width > 0 || height > 0) {
image.resize(width || null, height || null);
}

if (greyscale) {
image.greyscale();
}

res.setHeader("Content-Type", "image/" +
path.extname(req.image).substr(1));

image.pipe(res);
});
}

We're not validating as we probably should, but we're ensuring the width and height are positive numbers. For greyscaling, we're checking whether the query parameter equals y. If you prefer to support more options on greyscaling such as yes or true, change the line to something like the following:

let greyscale = [ "y", "yes", "1", "on"].includes(req.query.greyscale);

Now, we can drop the width, height, and greyscale route parameters we added before, and just keep the image parameter. Also, all our download routes can be removed, and we just keep the simpler one. In the end, we'll have something like this:

const bodyparser = require("body-parser");
const path = require("path");
const fs = require("fs");
const express = require("express");
const sharp = require("sharp");
const app = express();

app.param("image", (req, res, next, image) => {
if (!image.match(/.(png|jpg)$/i)) {
return res.status(req.method == "POST" ? 403 : 404).end();
}

req.image = image;
req.localpath = path.join(__dirname, "uploads", req.image);

return next();
});

app.post("/uploads/:image", bodyparser.raw({
limit : "10mb",
type : "image/*"
}), (req, res) => {
let fd = fs.createWriteStream(req.localpath, {
flags : "w+",
encoding : "binary"
});

fd.end(req.body);

fd.on("close", () => {
res.send({ status : "ok", size: req.body.length });
});
});

app.head("/uploads/:image", (req, res) => {
fs.access(req.localpath, fs.constants.R_OK , (err) => {
res.status(err ? 404 : 200).end();
});
});

app.get("/uploads/:image", download_image);

app.listen(3000, () => {
console.log("ready");
});

Let's try it out now. You should be able to do a resize like we did before, but with a different address:

We can also add the greyscale function to it:

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset