2

I am attempting to build an application that allows users to run a speedtest on the WiFi network they are connected to.

Obviously this is doable. There are many such stand alone speedtest apps: Speedtest.net and Google for example.

There are many speed test modules on NPM but these only work on the server which isn't helpful for my project.

When I Webpack / Browserify any of these modules and try to run the code within the browser it doesn't work. I get Cross Origin errors.

What do I need to do to perform (reliable) client side speed tests? I haven't been able to find an clear examples of an implementation of something like this.

Ideally, I'd be able to use a 3rd party API like speedtest.net or Google but, as mentioned, I'm getting cross origin errors when I try this.

currenthandle
  • 1,038
  • 2
  • 17
  • 34
  • To do a cross origin request from the browser you need either the remote server to allow that using CORS or you need a proxy on the same origin as your code is running. –  Aug 14 '18 at 19:11
  • By the way, I am not sure what you mean with run a speedtest on the WiFi network they are connected to. –  Aug 14 '18 at 19:12
  • @ErickRuizdeChavez run a speed test, as in test the speed of the network you are connected to. Like if you when to http://www.speedtest.net/ and click on the "GO" button, it will test and report the upload speed, download speed and ping of your network. – currenthandle Aug 14 '18 at 19:24
  • @ErickRuizdeChavez how would the proxy work? Would it be testing the network of the client o the proxy? – currenthandle Aug 14 '18 at 19:25
  • I remember I did some basic download speed test a while ago (10+ years maybe) with flash. The idea was to have a file on a server (you know the size before hand) and then calculated the speed based on the percentage downloaded vs the elapsed time. Upload speed test was harder cause there was no report of progress till the end and at that time we ended up licensing Ookla's. –  Aug 14 '18 at 19:28
  • A simple proxy for cross domain needs to be on your domain (where your code is hosted so you do not run into cross domain issues). You then send a request to this server with a remote origin and the request is performed in the server, not in the client. This can be done with any basic scripting language like php, python, ruby etc. It could even be done with a reverse proxy setting on Apache or Nginx. –  Aug 14 '18 at 19:29
  • the answer below is quite good for me. I tried it and placed the file download on different server, and it's fine. – gumuruh Mar 22 '20 at 06:06

1 Answers1

2

Ok, I adapted this from an MDN example to do a very simple and most likely inaccurate download speed test. It runs 100% on the browser and since everything is local for now speeds are too fast, so in Chrome you can enable throttling to get a more realistic experience.

enter image description here

In the server I have a text.txt file that weights about 3 MB. On the same server and path I have the following code:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>

<body>

  <div>
    Progress: <span class="progress">0%</span>
  </div>

  <div>
    File size: <span class="size">...</span>
  </div>

  <div>
    Total time: <span class="time">...</span>
  </div>

  <div>
    Speed: <span class="speed">...</span>
  </div>

  <script>
    const start = Date.now();
    const url = 'text.txt';
    const xhr = new XMLHttpRequest();
    let end;
    let size;
    let time;

    xhr.addEventListener("progress", updateProgress);
    xhr.addEventListener("load", transferComplete);
    xhr.addEventListener("error", transferFailed);
    xhr.addEventListener("abort", transferCanceled);

    xhr.open('GET', url);
    xhr.send();


    function updateProgress(oEvent) {
      if (oEvent.lengthComputable) {
        if (!size) {
          size = oEvent.total;
          document.querySelector('.size').innerHTML = `${Number.parseFloat(size / 1024 / 1024).toFixed(2)} MB`;
        }

        var percentComplete = oEvent.loaded / oEvent.total * 100;
        document.querySelector('.progress').innerHTML = `${parseInt(percentComplete, 10)}%`;
      }
    }

    function transferComplete(evt) {
      console.log('The transfer is complete.');
      end = Date.now();

      time = (end - start) / 1000;
      document.querySelector('.time').innerHTML = `${parseInt(time, 10)} seconds`;
      document.querySelector('.speed').innerHTML = `${Number.parseFloat(size / time / 1024).toFixed(2)} kB/s`;
    }

    function transferFailed(evt) {
      console.log('An error occurred while transferring the file.');
    }

    function transferCanceled(evt) {
      console.log('The transfer has been canceled by the user.');
    }

  </script>
</body>

</html>
  • Yes, I've tried this approach as well. But like you said it's likely quite inaccurate and I require reliable measurements. I was looking into Ookla as you mentioned (they actually host speedtest.net). It looks like I might be able to embed their applet in my app. Not ideal, but maybe I can make that work. – currenthandle Aug 14 '18 at 20:59
  • I tried your code above, and the result is good if we put the image 3MB on the different server. how about the upload test? – gumuruh Mar 22 '20 at 04:01