First Version of nodeJS Port

This commit is contained in:
Tom Sacher 2018-04-22 12:14:12 +02:00
parent e0dfcae1fc
commit 558ae82a75
30 changed files with 738 additions and 825 deletions

View file

@ -11,7 +11,7 @@ indent_size = 4
charset = utf-8
[*.js]
indent_size = 2
indent_size = 4
indent_style = space
[*.md]

3
.gitignore vendored
View file

@ -1,2 +1 @@
ugly.bat
wishlist.txt
node_modules

12
.idea/NodeSpeedtest.iml Normal file
View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
<excludeFolder url="file://$MODULE_DIR$/temp" />
<excludeFolder url="file://$MODULE_DIR$/tmp" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptLibraryMappings">
<includedPredefinedLibrary name="Node.js Core" />
</component>
</project>

6
.idea/misc.xml Normal file
View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptSettings">
<option name="languageLevel" value="ES6" />
</component>
</project>

8
.idea/modules.xml Normal file
View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/NodeSpeedtest.iml" filepath="$PROJECT_DIR$/.idea/NodeSpeedtest.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml Normal file
View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

313
.idea/workspace.xml Normal file
View file

@ -0,0 +1,313 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ChangeListManager">
<list default="true" id="a475261a-d91d-4c10-937c-3cde04698029" name="Default" comment="">
<change afterPath="$PROJECT_DIR$/.idea/vcs.xml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/SpeedTest.js" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.editorconfig" beforeDir="false" afterPath="$PROJECT_DIR$/.editorconfig" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.gitignore" beforeDir="false" afterPath="$PROJECT_DIR$/.gitignore" afterDir="false" />
<change beforePath="$PROJECT_DIR$/README.md" beforeDir="false" afterPath="$PROJECT_DIR$/README.md" afterDir="false" />
<change beforePath="$PROJECT_DIR$/empty.php" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/example-basic.html" beforeDir="false" afterPath="$PROJECT_DIR$/src/public/example-basic.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example-chart.html" beforeDir="false" afterPath="$PROJECT_DIR$/src/public/example-chart.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example-customSettings.html" beforeDir="false" afterPath="$PROJECT_DIR$/src/public/example-customSettings.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example-customSettings2.html" beforeDir="false" afterPath="$PROJECT_DIR$/src/public/example-customSettings2.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example-gauges.html" beforeDir="false" afterPath="$PROJECT_DIR$/src/public/example-gauges.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example-pretty.html" beforeDir="false" afterPath="$PROJECT_DIR$/src/public/example-pretty.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example-progressBar.html" beforeDir="false" afterPath="$PROJECT_DIR$/src/public/example-progressBar.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example-telemetryEnabled.html" beforeDir="false" afterPath="$PROJECT_DIR$/src/public/example-telemetryEnabled.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/garbage.php" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/getIP.php" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/speedtest_worker.js" beforeDir="false" afterPath="$PROJECT_DIR$/src/public/speedtest_worker.js" afterDir="false" />
<change beforePath="$PROJECT_DIR$/speedtest_worker.min.js" beforeDir="false" afterPath="$PROJECT_DIR$/src/public/speedtest_worker.min.js" afterDir="false" />
<change beforePath="$PROJECT_DIR$/telemetry.php" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/telemetry_mysql.sql" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/telemetry_postgresql.sql" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/telemetry_settings.php" beforeDir="false" />
</list>
<ignored path="$PROJECT_DIR$/.tmp/" />
<ignored path="$PROJECT_DIR$/temp/" />
<ignored path="$PROJECT_DIR$/tmp/" />
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
<option name="TRACKING_ENABLED" value="true" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="FileEditorManager">
<leaf>
<file leaf-file-name="SpeedTest.js" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/SpeedTest.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="525">
<caret line="35" column="43" lean-forward="true" selection-start-line="35" selection-start-column="43" selection-end-line="35" selection-end-column="43" />
</state>
</provider>
</entry>
</file>
<file leaf-file-name=".gitignore" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/.gitignore">
<provider selected="true" editor-type-id="text-editor">
<state>
<caret column="12" selection-start-column="12" selection-end-column="12" />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="README.md" pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/README.md">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="30">
<caret line="2" column="15" selection-start-line="2" selection-start-column="15" selection-end-line="2" selection-end-column="15" />
</state>
</provider>
</entry>
</file>
<file leaf-file-name=".editorconfig" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/.editorconfig">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="195">
<caret line="13" column="15" selection-start-line="13" selection-start-column="15" selection-end-line="13" selection-end-column="15" />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="example-basic.html" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/public/example-basic.html">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="230">
<caret line="23" column="44" selection-start-line="23" selection-start-column="44" selection-end-line="23" selection-end-column="44" />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="speedtest_worker.js" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/public/speedtest_worker.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-7">
<caret line="37" column="80" selection-start-line="37" selection-start-column="80" selection-end-line="37" selection-end-column="80" />
<folding>
<element signature="n#!!doc" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file leaf-file-name="example-pretty.html" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/public/example-pretty.html">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="98">
<caret line="123" column="38" selection-start-line="123" selection-start-column="38" selection-end-line="123" selection-end-column="38" />
</state>
</provider>
</entry>
</file>
</leaf>
</component>
<component name="FileTemplateManagerImpl">
<option name="RECENT_TEMPLATES">
<list>
<option value="JavaScript File" />
</list>
</option>
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
</component>
<component name="IdeDocumentHistory">
<option name="CHANGED_PATHS">
<list>
<option value="$PROJECT_DIR$/src/public/speedtest_worker.js" />
<option value="$PROJECT_DIR$/src/public/example-basic.html" />
<option value="$PROJECT_DIR$/src/public/example-pretty.html" />
<option value="$PROJECT_DIR$/.editorconfig" />
<option value="$PROJECT_DIR$/src/SpeedTest.js" />
<option value="$PROJECT_DIR$/.gitignore" />
<option value="$PROJECT_DIR$/README.md" />
</list>
</option>
</component>
<component name="JsBuildToolGruntFileManager" detection-done="true" sorting="DEFINITION_ORDER" />
<component name="JsBuildToolPackageJson" detection-done="true" sorting="DEFINITION_ORDER" />
<component name="JsGulpfileManager">
<detection-done>true</detection-done>
<sorting>DEFINITION_ORDER</sorting>
</component>
<component name="NodeModulesDirectoryManager">
<handled-path value="$PROJECT_DIR$/node_modules" />
</component>
<component name="NodePackageJsonFileManager">
<packageJsonPaths>
<path value="$PROJECT_DIR$/package.json" />
</packageJsonPaths>
</component>
<component name="ProjectFrameBounds">
<option name="x" value="1070" />
<option name="y" value="22" />
<option name="width" value="1490" />
<option name="height" value="1021" />
</component>
<component name="ProjectView">
<navigator proportions="" version="1">
<foldersAlwaysOnTop value="true" />
</navigator>
<panes>
<pane id="ProjectPane">
<subPane>
<expand>
<path>
<item name="NodeSpeedtest" type="b2602c69:ProjectViewProjectNode" />
<item name="NodeSpeedtest" type="462c0819:PsiDirectoryNode" />
</path>
</expand>
<select />
</subPane>
</pane>
<pane id="Scope" />
</panes>
</component>
<component name="PropertiesComponent">
<property name="WebServerToolWindowFactoryState" value="false" />
<property name="javascript.nodejs.core.library.configured.version" value="8.10.0" />
<property name="node.js.detected.package.prettier" value="true" />
<property name="node.js.path.for.package.prettier" value="project" />
<property name="node.js.selected.package.prettier" value="" />
<property name="nodejs_interpreter_path" value="node" />
<property name="nodejs_interpreter_path.stuck_in_default_project" value="undefined stuck path" />
<property name="nodejs_npm_path_reset_for_default_project" value="true" />
<property name="nodejs_package_manager_path" value="yarn" />
<property name="settings.editor.selected.configurable" value="preferences.sourceCode.JavaScript" />
</component>
<component name="RecentsManager">
<key name="MoveFile.RECENT_KEYS">
<recent name="$PROJECT_DIR$/src/public" />
</key>
</component>
<component name="RunDashboard">
<option name="ruleStates">
<list>
<RuleState>
<option name="name" value="ConfigurationTypeDashboardGroupingRule" />
</RuleState>
<RuleState>
<option name="name" value="StatusDashboardGroupingRule" />
</RuleState>
</list>
</option>
</component>
<component name="SvnConfiguration">
<configuration />
</component>
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="a475261a-d91d-4c10-937c-3cde04698029" name="Default" comment="" />
<created>1524388928332</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1524388928332</updated>
<workItem from="1524388930798" duration="2180000" />
</task>
<servers />
</component>
<component name="TimeTrackingManager">
<option name="totallyTimeSpent" value="2180000" />
</component>
<component name="ToolWindowManager">
<frame x="1070" y="22" width="1490" height="1021" extended-state="0" />
<editor active="true" />
<layout>
<window_info active="true" content_ui="combo" id="Project" order="0" visible="true" weight="0.20217836" />
<window_info anchor="bottom" id="TODO" order="6" />
<window_info anchor="bottom" id="Docker" show_stripe_button="false" />
<window_info anchor="bottom" id="Event Log" side_tool="true" />
<window_info anchor="bottom" id="Find" order="1" weight="0.32900432" />
<window_info anchor="bottom" id="Run" order="2" />
<window_info anchor="bottom" id="Version Control" />
<window_info id="Structure" order="1" side_tool="true" weight="0.25" />
<window_info anchor="bottom" id="Terminal" weight="0.32792208" />
<window_info anchor="bottom" id="Debug" order="3" weight="0.4" />
<window_info id="Favorites" side_tool="true" />
<window_info anchor="right" id="Commander" order="0" weight="0.4" />
<window_info anchor="right" content_ui="combo" id="Hierarchy" order="2" weight="0.25" />
<window_info anchor="bottom" id="Inspection" order="5" weight="0.4" />
<window_info anchor="right" id="Ant Build" order="1" weight="0.25" />
<window_info anchor="bottom" id="Message" order="0" />
<window_info anchor="bottom" id="Cvs" order="4" weight="0.25" />
</layout>
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="1" />
</component>
<component name="VcsContentAnnotationSettings">
<option name="myLimit" value="2678400000" />
</component>
<component name="editorHistoryManager">
<entry file="file://$PROJECT_DIR$/src/public/example-basic.html">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="230">
<caret line="23" column="44" selection-start-line="23" selection-start-column="44" selection-end-line="23" selection-end-column="44" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/public/example-pretty.html">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="98">
<caret line="123" column="38" selection-start-line="123" selection-start-column="38" selection-end-line="123" selection-end-column="38" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/empty.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="90">
<caret line="6" column="2" selection-start-line="6" selection-start-column="2" selection-end-line="6" selection-end-column="2" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/public/speedtest_worker.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-7">
<caret line="37" column="80" selection-start-line="37" selection-start-column="80" selection-end-line="37" selection-end-column="80" />
<folding>
<element signature="n#!!doc" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/.editorconfig">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="195">
<caret line="13" column="15" selection-start-line="13" selection-start-column="15" selection-end-line="13" selection-end-column="15" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/garbage.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="135">
<caret line="9" column="14" selection-start-line="8" selection-end-line="15" selection-end-column="27" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/SpeedTest.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="525">
<caret line="35" column="43" lean-forward="true" selection-start-line="35" selection-start-column="43" selection-end-line="35" selection-end-column="43" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/.gitignore">
<provider selected="true" editor-type-id="text-editor">
<state>
<caret column="12" selection-start-column="12" selection-end-column="12" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/README.md">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="30">
<caret line="2" column="15" selection-start-line="2" selection-start-column="15" selection-end-line="2" selection-end-column="15" />
</state>
</provider>
</entry>
</component>
</project>

View file

@ -1,45 +1,7 @@
# HTML5 Speedtest
No Flash, No Java, No Websocket, No Bullshit.
This is a s nodeJS Port from [adolfintel's HTML5 Speedtest](https://github.com/adolfintel/speedtest)
This is a very lightweight Speedtest implemented in Javascript, using XMLHttpRequest and Web Workers.
## Try it
[Take a Speedtest](http://speedtest.fdossena.com)
## Compatibility
Only modern browsers are supported (IE11, latest Edge, latest Chrome, latest Firefox, latest Safari)
## Features
* Download
* Upload
* Ping
* Jitter
* IP Address
* Telemetry (optional)
## Requirements
- A reasonably fast web server with PHP (see doc.md for details and use without PHP)
- Your server must accept large POST requests (up to 20 Megabytes), otherwise the upload test will fail
- It's also better if your server does not use compression, but it's not mandatory
## Quick installation videos
* [Debian 9.0 with Apache](https://fdossena.com/?p=speedtest/quickstart_deb.frag)
* [Windows Server 2016 with IIS](https://fdossena.com/?p=speedtest/quickstart_win.frag)
* [Ubuntu (External)](https://freedif.org/how-to-install-selfhosted-speedtest)
Also, here's an [example config on Ubuntu 16 LTS](https://github.com/adolfintel/speedtest/issues/50)
## How to use in your site
See the examples or doc.md
## Docker
Please see the ```docker``` branch
## Donate
If you want to support this project, you can
[Send a donation via PayPal](https://www.paypal.me/sineisochronic).
Send ETH at this address: 0x8A5273d4e2618c4cff2C62d8EB731701FceEd8E3
## License
Copyright (C) 2016-2018 Federico Dossena

424
doc.md
View file

@ -1,424 +0,0 @@
# HTML5 Speedtest
> by Federico Dossena
> Version 4.5.4, March 21, 2018
> [https://github.com/adolfintel/speedtest/](https://github.com/adolfintel/speedtest/)
## Introduction
In this document, we will introduce an XHR based HTML5 Speedtest and see how to use it.
This test measures download speed, upload speed, ping and jitter.
First of all, the requirements to run this test:
* The browser have to support XHR Level 2 and Web Workers and Javascript must be enabled.
* Internet Explorer 11
* Microsoft Edge 12+
* Mozilla Firefox 12+
* Google Chrome / Chromium 31+
* Apple Safari 7.1+
* Opera 18+
* Client side, the test can use up to 500 megabytes of RAM
* Server side, you'll need a fast connection (at least 100 Mbps recommended), and the web server must accept large POST requests (up to 20 megabytes).
Apache2 and PHP are recommended, but not mandatory.
If this looks good, let's proceed and see how to use the test.
## Quick installation videos
* [Debian 9.0 with Apache](https://fdossena.com/?p=speedtest/quickstart_deb.frag)
* [Windows Server 2016 with IIS](https://fdossena.com/?p=speedtest/quickstart_win.frag)
## Installation
To install the test on your server, upload the following files:
* `speedtest_worker.min.js`
* `garbage.php`
* `getIP.php`
* `empty.php`
* one of the examples
Later we'll see how to use the test without PHP, and how to configure the telemetry if you want to use it.
__Important:__ keep all the files together; all paths are relative to the js file
## Basic usage
You can start using this speedtest on your site without any special knowledge.
Start by copying one of the included examples. Here's a description for each of them:
* `example-basic.html`: This example shows the most basic configuration possible. Everything runs with the default settings, in a very simple page where the output is shown
* `example-pretty.html`: This is a more sophisticated example, with a nicer layout and a start/stop button. __This is the best starting point for most users__
* `example-progressBar.html`: A modified version of `example-pretty.html` with a progress indicator
* `example-customSettings.html`: A modified version of `example-pretty.html` showing how the test can be started with custom parameters
* `example-customSettings2.html`: A modified version of `example-pretty.html` showing how to make a custom test with only download and upload
* `example-gauges.html`: The most sophisticated example, with the same functions as `example-pretty.html` but also gauges and progress indicators for each test. This is the nicest example included, and also a good starting point, but drawing the gauges may slow down the test on slow devices like a Raspberry Pi
* `example-chart.html`: The old example5.html, showing how to use the test with the Chart.js library
* `example-telemetry.html`: A modified version of `example-pretty.html` with basic telemetry turned on. See the section on Telemetry for details
### Customizing your example
The included examples are good starting places if you want to have a simple speedtest on your site.
Once you've tested everything and you're sure that everything works, edit it and add some custom stuff like your logo or new colors.
If you want to change the test parameters, for instance to make the download test shorter, you can do so in every example:
Look for the line that contains `postMessage('start `
This is where custom parameters can be passed to the test as a JSON string. You can write the string manually or use ``JSON.stringify`` to do that for you.
Here's an example:
```js
w.postMessage('start {"time_dl":"10"}');
```
This starts the test with default settings, but sets the download test to last only 10 seconds.
Here's a cleaner version using ``JSON.stringify``:
```js
var params={
time_dl:10
}
w.postMessage('start '+JSON.stringify(params))
```
Notice that there is a space after the word `start`, don't forget that!
For a list of all test settings, look below, under Test parameters and Advanced test parameters. __Do not change anything if you don't know what you're doing.__
## Advanced usage
If you don't want to start from one of the examples, here's how to use the worker. Examples are still good for reference, so keep them handy.
To run the test, you need to do 3 things:
* Create the worker
* Write some code that handles the data coming from the worker
* Start the test
### Creating the worker
```js
var w = new Worker("speedtest_worker.min.js")
```
__Important:__ use the minified version, it's smaller!
### Response handler
First, we set up a timer that fetches the status of the worker continuously:
```js
var timer = setInterval(function () {
w.postMessage('status')
}, 100)
```
Then we write a response handler that receives the status and updates the page. Later
we'll see the details of the format of the response.
```js
w.onmessage = function (event) {
var data = event.data.split(';')
var testState = data[0]
var dlStatus = data[1]
var ulStatus = data[2]
var pingStatus = data[3]
var jitterStatus = data[5]
var clientIp = data[4]
var dlProgress = data[6]
var ulProgress = data[7]
var pingProgress = data[8]
if (testState >= 4) {
clearInterval(timer) // test is finished or aborted
}
// .. update your page here ..
}
```
#### Response format
The response from the worker is composed of values separated by `;` (semicolon) in this
format:
`testState;dlStatus;ulStatus;pingStatus;clientIp;jitterStatus;dlProgress;ulProgress;pingProgress`
* __testState__ is an integer between -1 and 5
* `-1` = Test not started yet
* `0` = Test starting
* `1` = Download test in progress
* `2` = Ping + Jitter test in progress
* `3` = Upload test in progress
* `4` = Test finished
* `5` = Test aborted
* __dlStatus__ is either
* Empty string (not started or aborted)
* Download speed in Megabit/s as a number with 2 decimals
* The string "Fail" (test failed)
* __ulStatus__ is either
* Empty string (not started or aborted)
* Upload speed in Megabit/s as a number with 2 decimals
* The string "Fail" (test failed)
* __pingStatus__ is either
* Empty string (not started or aborted)
* Estimated ping in milliseconds as a number with 2 decimals
* The string "Fail" (test failed)
* __clientIp__ is either
* Empty string (not fetched yet or failed)
* The client's IP address as a string
* __jitterStatus__ is either
* Empty string (not started or aborted)
* Estimated jitter in milliseconds as a number with 2 decimals (lower = stable connection)
* The string "Fail" (test failed)
* __dlProgress__: the progress of the download test as a number between 0 and 1
* __ulProgress__: the progress of the upload test as a number between 0 and 1
* __pingProgress__: the progress of the ping+jitter test as a number between 0 and 1
Note: clientIp appears before jitterStatus. This is not a mistake, it's to keep the js file compatible with older pages from before the jitter test was introduced.
### Starting the test
To start the test with the default settings, which is usually the best choice, send the start command to the worker:
```js
w.postMessage('start')
```
If you want, you can change these settings and pass them to the worker as JSON when you start it, like this:
```js
w.postMessage('start {"param1": "value1", "param2": "value2", ...}')
```
or this:
```js
var params{
param1:value1,
param2:value2,
...
}
w.postMessage('start '+JSON.stringify(params))
```
#### Test parameters
* __time_dl__: How long the download test should be in seconds. The test will continue regardless of this limit if the speed is still 0.00 when the limit is reached.
* Default: `15`
* Recommended: `>=5`
* __time_ul__: How long the upload test should be in seconds. The test will continue regardless of this limit if the speed is still 0.00 when the limit is reached.
* Default: `15`
* Recommended: `>=10`
* __count_ping__: How many pings to perform in the ping test
* Default: `35`
* Recommended: `>=20`
* __url_dl__: path to garbage.php or a large file to use for the download test.
* Default: `garbage.php`
* __Important:__ path is relative to js file
* __url_ul__: path to an empty file or empty.php to use for the upload test
* Default: `empty.php`
* __Important:__ path is relative to js file
* __url_ping__: path to an empty file or empty.php to use for the ping test
* Default: `empty.php`
* __Important:__ path is relative to js file
* __url_getIp__: path to getIP.php or replacement
* Default: `getIP.php`
* __Important:__ path is relative to js file
#### Advanced test parameters
* __test_order__: the order in which tests will be performed. Each character represents an operation:
* `I`: get IP
* `D`: download test
* `U`: upload test
* `P`: ping + jitter test
* `_`: delay 1 second
* Default test order: `IP_D_U`
* __Important:__ Tests can only be run once
* __Important:__ On Firefox, it is better to run the upload test last
* __getIp_ispInfo__: if true, the server will try to get ISP info and pass it along with the IP address. This will add `isp=true` to the request to `url_getIp`. getIP.php accomplishes this using ipinfo.io
* Default: `true`
* __getIp_ispInfo_distance__: if true, the server will try to get an estimate of the distance from the client to the speedtest server. This will add a `distance` argument to the request to `url_getIp`. `__getIp_ispInfo__` must be enabled in order for this to work. getIP.php accomplishes this using ipinfo.io
* `km`: estimate distance in kilometers
* `mi`: estimate distance in miles
* not set: do not measure distance
* Default: `km`
* __enable_quirks__: enables browser-specific optimizations. These optimizations override some of the default settings. They do not override settings that are explicitly set.
* Default: `true`
* __garbagePhp_chunkSize__: size of chunks sent by garbage.php in megabytes
* Default: `20`
* Recommended: `>=10`
* Maximum: `100`
* __xhr_dlMultistream__: how many streams should be opened for the download test
* Default: `10`
* Recommended: `>=3`
* Default override: 3 on Edge if enable_quirks is true
* Default override: 5 on Chromium-based if enable_quirks is true
* __xhr_ulMultistream__: how many streams should be opened for the upload test
* Default: `3`
* Recommended: `>=1`
* Default override: 1 on Firefox if enable_quirks is true
* __xhr_ul_blob_megabytes__: size in megabytes of the blobs sent during the upload test
* Default: `20`
* Default override: 4 on Chromium-based mobile browsers (limitation introduced around version 65). This will be forced
* Default override: IE11 and Edge currently use a different method for the upload test. This parameter is ignored
* __xhr_multistreamDelay__: how long should the multiple streams be delayed (in ms)
* Default: `300`
* Recommended: `>=100`, `<=700`
* __xhr_ignoreErrors__: how to react to errors in download/upload streams and the ping test
* `0`: Fail test on error (behaviour of previous versions of this test)
* `1`: Restart a stream/ping when it fails
* `2`: Ignore all errors
* Default: `1`
* Recommended: `1`
* __time_dlGraceTime__: How long to wait (in seconds) before actually measuring the download speed. This is a good idea because we want to wait for the TCP window to be at its maximum (or close to it)
* Default: `1.5`
* Recommended: `>=0`
* __time_ulGraceTime__: How long to wait (in seconds) before actually measuring the upload speed. This is a good idea because we want to wait for the buffers to be full (avoids the peak at the beginning of the test)
* Default: `3`
* Recommended: `>=1`
* __ping_allowPerformanceApi__: toggles use of Performance API to improve accuracy of Ping/Jitter test on browsers that support it.
* Default: `true`
* __useMebibits__: use mebibits/s instead of megabits/s for the speeds
* Default: `false`
* __overheadCompensationFactor__: compensation for HTTP and network overhead. Default value assumes typical MTUs used over the Internet. You might want to change this if you're using this in your internal network with different MTUs, or if you're using IPv6 instead of IPv4.
* Default: `1.06` probably a decent estimate for all overhead. This was measured empirically by comparing the measured speed and the speed reported by my the network adapter.
* `1048576/925000`: old default value. This is probably too high.
* `1.0513`: HTTP+TCP+IPv6+ETH, over the Internet (empirically tested, not calculated)
* `1.0369`: Alternative value for HTTP+TCP+IPv4+ETH, over the Internet (empirically tested, not calculated)
* `1.081`: Yet another alternative value for over the Internet (empirically tested, not calculated)
* `1514 / 1460`: TCP+IPv4+ETH, ignoring HTTP overhead
* `1514 / 1440`: TCP+IPv6+ETH, ignoring HTTP overhead
* `1`: ignore overheads. This measures the speed at which you actually download and upload files rather than the raw connection speed
### Aborting the test prematurely
The test can be aborted at any time by sending an abort command to the worker:
```js
w.postMessage('abort')
```
This will terminate all network activity and stop the worker.
__Important:__ do not simply kill the worker while it's running, as it may leave pending XHR requests!
### Important notice on backwards compatibility
__Do NOT link the js file from github or fdossena.com directly into your html file. __
A lot of web developers think that referring to the latest version of a library in their project is a good thing. It is not.
Things may change and I don't want to break your project, so do yourself a favor, and keep all files on your server.
You have been warned.
## Using the test without PHP
If your server does not support PHP, or you're using something newer like Node.js, you can still use this test by replacing `garbage.php`, `empty.php` and `getIP.php` with equivalents.
### Replacements
#### Replacement for `garbage.php`
A replacement for `garbage.php` must generate incompressible garbage data.
A large file (10-100 Mbytes) is a possible replacement. You can get [one here](http://downloads.fdossena.com/geth.php?r=speedtest-bigfile).
If you're using Node.js or some other server, your replacement should accept the `ckSize` parameter (via GET) which tells it how many megabytes of garbage to generate.
It is important here to turn off compression, and generate incompressible data.
A symlink to `/dev/urandom` is also ok.
#### Replacement for `empty.php`
Your replacement must simply respond with a HTTP code 200 and send nothing else. You may want to send additional headers to disable caching. The test assumes that Connection:keep-alive is sent by the server.
#### Replacement for `getIP.php`
Your replacement must simply respond with the client's IP as plaintext. Nothing fancy.
If you want, you can also accept the `isp=true` parameter and also include the ISP info.
#### JS
You need to start the test with your replacements like this:
```js
w.postMessage('start {"url_dl": "newGarbageURL", "url_ul": "newEmptyURL", "url_ping": "newEmptyURL", "url_getIp": "newIpURL"}')
```
## Telemetry
Telemetry currently requires PHP and either MySQL, PostgreSQL or SQLite.
To set up the telemetry, we need to do 4 things:
* copy `telemetry.php` and `telemetry_settings.php`
* edit `telemetry_settings.php` to add your database settings
* create the database
* enable telemetry
### Creating the database
This step is only for MySQL and PostgreSQL. Skip this if you want to use SQLite.
Log into your database using phpMyAdmin or a similar software and import the appropriate sql file into an empty database. For MySQL databases use `telemetry_mysql.sql` and for PostgreSQL databases use `telemetry_postgesql.sql`.
If you see a table called `speedtest_users`, empty, you did it right.
### Configuring `telemetry.php`
Open telemetry_settings.php with notepad or a similar text editor.
Set your preferred database, ``$db_type="mysql";``, ``$db_type="sqlite";`` or ``$db_type="postgresql";``
If you choose to use Sqlite3, you must set the path to your database file:
```php
$Sqlite_db_file = "../telemetry.sql";
```
If you choose to use MySQL, you must also add your database credentials:
```php
$MySql_username="USERNAME"; //your database username
$MySql_password="PASSWORD"; //your database password
$MySql_hostname="DB_HOSTNAME"; //database address, usually localhost\
$MySql_databasename="DB_NAME"; //the name of the database where you loaded telemetry_mysql.sql
```
If you choose to use PostgreSQL, you must also add your database credentials:
```php
$PostgreSql_username="USERNAME"; //your database username
$PostgreSql_password="PASSWORD"; //your database password
$PostgreSql_hostname="DB_HOSTNAME"; //database address, usually localhost
$PostgreSql_databasename="DB_NAME"; //the name of the database where you loaded telemetry_postgresql.sql
```
### Enabling telemetry
Edit your test page; where you start the worker, you need to specify the `telemetry_level`.
There are 3 levels:
* `none`: telemetry is disabled (default)
* `basic`: telemetry collects IP, User Agent, Preferred language, Test results
* `full`: same as above, but also collects a log (10-150 Kb each, not recommended)
Example:
```js
w.postMessage('start {"telemetry_level":"basic"}')
```
Also, see example-telemetry.html
### Seeing the results
At the moment there is no front-end to see the telemetry data; you can connect to the database and see the collected results in the `speedtest_users` table.
## Troubleshooting
These are the most common issues reported by users, and how to fix them. If you still need help, contact me at [dosse91@paranoici.org](mailto:dosse91@paranoici.org).
#### Download test gives very low result
Are garbage.php and empty.php (or your replacements) reachable?
Press F12, select network and start the test. Do you see errors? (cancelled requests are not errors)
If a small download starts, open it in a text editor. Does it say it's missing openssl_random_pseudo_bytes()? In this case, install OpenSSL (this is usually included when you install Apache and PHP on most distros).
#### Upload test is inaccurate, and/or I see lag spikes
Check your server's maximum POST size, make sure it's at least 20Mbytes, possibly more
#### Download and/or upload results are slightly too optimistic
The test was fine tuned to run over a typical IPv4 internet connection. If you're using it under different conditions, see the ``overheadCompensationFactor`` parameter.
#### All tests are wrong, give extremely high results, browser lags/crashes, ...
You're running the test on localhost, therefore it is trying to measure the speed of your loopback interface. The test is meant to be run over an Internet connection, from a different machine.
#### Ping test shows double the actual ping
Make sure your server is sending the ```Connection:keep-alive``` header
## Known bugs and limitations
### General
* The ping/jitter test is measured by seeing how long it takes for an empty XHR to complete. It is not an acutal ICMP ping. Different browsers may also show different results, especially on very fast connections on slow devices.
### IE-Specific
* The upload test is not precise on very fast connections with high latency (will probably be fixed by Edge 17)
* On IE11, a same origin policy error is erroneously triggered under unknown conditions. Seems to be related to running the test from unusual URLs like a top level domain (for instance http://abc/speedtest). These are bugs in IE11's implementation of the same origin policy, not in the speedtest itself.
* On IE11, under unknown circumstances, on some systems the test can only be run once, after which speedtest_worker.js will not be loaded by IE until the browser is restarted. This is a rare bug in IE11.
### Firefox-Specific
* On some Linux systems with hardware acceleration turned off, the page rendering makes the browser lag, reducing the accuracy of the ping/jitter test
## Making changes
Since this is an open source project, you can modify it.
To make changes to the speedtest itself, edit `speedtest_worker.js`
To create the minified version, use UglifyJS like this:
```
uglifyjs -c speedtest_worker.js > speedtest_worker.min.js
```
Pull requests are very appreciated. If you don't use github (or git), simply contact me at [dosse91@paranoici.org](mailto:dosse91@paranoici.org).
__Important:__ please add your name to modified versions to distinguish them from the main project.
## License
This software is under the GNU LGPL license, Version 3 or newer.
To put it short: you are free to use, study, modify, and redistribute this software and modified versions of it, for free or for money.
You can also use it in proprietary software but all changes to this software must remain under the same GNU LGPL license.
Contact me at [dosse91@paranoici.org](mailto:dosse91@paranoici.org) for other licensing models.

View file

@ -1,7 +0,0 @@
<?php
header( "HTTP/1.1 200 OK" );
header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
header("Connection: keep-alive");
?>

View file

@ -1,27 +0,0 @@
<?php
// Disable Compression
@ini_set('zlib.output_compression', 'Off');
@ini_set('output_buffering', 'Off');
@ini_set('output_handler', '');
// Headers
header('HTTP/1.1 200 OK');
// Download follows...
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=random.dat');
header('Content-Transfer-Encoding: binary');
// Never cache me
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
// Generate data
$data=openssl_random_pseudo_bytes(1048576);
// Deliver chunks of 1048576 bytes
$chunks=isset($_GET['ckSize']) ? intval($_GET['ckSize']) : 4;
if(empty($chunks)){$chunks = 4;}
if($chunks>100){$chunks = 100;}
for($i=0;$i<$chunks;$i++){
echo $data;
flush();
}
?>

View file

@ -1,68 +0,0 @@
<?php
$ip="";
header('Content-Type: text/plain; charset=utf-8');
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
$ip=$_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['X-Real-IP'])) {
$ip=$_SERVER['X-Real-IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ip=$_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
$ip=$_SERVER['REMOTE_ADDR'];
}
$ip=preg_replace("/^::ffff:/", "", $ip);
/**
* Optimized algorithm from http://www.codexworld.com
*
* @param float $latitudeFrom
* @param float $longitudeFrom
* @param float $latitudeTo
* @param float $longitudeTo
*
* @return float [km]
*/
function distance($latitudeFrom, $longitudeFrom, $latitudeTo, $longitudeTo){
$rad = M_PI / 180;
$theta = $longitudeFrom - $longitudeTo;
$dist = sin($latitudeFrom * $rad) * sin($latitudeTo * $rad) + cos($latitudeFrom * $rad) * cos($latitudeTo * $rad) * cos($theta * $rad);
return acos($dist) / $rad * 60 * 1.853;
}
if(isset($_GET["isp"])){
$isp="";
try{
$json = file_get_contents("https://ipinfo.io/".$ip."/json");
$details = json_decode($json,true);
if(array_key_exists("org",$details)) $isp.=$details["org"]; else $isp.="Unknown ISP";
if(array_key_exists("country",$details)) $isp.=", ".$details["country"];
$clientLoc=NULL; $serverLoc=NULL;
if(array_key_exists("loc",$details)) $clientLoc=$details["loc"];
if(isset($_GET["distance"])){
if($clientLoc){
$json = file_get_contents("https://ipinfo.io/json");
$details = json_decode($json,true);
if(array_key_exists("loc",$details)) $serverLoc=$details["loc"];
if($serverLoc){
try{
$clientLoc=explode(",",$clientLoc);
$serverLoc=explode(",",$serverLoc);
$dist=distance($clientLoc[0],$clientLoc[1],$serverLoc[0],$serverLoc[1]);
if($_GET["distance"]=="mi"){
$dist/=1.609344;
$dist=round($dist,-1);
if($dist<15) $dist="<15";
$isp.=" (".$dist." mi)";
}else if($_GET["distance"]=="km"){
$dist=round($dist,-1);
if($dist<20) $dist="<20";
$isp.=" (".$dist." km)";
}
}catch(Exception $e){}
}
}
}
}catch(Exception $ex){
$isp="Unknown ISP";
}
echo $ip." - ".$isp;
} else echo $ip;
?>

13
package.json Normal file
View file

@ -0,0 +1,13 @@
{
"name": "NodeSpeedtest",
"version": "1.0.0",
"description": "HTML5 Speedtest with NodeJS Backend",
"main": "src/Speedtest.js",
"repository": "https://github.com/dunklesToast/NodeSpeedtest",
"license": "MIT",
"private": false,
"dependencies": {
"express": "^4.16.3",
"random-bytes": "^1.0.0"
}
}

53
src/SpeedTest.js Normal file
View file

@ -0,0 +1,53 @@
const express = require('express');
const Server = express();
const randomBytes = require('random-bytes');
const path = require('path');
let cache = {
size: 0,
random: null
};
Server.get('/empty', function (req, res) {
res.sendStatus(200);
});
Server.post('/empty', function (req, res) {
res.set("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0");
res.set("Cache-Control", "post-check=0, pre-check=0");
res.set("Pragma", "no-cache");
res.sendStatus(200);
});
Server.get('/garbage', function (req, res) {
res.set('Content-Description', 'File Transfer');
res.set('Content-Type', 'application/octet-stream');
res.set('Content-Disposition', 'attachment; filename=random.dat');
res.set('Content-Transfer-Encoding', 'binary');
res.set('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0');
res.set('Cache-Control', 'post-check=0, pre-check=0', false);
res.set('Pragma', 'no-cache');
const requestedSize = (req.query.ckSize || 100);
if (cache.size === requestedSize) {
res.end(cache.random);
} else {
const size = 1048576 * (req.query.ckSize || 100);
randomBytes(size, (error, bytes) => {
if (error) res.sendStatus(500);
else {
cache.random = bytes;
cache.size = (req.query.ckSize || 100);
res.end(bytes);
}
})
}
});
Server.get('/getIP', function (req, res) {
res.send(req.headers['x-forwarded-for'] || req.connection.remoteAddress)
});
Server.use(express.static(path.join(__dirname, 'public')));
Server.listen(8888);

View file

@ -21,7 +21,7 @@
<p id="ping"></p>
<script type="text/javascript">
var w = new Worker('speedtest_worker.min.js') // create new worker
var w = new Worker('speedtest_worker.js') // create new worker
setInterval(function () { w.postMessage('status') }, 100) // ask for status every 100ms
w.onmessage = function (event) { // when status is received, split the string and put the values in the appropriate fields
var data = event.data.split(';') // string format: status;download;upload;ping (speeds are in mbit/s) (status: 0=not started, 1=downloading, 2=uploading, 3=ping, 4=done, 5=aborted)

View file

@ -121,7 +121,7 @@ function startStop(){
initUI();
}else{
//test is not running, begin
w=new Worker('speedtest_worker.min.js');
w=new Worker('speedtest_worker.js');
w.postMessage('start'); //Add optional parameters as a JSON object to this command
I("startStopBtn").className="running";
w.onmessage=function(e){
@ -190,4 +190,4 @@ function initUI(){
<a href="https://github.com/adolfintel/speedtest">Source code</a>
<script type="text/javascript">initUI();</script>
</body>
</html>
</html>

View file

@ -28,10 +28,10 @@ var settings = {
time_ulGraceTime: 3, //time to wait in seconds before actually measuring ul speed (wait for buffers to fill)
time_dlGraceTime: 1.5, //time to wait in seconds before actually measuring dl speed (wait for TCP window to increase)
count_ping: 35, // number of pings to perform in ping test
url_dl: 'garbage.php', // path to a large file or garbage.php, used for download test. must be relative to this js file
url_ul: 'empty.php', // path to an empty file, used for upload test. must be relative to this js file
url_ping: 'empty.php', // path to an empty file, used for ping test. must be relative to this js file
url_getIp: 'getIP.php', // path to getIP.php relative to this js file, or a similar thing that outputs the client's ip
url_dl: 'garbage', // path to a large file or garbage.php, used for download test. must be relative to this js file
url_ul: 'empty', // path to an empty file, used for upload test. must be relative to this js file
url_ping: 'empty', // path to an empty file, used for ping test. must be relative to this js file
url_getIp: 'getIP', // path to getIP.php relative to this js file, or a similar thing that outputs the client's ip
getIp_ispInfo: true, //if set to true, the server will include ISP info with the IP address
getIp_ispInfo_distance: 'km', //km or mi=estimate distance from server in km/mi; set to false to disable distance estimation. getIp_ispInfo must be enabled in order for this to work
xhr_dlMultistream: 10, // number of download streams to use (can be different if enable_quirks is active)
@ -469,4 +469,4 @@ function sendTelemetry(){
}
}
}

View file

@ -1,52 +0,0 @@
<?php
include_once('telemetry_settings.php');
$ip=($_SERVER['REMOTE_ADDR']);
$ua=($_SERVER['HTTP_USER_AGENT']);
$lang=""; if(isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) $lang=($_SERVER['HTTP_ACCEPT_LANGUAGE']);
$dl=($_POST["dl"]);
$ul=($_POST["ul"]);
$ping=($_POST["ping"]);
$jitter=($_POST["jitter"]);
$log=($_POST["log"]);
if($db_type=="mysql"){
$conn = new mysqli($MySql_hostname, $MySql_username, $MySql_password, $MySql_databasename) or die("1");
$stmt = $conn->prepare("INSERT INTO speedtest_users (ip,ua,lang,dl,ul,ping,jitter,log) VALUES (?,?,?,?,?,?,?,?)") or die("2");
$stmt->bind_param("ssssssss",$ip,$ua,$lang,$dl,$ul,$ping,$jitter,$log) or die("3");
$stmt->execute() or die("4");
$stmt->close() or die("5");
$conn->close() or die("6");
}elseif($db_type=="sqlite"){
$conn = new PDO("sqlite:$Sqlite_db_file") or die("1");
$conn->exec("
CREATE TABLE IF NOT EXISTS `speedtest_users` (
`id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`ip` text NOT NULL,
`ua` text NOT NULL,
`lang` text NOT NULL,
`dl` text,
`ul` text,
`ping` text,
`jitter` text,
`log` longtext
);
");
$stmt = $conn->prepare("INSERT INTO speedtest_users (ip,ua,lang,dl,ul,ping,jitter,log) VALUES (?,?,?,?,?,?,?,?)") or die("2");
$stmt->execute(array($ip,$ua,$lang,$dl,$ul,$ping,$jitter,$log)) or die("3");
$conn = null;
}elseif($db_type=="postgresql"){
// Prepare connection parameters for db connection
$conn_host = "host=$PostgreSql_hostname";
$conn_db = "dbname=$PostgreSql_databasename";
$conn_user = "user=$PostgreSql_username";
$conn_password = "password=$PostgreSql_password";
// Create db connection
$conn = new PDO("pgsql:$conn_host;$conn_db;$conn_user;$conn_password") or die("1");
$stmt = $conn->prepare("INSERT INTO speedtest_users (ip,ua,lang,dl,ul,ping,jitter,log) VALUES (?,?,?,?,?,?,?,?)") or die("2");
$stmt->execute(array($ip,$ua,$lang,$dl,$ul,$ping,$jitter,$log)) or die("3");
$conn = null;
}
?>

View file

@ -1,66 +0,0 @@
-- phpMyAdmin SQL Dump
-- version 4.7.0
-- https://www.phpmyadmin.net/
--
-- Host: 127.0.0.1
-- Generation Time: Aug 24, 2017 at 02:16 PM
-- Server version: 10.1.25-MariaDB
-- PHP Version: 7.1.7
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET AUTOCOMMIT = 0;
START TRANSACTION;
SET time_zone = "+00:00";
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;
--
-- Database: `speedtest_telemetry`
--
-- --------------------------------------------------------
--
-- Table structure for table `speedtest_users`
--
CREATE TABLE `speedtest_users` (
`id` int(11) NOT NULL,
`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`ip` text NOT NULL,
`ua` text NOT NULL,
`lang` text NOT NULL,
`dl` text,
`ul` text,
`ping` text,
`jitter` text,
`log` longtext
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
--
-- Indexes for dumped tables
--
--
-- Indexes for table `speedtest_users`
--
ALTER TABLE `speedtest_users`
ADD PRIMARY KEY (`id`);
--
-- AUTO_INCREMENT for dumped tables
--
--
-- AUTO_INCREMENT for table `speedtest_users`
--
ALTER TABLE `speedtest_users`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;COMMIT;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;

View file

@ -1,111 +0,0 @@
--
-- PostgreSQL database dump
--
-- Dumped from database version 9.6.3
-- Dumped by pg_dump version 9.6.5
SET statement_timeout = 0;
SET lock_timeout = 0;
SET idle_in_transaction_session_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SET check_function_bodies = false;
SET client_min_messages = warning;
SET row_security = off;
--
-- Name: plpgsql; Type: EXTENSION; Schema: -; Owner:
--
CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog;
--
-- Name: EXTENSION plpgsql; Type: COMMENT; Schema: -; Owner:
--
COMMENT ON EXTENSION plpgsql IS 'PL/pgSQL procedural language';
SET search_path = public, pg_catalog;
SET default_tablespace = '';
SET default_with_oids = false;
--
-- Name: speedtest_users; Type: TABLE; Schema: public; Owner: speedtest
--
CREATE TABLE speedtest_users (
id integer NOT NULL,
"timestamp" timestamp without time zone DEFAULT now() NOT NULL,
ip text NOT NULL,
ua text NOT NULL,
lang text NOT NULL,
dl text,
ul text,
ping text,
jitter text,
log text
);
-- Commented out the following line because it assumes the user of the speedtest server, @bplower
-- ALTER TABLE speedtest_users OWNER TO speedtest;
--
-- Name: speedtest_users_id_seq; Type: SEQUENCE; Schema: public; Owner: speedtest
--
CREATE SEQUENCE speedtest_users_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-- Commented out the following line because it assumes the user of the speedtest server, @bplower
-- ALTER TABLE speedtest_users_id_seq OWNER TO speedtest;
--
-- Name: speedtest_users_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: speedtest
--
ALTER SEQUENCE speedtest_users_id_seq OWNED BY speedtest_users.id;
--
-- Name: speedtest_users id; Type: DEFAULT; Schema: public; Owner: speedtest
--
ALTER TABLE ONLY speedtest_users ALTER COLUMN id SET DEFAULT nextval('speedtest_users_id_seq'::regclass);
--
-- Data for Name: speedtest_users; Type: TABLE DATA; Schema: public; Owner: speedtest
--
COPY speedtest_users (id, "timestamp", ip, ua, lang, dl, ul, ping, jitter, log) FROM stdin;
\.
--
-- Name: speedtest_users_id_seq; Type: SEQUENCE SET; Schema: public; Owner: speedtest
--
SELECT pg_catalog.setval('speedtest_users_id_seq', 1, true);
--
-- Name: speedtest_users speedtest_users_pkey; Type: CONSTRAINT; Schema: public; Owner: speedtest
--
ALTER TABLE ONLY speedtest_users
ADD CONSTRAINT speedtest_users_pkey PRIMARY KEY (id);
--
-- PostgreSQL database dump complete
--

View file

@ -1,20 +0,0 @@
<?php
$db_type="mysql"; //Type of db: "mysql", "sqlite" or "postgresql"
// Sqlite3 settings
$Sqlite_db_file = "../telemetry.sql";
// Mysql settings
$MySql_username="USERNAME";
$MySql_password="PASSWORD";
$MySql_hostname="DB_HOSTNAME";
$MySql_databasename="DB_NAME";
// Postgresql settings
$PostgreSql_username="USERNAME";
$PostgreSql_password="PASSWORD";
$PostgreSql_hostname="DB_HOSTNAME";
$PostgreSql_databasename="DB_NAME";
?>

310
yarn.lock Normal file
View file

@ -0,0 +1,310 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
accepts@~1.3.5:
version "1.3.5"
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.5.tgz#eb777df6011723a3b14e8a72c0805c8e86746bd2"
dependencies:
mime-types "~2.1.18"
negotiator "0.6.1"
array-flatten@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
body-parser@1.18.2:
version "1.18.2"
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.2.tgz#87678a19d84b47d859b83199bd59bce222b10454"
dependencies:
bytes "3.0.0"
content-type "~1.0.4"
debug "2.6.9"
depd "~1.1.1"
http-errors "~1.6.2"
iconv-lite "0.4.19"
on-finished "~2.3.0"
qs "6.5.1"
raw-body "2.3.2"
type-is "~1.6.15"
bytes@3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
content-disposition@0.5.2:
version "0.5.2"
resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4"
content-type@~1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
cookie-signature@1.0.6:
version "1.0.6"
resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
cookie@0.3.1:
version "0.3.1"
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb"
debug@2.6.9:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
dependencies:
ms "2.0.0"
depd@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.1.tgz#5783b4e1c459f06fa5ca27f991f3d06e7a310359"
depd@~1.1.1, depd@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
destroy@~1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
ee-first@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
encodeurl@~1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
escape-html@~1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
etag@~1.8.1:
version "1.8.1"
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
express@^4.16.3:
version "4.16.3"
resolved "https://registry.yarnpkg.com/express/-/express-4.16.3.tgz#6af8a502350db3246ecc4becf6b5a34d22f7ed53"
dependencies:
accepts "~1.3.5"
array-flatten "1.1.1"
body-parser "1.18.2"
content-disposition "0.5.2"
content-type "~1.0.4"
cookie "0.3.1"
cookie-signature "1.0.6"
debug "2.6.9"
depd "~1.1.2"
encodeurl "~1.0.2"
escape-html "~1.0.3"
etag "~1.8.1"
finalhandler "1.1.1"
fresh "0.5.2"
merge-descriptors "1.0.1"
methods "~1.1.2"
on-finished "~2.3.0"
parseurl "~1.3.2"
path-to-regexp "0.1.7"
proxy-addr "~2.0.3"
qs "6.5.1"
range-parser "~1.2.0"
safe-buffer "5.1.1"
send "0.16.2"
serve-static "1.13.2"
setprototypeof "1.1.0"
statuses "~1.4.0"
type-is "~1.6.16"
utils-merge "1.0.1"
vary "~1.1.2"
finalhandler@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.1.tgz#eebf4ed840079c83f4249038c9d703008301b105"
dependencies:
debug "2.6.9"
encodeurl "~1.0.2"
escape-html "~1.0.3"
on-finished "~2.3.0"
parseurl "~1.3.2"
statuses "~1.4.0"
unpipe "~1.0.0"
forwarded@~0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84"
fresh@0.5.2:
version "0.5.2"
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
http-errors@1.6.2:
version "1.6.2"
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.2.tgz#0a002cc85707192a7e7946ceedc11155f60ec736"
dependencies:
depd "1.1.1"
inherits "2.0.3"
setprototypeof "1.0.3"
statuses ">= 1.3.1 < 2"
http-errors@~1.6.2:
version "1.6.3"
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d"
dependencies:
depd "~1.1.2"
inherits "2.0.3"
setprototypeof "1.1.0"
statuses ">= 1.4.0 < 2"
iconv-lite@0.4.19:
version "0.4.19"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b"
inherits@2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
ipaddr.js@1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.6.0.tgz#e3fa357b773da619f26e95f049d055c72796f86b"
media-typer@0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
merge-descriptors@1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
methods@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
mime-db@~1.33.0:
version "1.33.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db"
mime-types@~2.1.18:
version "2.1.18"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8"
dependencies:
mime-db "~1.33.0"
mime@1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6"
ms@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
negotiator@0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9"
on-finished@~2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
dependencies:
ee-first "1.1.1"
parseurl@~1.3.2:
version "1.3.2"
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3"
path-to-regexp@0.1.7:
version "0.1.7"
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
proxy-addr@~2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.3.tgz#355f262505a621646b3130a728eb647e22055341"
dependencies:
forwarded "~0.1.2"
ipaddr.js "1.6.0"
qs@6.5.1:
version "6.5.1"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8"
random-bytes@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/random-bytes/-/random-bytes-1.0.0.tgz#4f68a1dc0ae58bd3fb95848c30324db75d64360b"
range-parser@~1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e"
raw-body@2.3.2:
version "2.3.2"
resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.2.tgz#bcd60c77d3eb93cde0050295c3f379389bc88f89"
dependencies:
bytes "3.0.0"
http-errors "1.6.2"
iconv-lite "0.4.19"
unpipe "1.0.0"
safe-buffer@5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853"
send@0.16.2:
version "0.16.2"
resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1"
dependencies:
debug "2.6.9"
depd "~1.1.2"
destroy "~1.0.4"
encodeurl "~1.0.2"
escape-html "~1.0.3"
etag "~1.8.1"
fresh "0.5.2"
http-errors "~1.6.2"
mime "1.4.1"
ms "2.0.0"
on-finished "~2.3.0"
range-parser "~1.2.0"
statuses "~1.4.0"
serve-static@1.13.2:
version "1.13.2"
resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.2.tgz#095e8472fd5b46237db50ce486a43f4b86c6cec1"
dependencies:
encodeurl "~1.0.2"
escape-html "~1.0.3"
parseurl "~1.3.2"
send "0.16.2"
setprototypeof@1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.3.tgz#66567e37043eeb4f04d91bd658c0cbefb55b8e04"
setprototypeof@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656"
"statuses@>= 1.3.1 < 2", "statuses@>= 1.4.0 < 2":
version "1.5.0"
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
statuses@~1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087"
type-is@~1.6.15, type-is@~1.6.16:
version "1.6.16"
resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.16.tgz#f89ce341541c672b25ee7ae3c73dee3b2be50194"
dependencies:
media-typer "0.3.0"
mime-types "~2.1.18"
unpipe@1.0.0, unpipe@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
utils-merge@1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
vary@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"