0
\$\begingroup\$

The website TryHackMe came up with a challenge that involves using HTTP requests to interface with REST APIs (here, task #14/day 9). The challenge basically involves querying a basic REST API to reconstruct a string value from the information returned by the service. Specifically, the value key has a piece of the string to be appended to a final string, and the next key has a subdirectory to visit for the next value to be appended to the final string. The solution is supposed to repeat this procedure until the value key has a value of "end".

I published a writeup that discusses this further (if the paywall is giving you problems, just open this link in private browsing ;-):

Here are some things that I am curious about:

  1. What are your initial & overall impressions of the code?
  2. Is there a better way of writing an implementation?
  3. A bit of a rehash of the second one, but what do you not like about my code (assuming that you notice flaws)?
  4. A bit of a meta question: do you think I can present my problem & solution a little better next time?

And of course, my JavaScript solution

/*
 * An implementation to the Advent of Cyber's "Requests" task.
 * (Partially) ported from Hamdan (2021)'s solution
 * Implemented by Aleksey
 *  - GitHub: https://github.com/Alekseyyy
 *  - Keybase: https://keybase.io/epsiloncalculus
 */

const XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
const xhr = new XMLHttpRequest();
const url = "http://requests.thm:3000/";

let currentPath = "";
let flag = "";

let done = false;
while (!done) {
  if (currentPath.toLowerCase() === "end") {
    done = true;
    break;
  }

  xhr.open("GET", url + currentPath, false);
  xhr.send();

  const myJson = JSON.parse(xhr.responseText);
  flag += myJson["value"];
  currentPath = myJson["next"];
}

console.log(flag);

/* References
 * Hamdan, M. (2021). Python For Web Automation | TryHackMe
 *   Advent Of Cyber 1 Day 9. YouTube Video. Retrieved on Feb.
 *   12, 2023 from: https://youtu.be/zFeLExZNPso
 */
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

Your questions

"What are your initial & overall impressions of the code?"

  • Very old school, then I noticed that this must be Node.js. Is fetch still behind a flag??? Though a synchronous request is old school as well. When possible always use asynchronous API's

  • Looks like you do not understand what JSON is! JSON is a transport format (file) when loaded and parsed JSON is an object like any other object.

    You don't need to use bracket notation when not required. flag += myJson["value"]; is same as flag += myJson.value;

    You only use bracket notation if the object property has an illegal JavaScript name eg flag += myJson["1flag"]; is valid but as myJson.1flag is a syntax error.

  • Prefixing my to names is only for example code and represents a name to replace with your own variables name, you should never prefix my in your own code.

  • Not catching errors. JSON.parse can throw, server requests can fail, yet there is no error checking in your code?

  • currentPath too verbose in this context and could just be path


"Is there a better way of writing an implementation?"

Yes use the fetch API and async functions. Node has fetch behind some flags eg node --experimental-fetch myCode.js

See rewrite

Note rather than break out of the while loop, the rewrite tests for path === "end" inside the while clause using a reg expression eg while (!path.match(/^end$/i)) {


"A bit of a meta question: do you think I can present my problem & solution a little better next time?"

I edited your question and replaced the tag with as it was far more relevant to the question.

Rewrite

Rewrite uses fetch API and async function.

The catch will catch both request errors and JSON parsing errors.

const url = "url";
async function doThing() {
    var path = "", flag = "";    
    while (!path.match(/^end$/i)) {
        const data = await fetch(url + path).then(res => res.json());
        flag += data.value;
        path = data.next;       
    }
    return flag;
}

doThing()
    .then(flag => console.log(flag))
    .catch(error => console.error(error));
\$\endgroup\$
1
  • \$\begingroup\$ Hey, thanks for your feedback. I am not a JavaScript programmer (like you noticed, I'm more "old school"), so that's probably why my code is substandard. Regarding exception handling, I knowingly did not implement it because this is more "quick and dirty." And regarding the arrow operators, I did not use them since I'm more used to the object-oriented approach (though should work more with the functional approach). But yeah, we do appreciate your advices & will try to learn more JavaScript! \$\endgroup\$
    – Aleksey
    Commented Feb 24, 2023 at 0:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.