2

I am in the process of building a picture framing calculator API using Node JS & Express. The JavaScript I am using is:

app.post("/api/chatfuel/calculator/triplematapi", (req,res) => {
    if (!(req.body.FrameWidth > -1)) {
        res.status(422).json({ messages: "Please insert a positive value" });
    }
    let FrameWidth = 1 * req.body.FrameWidth.split("/").reduce((a, denom) => a.split(" ").reduce((int, numer) => 1 * numer + int * denom) / denom);
    if (!(req.body.FrameHeight > -1)) {
        res.status(422).json({ messages: "Please insert a positive value" });
    }
    let FrameHeight = 1 * req.body.FrameHeight.split("/").reduce((a, denom) => a.split(" ").reduce((int, numer) => 1 * numer + int * denom) / denom);
    if (!(req.body.PictureWidth > -1)) {
        res.status(422).json({ messages: "Please insert a positive value" });
    }
    let PictureWidth = 1 * req.body.PictureWidth.split("/").reduce((a, denom) => a.split(" ").reduce((int, numer) => 1 * numer + int * denom) / denom);
    if (!(req.body.FrameHeight > -1)) {
        res.status(422).json({ messages: "Please insert a positive value" });
    }
    let PictureHeight = 1 * req.body.PictureHeight.split("/").reduce((a, denom) => a.split(" ").reduce((int, numer) => 1 * numer + int * denom) / denom);
    if (!(req.body.MiddleMat > -1)) {
        res.status(422).json({ messages: "Please insert a positive value" });
    }
    let MiddleMat = 1 * req.body.MiddleMat.split("/").reduce((a, denom) => a.split(" ").reduce((int, numer) => 1 * numer + int * denom) / denom);
    if (!(req.body.BottomMat > -1)) {
        res.status(422).json({ messages: "Please insert a positive value" });
    }
    let BottomMat = 1 * req.body.BottomMat.split("/").reduce((a, denom) => a.split(" ").reduce((int, numer) => 1 * numer + int * denom) / denom);
    let TopMatWidth = ((FrameHeight)-(PictureHeight))/2-(MiddleMat);
    let TopMatHeight = ((FrameWidth)-(PictureWidth))/2-(MiddleMat);
    let MiddleMatWidth = ((FrameHeight)-(PictureHeight))/2;
    let MiddleMatHeight = ((FrameWidth)-(PictureWidth))/2;
    let BottomMatWidth = ((FrameHeight)-(PictureHeight))/(2)+(BottomMat);
    let BottomMatHeight = ((FrameWidth)-(PictureWidth))/(2)+(BottomMat);
    res.json({"messages": [{"text": "Place the parallel mat guide at the following inch mark, then make the respective width and height cut starting with the Top Mat, Middle Mat, then Bottom Mat:"},{"text": `Top Mat Width Cut = ${new Fraction(TopMatWidth).toString()} inches`},{"text": `Top Mat Height Cut = ${new Fraction(TopMatHeight).toString()} inches`},{"text": `Middle Mat Width Cut = ${new Fraction(MiddleMatWidth).toString()} inches`},{"text": `Middle Mat Height Cut = ${new Fraction(MiddleMatHeight).toString()} inches`},{"text": `Bottom Mat Width Cut = ${new Fraction(BottomMatWidth).toString()} inches`},{"text": `Bottom Mat Height Cut = ${new Fraction(BottomMatHeight).toString()} inches`},{"buttons": [{"title": "Go to I Was Framed!","type": "web_url","url": "https://iwasframed.com/"}]}]});
});

Therefore, an example POST request would be:

{
    "FrameWidth": "16",
    "FrameHeight": "20",
    "PictureWidth": "11",
    "PictureHeight": "17",
    "MiddleMat": "1",
    "BottomMat": "1/2"
}

The problem I'm running into is that before I added a check to verify that the input value is positive, then the return response would make the calculation. However, by adding this code (I had to use -1 because 0 is a valid, positive input):

if (!(req.body.BottomMat > -1)) {
    res.status(422).json({ messages: "Please insert a positive value" });
}

Then any fraction I input such as 1/2 - it throws the error:

{
    "messages": "Please insert a positive value"
}

It should not be throwing a error message because these fractions are positive inputs. Can I get some guidance on how to prevent an error message when the input is a positive fraction as well?

thebluetropics
  • 82
  • 2
  • 10
Durendel
  • 489
  • 2
  • 12

3 Answers3

1

Your input "1/2" is string at the time you are checking it in your condition, so you need to convert it to number

If you are directly trying to convert the fraction string into number using Number("1/2") method it will throw NaN. so use eval("1/2")

It will solve your problem

if (!(eval(req.body.BottomMat) > -1)) {
        res.status(422).json({ messages: "Please insert a positive value" });
    }

If you need secure method you can add regex to validate the input is valid number

if (!(req.body.BottomMat.match(/^[0-9\/\.]+$/) != null && eval(req.body.BottomMat) > -1)) {
  ...
}

So if the input contains any text other than 0-9 and / and . it will return false so it doesn't run eval for malicious inputs

Ramkumar G
  • 415
  • 1
  • 8
  • Hi there. This works great, but is it possible to allow for the regex to allow for `mixed fractions` such as `16 1/2`? It works perfectly for fractions such as `1/2`. Thank you so much for your time!! – Durendel Aug 27 '22 at 08:18
  • yes you can use \s to match space `(/^[0-9\s\/\.]+$/)`. but eval doesnot work if you pass your input like `16 1/2` so you need to replace space with `+ or *` depending on your need. Then you can add these symbols in your regex to match it.. For example: ` var x = String(req.body.BottomMat).replace(" ", "*"); if (!(x.match(/^[0-9\\*\/\.]+$/) != null && eval(x) > -1)) {} ` – Ramkumar G Aug 27 '22 at 10:36
  • I have small suggestion in your code.. I'm not sure why you are using `> -1` to find possitive values. What about if the input in `-0.5`? . Use `>=0` instead – Ramkumar G Aug 27 '22 at 10:57
  • +1 This answer keeps the formatting in fraction format and mixed number format. And the answer provides sanitization for `eval`. Thank you. – Durendel Aug 27 '22 at 16:09
0

the problem is with your condition req.body.BottomMat > -1 BottomMat is a string and you compare string with number "1/2" > -1 therefore it returns false, you need to convert to number before check

Mike
  • 801
  • 4
  • 7
  • Thank you for the answer, but I was wondering if you could assist me further. I have tried to convert it based on here: [link](https://stackoverflow.com/questions/1133770/how-to-convert-a-string-to-an-integer-in-javascript) but I am unsure what I'm doing wrong. I've tried `BottomMat = parseInt(BottomMat)`, `BottomMat = parseFloat(BottomMat)`. Am I on the right track or could you respectfully help me? Thank you again for everything. – Durendel Aug 25 '22 at 23:21
  • you need to calc fraction result before parsing string like `"1/2"` is equal to `"0.5"` then parse it with `parseFloat` – Mike Aug 26 '22 at 07:47
  • or you can use lib that works with fractions – Mike Aug 26 '22 at 07:49
0

First Step

Don't send your data as 1/2, but as 0.5, because you will be able to parse it as Number with parseFloat().

Second Step

Now you can easily add validations:

app.post("/api/chatfuel/calculator/triplematapi", (req,res) => {
  const FrameWidth = parseFloat(req.body.FrameWidth);
  const FrameHeight = parseFloat(req.body.FrameHeight);
  const PictureWidth = parseFloat(req.body.PictureWidth);
  const PictureHeight = parseFloat(req.body.PictureHeight);
  const MiddleMat = parseFloat(req.body.MiddleMat);
  const BottomMat = parseFloat(req.body.BottomMat);
 
  if (FrameWidth < 0) res.status(422).json({ messages: "Please insert a positive value" });
  if (FrameHeight < 0) res.status(422).json({ messages: "Please insert a positive value" });
  if (PictureWidth < 0) res.status(422).json({ messages: "Please insert a positive value" });
  if (PictureHeight < 0) res.status(422).json({ messages: "Please insert a positive value" });
  if (MiddleMat < 0) res.status(422).json({ messages: "Please insert a positive value" });
  if (BottomMat < 0) res.status(422).json({ messages: "Please insert a positive value" });

  ...

});

NeNaD
  • 18,172
  • 8
  • 47
  • 89