Browse Source

Add hit counter & README documentation

master
NGnius (Graham) 5 years ago
parent
commit
d9ecbc416e
4 changed files with 70 additions and 4 deletions
  1. +35
    -1
      README.md
  2. +19
    -3
      rxsmserver/__init__.py
  3. +9
    -0
      rxsmserver/make-release.py
  4. +7
    -0
      rxsmserver/server-tester.py

+ 35
- 1
README.md View File

@@ -1,3 +1,37 @@
# rxsm-server

RXSM update server
RXSM update server for storing and retrieving updates.
This is a single file application; all server functionality is stored in `rxsmserver/__init__.py`.

## API
`/db`
> **GET** request to download the sqlite database.
> The database stores version information and a daily hit counter (requests to `/update` per day).
> This is publicly accessibly by design, for transparency.

`/update`
> **POST** request to check for updates.
>
> The body of the request must be a JSON like
>
> `{'version':'[version number]', 'platform':'[platform]'}`
>
> The response will be a JSON like
>
> `{'status':200, 'reason':'Ok', 'url':'[url to download latest version]', 'out-of-date':true/false}`
>
> The status and reason may be different, and url and out-of-date may not be included if the request is invalid or an error occurs.

`/release`
> **POST** request to create/update a new release.
> This is password-protected to prevent users from adding malicious code into releases.
>
> The body of the request must be a JSON like
>
> `{'token':'[server password]', 'version':'[version number]', 'platform':'[platform]', 'url':'[url to download version]'}`
>
> The response will be a JSON like
>
> `{'status':200, 'reason':'Version created successfully'}`
>
> The status and reason may be different, especially if the request is invalid or an error occurs.

+ 19
- 3
rxsmserver/__init__.py View File

@@ -5,6 +5,7 @@ from hashlib import sha512
from os import getcwd
from threading import get_ident
from time import time
from datetime import datetime

database_path = 'rxsm-update.db'

@@ -58,16 +59,26 @@ def download_database():
@app.route('/check-for-update', methods=['POST'])
def check_for_update():
start = time()
db_connection = get_or_create_connection()
cursor = db_connection.cursor()
collect_anonymous_stats = str(request.headers.get('DNT')).strip() != '1'
# TODO: add hit counter
# hit counter
if collect_anonymous_stats:
today = datetime.today().date().isoformat()
cursor.execute('SELECT count FROM hits WHERE date=?', (today,))
result = cursor.fetchone()
if result is not None:
cursor.execute('UPDATE hits SET count=count+1 WHERE date=?', (today,))
else:
cursor.execute('INSERT INTO hits (date, count) VALUES (?,?)', (today, 1))
db_connection.commit()
# update lookup
try:
req_json = request.get_json(force=True)
current_version = req_json['version']
platform = req_json['platform']
except:
return jsonify({'status':400, 'reason':'Invalid request; missing parameter or invalid JSON'}), 400
db_connection = get_or_create_connection()
cursor = db_connection.cursor()
cursor.execute('SELECT version, url FROM releases WHERE platform=? ORDER BY created_date DESC', (platform,))
result = cursor.fetchone()
if result is None:
@@ -88,6 +99,11 @@ cursor.execute(\
platform TEXT NOT NULL,
created_date INTEGER NOT NULL
)''' )
cursor.execute(\
'''CREATE TABLE IF NOT EXISTS hits (
date TEXT UNIQUE NOT NULL,
count INTEGER NOT NULL
)''' )
conn.commit()

if __name__ == '__main__':


+ 9
- 0
rxsmserver/make-release.py View File

@@ -0,0 +1,9 @@
import requests
raw_token = input('token password: ')
url = input('update server: ')+'/release'
version = input('version: ')
platform = input('platform: ')
download_url = input('download link: ')
release_resp = requests.post(url, json={'token':raw_token, 'version':version, 'platform':platform, 'url':download_url})
print(release_resp.status_code)
print(release_resp.json())

+ 7
- 0
rxsmserver/server-tester.py View File

@@ -32,3 +32,10 @@ print(update_resp.json())
assert update_resp.status_code == 404
assert update_resp.json()['url'] == ''
print('Update Ok')

print('Testing /update DNT')
update_resp = requests.post('http://localhost:9080/update', json={'version':'v0.42.0a', 'platform':'fake-i386'}, headers={"DNT": "1"})
print(update_resp.json())
assert update_resp.status_code == 200
assert update_resp.json()['url'] == 'https://google.com'
print('Update Ok')