Giter VIP home page Giter VIP logo

network.js's Introduction

Network.js Build Status

A JavaScript library, entirely written in ES6, to measure various aspects of a connection. It can accurately estimate a bandwidth/latency between a client (using a web browser) and a server (running a specific script).

THE PROJECT IS ON HOLD

I'm not working on Network.js anymore because I don't have time for it. It will stay on hold until I found some time to work on it or until someone wants to become the new maintainer of this project.

Contact me on my e-mail address (see my Github profile) if you want to become the new maintainer of Network.js.

Installation

Use Bower or download an archive from the releases page:

bower install network-js
<script src="bower_components/network-js/dist/network.min.js"></script>

Next, add the server.php on your web server.

How to use

var settings = {

    endpoint: 'path/to/the/server.php', // Where is located the PHP file.

    // The complete settings list is available below.

};

// Create a new Network instance by providing an optional object.
var net = new Network(settings);

// Listen for the "end" event which provides the calculated latencies.
net.latency.on('end', function(averageLatency, allLatencies) {
    // "allLatencies" is an array containing the five calculated latencies in
    // milliseconds. They're used to determine an average latency.
    console.log('end', averageLatency, allLatencies);
});

// Once all the configuration is done, start the requests for this module.
net.latency.start();

// It is possible to chain functions for all the modules, here's an example with the
// upload module.
net.upload
     .on('start', function(dataSize) {
         console.log('start', dataSize);
     })
     .on('progress', function(averageSpeed, instantSpeed) {
         // Every bandwidth measure are in Mega BYTES per second!
         console.log('progress', averageSpeed, instantSpeed);
     })
     .on('restart', function(dataSize) {
         // The restart event is triggered when the module didn't have time
         // (according to the `delay` option) to take all the measures. A new
         // request will start with data size increased by the multiplier value.
         console.log('restart', dataSize);
     })
     .on('end', function(averageSpeed, allInstantSpeeds) {
         console.log('end', averageSpeed, allInstantSpeeds);
     })
     .start();

// You can also cancel a request (except for the "latency" module).
net.upload.abort();

net.download
     .on('start', function(dataSize) {
         console.log('start', dataSize);
     })
     .on('progress', function(averageSpeed, instantSpeed) {
         console.log('progress', averageSpeed, instantSpeed);
     })
     .on('restart', function(dataSize) {
         console.log('restart', dataSize);
     })
     .on('end', function(averageSpeed, allInstantSpeeds) {
         console.log('end', averageSpeed, allInstantSpeeds);
     })
     .start();

net.download.abort();

Settings

The available settings with their default values:

{
    latency: {
        // Where is located your `network.php` file.
        endpoint: './network.php',
        // How many measures should be returned.
        measures: 5,
        // How much attempts to get a valid value should be done for each measure.
        attempts: 3
    },

    upload: {
        // Where is located your `network.php` file.
        endpoint: './network.php',
        // The delay while you want to take measures.
        delay: 8000,

        data: {
            // The amount of data to initially use.
            size: 2 * 1024 * 1024, // 2 MB

            // If the measure period can't reach the delay defined in the settings,
            // the data amount is multiplied by the following value.
            multiplier: 2
        }
    },

    download: {
        // Where is located your `network.php` file.
        endpoint: './network.php',
        // The delay while you want to take measures.
        delay: 8000,

        data: {
            // The amount of data to initially use.
            size: 10 * 1024 * 1024, // 10 MB

            // If the measure period can't reach the delay defined in the settings,
            // the data amount is multiplied by the following value.
            multiplier: 2
        }
    }
}

Here is an example usage:

var net = new Network({
    // If you define a value at the top level of the object,
    // it will be applied to every module.
    endpoint: './my-new-endpoint/',

    download: {
        data: {
            multiplier: 2.5
        }
    }
});

You can also redefine settings whenever you want:

// The `settings()` method takes an object in parameter.
net.settings({
    endpoint: './my-second-new-endpoint'
});

// Without any parameters, it will return the current settings.
console.log(net.settings()); // Prints the current settings in the console.

// Each module has a `settings()` method that works the same way.
net.latency.settings({
    measures: 10
});
console.log(net.latency.settings());

Server configuration

If you use Apache with its default configuration, everything should work.

If you get any errors, check your server configuration, you must:

  • Disable persistent HTTP connections and add a Connection: close header to responses.
  • Disable any form of cache with Cache-Control: no-cache, no-store, no-transform and Pragma: no-cache.
  • Disable GZIP compression.
  • Disable the body size limit.

Compatibility

Network.js is based on two browser features: Resource Timing and XMLHttpRequest (v2). While the first one can be polyfilled, the second one is a requirement.

Thus, Network.js should be compatible with:

Browser Partial support (polyfill) Native support
IE 10+
Firefox 35+
Chrome 29+
Opera 15+
Android Browser 4.4+
Safari 5+
iOS Safari 5.1+
Firefox 12+
Opera 12.1+
Android Browser 3+

Latency measures can be very far from reality if the browser doesn't support Resource Timing and uses the provided polyfill. You can determine if the browser uses the latter:

if (Network.supportsResourceTiming) {
    // Resource Timing is available.
} else {
    // The polyfill will be used, expect some weird latency measures.
}

Caveats

  • Chrome cannot upload a ~128 MB file, which will mainly affect fiber users.

Compilation

To compile the project, install the latest version of Node and run these commands inside a terminal:

git clone https://github.com/nesk/network.js.git
cd network.js
npm install
npm run build

There's also a watch script which compiles the project whenever a file is changed:

npm run watch

To check if the project passes all the tests, run:

npm test

Contribution

Read the CONTRIBUTING file.

License

This project is licensed under the MIT license, check TLDRLegal for details.

network.js's People

Contributors

charley-peng avatar jarzon avatar nesk avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

network.js's Issues

Handle the case where the server reaches it's maximum content size

Currently, if the client asks for a file with a size superior to 200MB, it will relaunch the measure indefinitely.

What we need in the future:

  • The client doesn't make a complete measure with 150MB of data. Before it triggers the restart event it asks for 300MB of data to the server.
  • The server can return a maximum of 200MB, it can't fulfill the request so it returns an error (for example, a 409 HTTP code with an appropriate message).
  • The client cancels the restart event and emits the end event with the measures made with 150MB of data. Optionally, a warning could be thrown and a special event emitted.

fiber link : big differences between browsers

Hi
I have a 100MB fiber optic link.

Firefox :
=> Upload : 79.079 MBps
=> Download : 98.210 MBps

Google Chrome :
=> Upload : 79.953 MBps.
=> Download : 50.461 MBps.

On Google Chrome, the download result it's always around 50MB.
It's a interne limit of Chrome ? (Same problem with Chromium).

Upload/Download requests gets cancled

Hi, i am trying to setup a speed test.
the download and upload requests are getting cancelled .
you can check my code here : http://farhadadeli.ir/SpeedTest
can you help? it's kind of urgent ...
I am using the provided php file as the server.

I used the code from your "How to use" witch is not working, but then i used the "main.js" file from your own sample site and that one works.

Support static files for download measures

The client should support requesting static files for download mesures, a possible API could be:

new Network({
    download: {
        endpoint: [
            './static-file-1',
            './static-file-2',
            './static-file-3',
            './static-file-4'
        ]
    }
});

This way, the download measure will start by requesting ./static-file-1, if the measure isn't complete, it will request the second file, etc…

Network.js will provide a cli to generate a file with a specific size:

$ npm install -g network-js
$ network-js 5
-----
$ network-js 5 --content="0"
00000
$ network-js 5 data/output-file-1
$ network-js 10 data/output-file-2

server side implementation?

Hello,

I was interested in this project and made an attempt to get it going. I started with the example PHP script for downloads, but it seems I might have something incorrect with my port to nodejs' express framework. The client side seems to continue trying to download but never stops, and continues saying "did not reach the right size in the delay."

The code I'm attempting to use is as follows:

router.get('/test', function(req, res) {
  var module = req.param('module');
  console.log("Dealing with: ", module);

  res.set({
    // Make sure the connection closes after each request
    'Connection': 'close',
    // Don't let any caching happen
    'Cache-Control': 'no-cache, no-store, no-transform',
    'Pragma': 'no-cache',
  })

  if (module && module == 'download') {
    // Default to 20mb file download, unless a size is specified.
    var contentSize = req.param('size', 20 * 1024 * 1024);
    var baseString = 'This text is so uncool, deal with it. ';
    var baseLength = baseString.length;

    // Make this an application/octet-stream
    res.set('Content-Type', 'application/octet-stream');

    for (var i = 0; i < parseInt(contentSize / baseLength); i++) {
      res.write(baseString);
    }

    var lastBytes = contentSize % baseLength;

    if (lastBytes > 0) {
      res.write(baseString.substring(0, lastBytes));
    }

    res.send();

  } else {
    // We need to actually send something, otherwise express just hangs forever
    res.send('OK');
  }
});

router.post('/test', function(req, res) {
  var module = req.param('module');
  console.log("Dealing with: ", module);
  res.set('Content-Type', 'text/html; charset=UTF-8');
  res.set('Connection', 'close');

  var body = ''

  var length = 0;

  if (module && module == 'upload') {
    req.on('data', function(data) {
    });

    req.on('end', function() {
      console.log('end', length);
      res.send('bye.');
    });
  } else {
    res.send("bye.");
  }
});

On the client side i simply set the endpoint to './test' on my nodejs server which also serves a copy of your example site at http://code.jpardanaud.com/speedtest/.

Is there anything I'm missing from the server end? I can get latency tests to work just fine, but download continues forever, and upload stops processing (doesn't even post to my server) at 512mb each time.

Add unit testing

With continuous integration, Travis CI (preferred) or CircleCI.

Delay time is not changing

Hi i am using the below code and network-js library is not working for these settings.

var net = new Network({
      delay: 20000,
      upload: {
          // Where is located your `network.php` file.
          endpoint: './network.php',
          // The delay while you want to take measures.
          delay: 20000,

          data: {
              // The amount of data to initially use.
              size: 2 * 1024 * 1024, // 2 MB

              // If the measure period can't reach the delay defined in the settings,
              // the data amount is multiplied by the following value.
              multiplier: 2
          }
      }
    });

Speed with 1Gbit/s

Hi.
Is this library able to check speed about 1Gbit/s?

We are using project:
enryIT/html5_speedtest#5
Author says that it's just UI for network.js, so i suppose he thing about library problem.

Support endpoint callbacks

new Network({
    /**
     * Called each time a request is started.
     * @param  {string} module The module name: "latency", "upload" or "download".
     * @param  {number} size   The request/response size. Undefined for latency measures.
     * @return {string}        The address of the endpoint.
     */
    endpoint: function(module, size) {
        return './network.php';
    }
});

Root nodejs file location is unclear [v2.0.0]

This may not be an issue, but after compiling v2.0.0 by following the instructions in the README, I am unable to locate a js file to run with nodejs.

How do you launch the node SpeedTest application?

I am new to nodejs so I may be missing something.

Upload does not work on HTTPS

Just as the title says. Also, the "Abort"-button does not work in this case.

I will gladly provide any logs if required.

add example index.html

I think a simple html file should be provided that calls the library and shows the results. That will make this tool a complete solution (which most people probably need)

In my case I just want a tool with which users can check access speed to a web server without involving the sysadmin each time they beleive there's a congestion :)

Feature request: parallel connections to one or multiple endpoints

So, I have a very specific feature request for this awesome library...

I work for a non-profit that delivers a completely free videoconferencing service to children with a long term illness. This allows the children to follow class from home or from the hospital.

We have a lot of issues with packet loss in schools, because they don't apply proper Quality of Service for our videoconferencing service. The QoS is (or should be at least) configured based on destination IP.

We want the network administrators in the schools to be able to test their QoS configuration by simulating high-bandwith connections using a browser speedtest that uses network.js. One connection would go to our videoconferencing server and a large number of other connections (100 simultaneous approximately) would go to other endpoints. This large number of connections is needed because the purpose is to try and catch a badly configured QoS. If the single connection towards the videoconferencing server drops under 2 Mbit, we would know that QoS was not configured properly.

The browser has a limit of concurrent connections to one domain name (in Chrome/Chromium: 6), so the connections would have to go to multiple endpoints.

A example configuration would be the following:

{
    download: {
        // Multiple endpoints can be defined
        endpoints: [ 'http://speedtest1.example.com/network.php', 'http://speedtest2.example.com/network.php' ],
        // Connections PER endpoint, so this would make for 8 concurrent connections
        connections: 4
        }
    }
}

Things such as delay and data size would still be applicable to the entire aggregation of the connections. So in effect, nothing would change except for using multiple connections underneath.

I'd love to take a crack at submitting a pull request, but my god, my JavaScript skills are non-existent. I have no insight as to whether this feature request would require a major overhaul or not. I just know it would be very beneficial to us, to if it doesn't require too much effort, I would love for this feature to get implemented.

I hope I've explained my reasoning for this pull request well enough. Let me know if you have any questions.

And thanks very much for this library already, it's really great!

Provide a warning or property to handle 150 request resource limit of Performance API

This improves debugging in relation to my issue where the Performance API exceeded 150 entries and produced errors.

If there are 150 performance entries and the Network JS latency request is not one of them, the script will fail. This could be handled gracefully by providing the user a warning and/or by adding a flag to Network JS to flush performance entries prior to executing the latency test.

PR opened

note: I realize 150 requests is way too many. If anyone wonders what the use case is, it's an angular app in the development environment, and without concatenation 400 requests is not uncommon.

Can't upload large data chunks with Chrome

This is an error I get when using Firefox to test the upload speed. Am I hitting some internal browser limit there?

The last request made was for the size of 512M.

On Chrome and Firefox, the end event is never fired for the upload.

Same speeds across the board

I have tested over DSL and 4G, where speedtest.net reports 2.6 and 6.8Mbps respectively, against my server at http://mm.mg/st/

Over both connections, speed is reported at an average of just below 1Mbps (eg. 0.948Mbps).

Can you please take a look?

entry is null in getTimingEntry callback

Using the basic setup instructions, in my current app I'm getting:

Uncaught TypeError: Cannot read property 'secureConnectionStart' of null

This is odd in that it works perfectly in another app we have, using the exact same backend endpoint to run the latency test against.

Thoughts?

1-2 MBps speed reading while everywhere else 11MBps+?

I'm not sure why that huge gap but it doesn't show correct speed test any reasons for that? I also hosted it myself on aws just to make sure same thing It max out to about ~2MBps. I've also tested different browsers. I'm a little bit surprised of the results how come it's so wrong?

Most of the app does not seem to work...

Running Chrome 39, cannot get the resource timing to return non-zeros.

Using your example invocation code with console.log() calls, we also see errors triggered about making one request at a time etc.

When using in Safari it drops back to the Date method, and then doesn't run the speed tests...

Is this something we should be trying to use yet? Considering debugging and trying to fix issues, but don't know if we are going to be wasting time if you're aware of issues and working on them already?

Console output (Chrome 39):

start 2097152
To ensure accurate measures, you can only make one request at a time.
A request must have been created before it can be sent.
start 10485760
To ensure accurate measures, you can only make one request at a time.
A request must have been created before it can be sent.
At least one latency returned a zero value, this can be due to the configuration of your web server which is probably using persistant connections. Check the documentation to solve this problem.
end 0 [0, 0, 0, 0, 0]

Console output (Safari 8)

start 2097152
To ensure accurate measures, you can only make one request at a time.
A request must have been created before it can be sent.
start 10485760
To ensure accurate measures, you can only make one request at a time.
A request must have been created before it can be sent.
end 11.31342239677906 [10.200232034549117, 22.778420010581613, 9.469825075939298, 7.207710994407535, 6.91092386841774]

Download and Upload tests bad works on local server (localhost). Speed no limit.

Download and Upload tests bad works on local server (localhost). Turns out endless test with large numbers (newer stop?).

[Download] The minimum delay of 8.000 seconds has not been reached
[Download] Restarting measures with 163840.000 MB of data...
etc...

Tested in Firefox and Chromium latest version.
Server Apache 2.4 on Windows.

Ping from js

This is very very cool project :)
But I don't know how ping some server (i need ping some gameservers). Any help?

Use random data to reduce chance of compression impacting results

Currently this package is generating data using a very small, fixed set of data. If there is any compression being done (e.g. if there is a web server in front of this that does gzip compression) , the content is going to compress incredibly well. Which is going to work against doing accurate characterization of the bandwidth or latency.

To combat this and make the bandwidth estimate more robust, the returned data should contain random data.

Consider something using something like this:

Let me know if this is of interest and I could pull together a PR.

Start average from top to bottom

right now it starts at lowest average and goes to top average that means you need to test it longer to really get the correct average speed, If we switch it to the opposite you get a quicker idea of the real speed.

A question for the version 1.0.0

Hi @nesk
I would like to add network.js in cdnjs, and need to make the confirmation of all stable versions.
For the user experience, should we host version 1.0.0?

Thanks for your great work! 😀

Uncaught TypeError: Cannot read property 'on' of undefined in main.js:111

  1. Copy project on your server http://myserver.com/speedtest
  2. Edit /example/index.html and change line 78 to <script src="./../dist/speedtest.js"></script>
  3. Browse http://myserver.com/speedtest/example
  4. See error message in console Uncaught TypeError: Cannot read property 'on' of undefined in main.js:111

Request "Post" not canceled.

Hi,

I currently use your project for hosting my own network speed test instance. I came upon an issue with the upload function :

Using your own test instance at http://code.jpardanaud.com/speedtest/, each POST request eventually ends in a "canceled" status in Google Chrome network inspector.

Using my own test instance, the last POST request ends in a "200 - OK" status but the test seems to be locked for half of total duration.

Does it ring a bell? :)

Otherwise, there is a small code block that seems weird to me: client/bandwith.js (line 79)

    // Initiate and send a new request.
    this._newRequest(type, {
        size: dataSize.download
    })._sendRequest(blob);

Why "dataSize.download" instead of "dataSize.upload" since it's an upload request, sending a blob ?

Thanks a lot for this great software!

Regards,

Questions

Since you state on your demopage that your server has a low bandwidth (and my home connection is faster than that [VDSL 50/10] ), I deployed the example page on my VPS which has 100M symmetrical.

Some questions arose:

  • Is there a logic to dynamically decide the size of the upload and download pieces? If not, this might be a major feature request ;-) (I can open another issue for that)
  • The latency test returns nothing on my server in Chrome 45 (nginx+hhvm, no errors in the logs)

Very nice test, basically what I wanted for a self-hosted speedtest. Keep up the good work!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.