Compare commits
15 Commits
v1.0.0
...
45d197add4
Author | SHA1 | Date | |
---|---|---|---|
45d197add4
|
|||
c191f983fe
|
|||
9e83da6b1a
|
|||
c952bd921f
|
|||
1a4d4997da
|
|||
34d6aa5a36
|
|||
90e9b9bb05
|
|||
44c4f4045f
|
|||
95c6ecf8b4
|
|||
f34cd88de1
|
|||
a999024ddf
|
|||
9ef9c8454b
|
|||
8f2a575010
|
|||
654f2982de
|
|||
f0230bbbc3
|
@ -4,8 +4,9 @@
|
||||
|
||||
```json
|
||||
{
|
||||
"host": "127.0.0.1",
|
||||
"port": 9250,
|
||||
"binds": [
|
||||
"127.0.0.1:9250"
|
||||
],
|
||||
"log": "-",
|
||||
"buffer-size": "4KiB",
|
||||
"max-size": "2GB",
|
||||
@ -13,6 +14,6 @@
|
||||
"TESTKEY"
|
||||
],
|
||||
"max-data": "10GB",
|
||||
"database": "databse.json"
|
||||
"database": "database.json"
|
||||
}
|
||||
```
|
||||
|
30
flake.lock
generated
30
flake.lock
generated
@ -23,11 +23,11 @@
|
||||
"systems": "systems_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1705309234,
|
||||
"narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=",
|
||||
"lastModified": 1710146030,
|
||||
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26",
|
||||
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@ -45,11 +45,11 @@
|
||||
"spectrum": "spectrum"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1712654305,
|
||||
"narHash": "sha256-CNdpLnGOUZfIhBanAFVF7t1xstaQGL4w6sQPrVeLlus=",
|
||||
"lastModified": 1720034501,
|
||||
"narHash": "sha256-fzZpuVnhw5uOtA4OuXw3a+Otpy8C+QV0Uu5XfhGEPSg=",
|
||||
"owner": "astro",
|
||||
"repo": "microvm.nix",
|
||||
"rev": "ee0068ca87bdabbde3cc39b7af807c0302d0304c",
|
||||
"rev": "a808af7775f508a2afedd1e4940a382fe1194f21",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@ -81,11 +81,11 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1712608508,
|
||||
"narHash": "sha256-vMZ5603yU0wxgyQeHJryOI+O61yrX2AHwY6LOFyV1gM=",
|
||||
"lastModified": 1720031269,
|
||||
"narHash": "sha256-rwz8NJZV+387rnWpTYcXaRNvzUSnnF9aHONoJIYmiUQ=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "4cba8b53da471aea2ab2b0c1f30a81e7c451f4b6",
|
||||
"rev": "9f4128e00b0ae8ec65918efeba59db998750ead6",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@ -106,11 +106,11 @@
|
||||
"treefmt-nix": "treefmt-nix"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1708589824,
|
||||
"narHash": "sha256-2GOiFTkvs5MtVF65sC78KNVxQSmsxtk0WmV1wJ9V2ck=",
|
||||
"lastModified": 1719850884,
|
||||
"narHash": "sha256-UU/lVTHFx0GpEkihoLJrMuM9DcuhZmNe3db45vshSyI=",
|
||||
"owner": "nix-community",
|
||||
"repo": "poetry2nix",
|
||||
"rev": "3c92540611f42d3fb2d0d084a6c694cd6544b609",
|
||||
"rev": "42262f382c68afab1113ebd1911d0c93822d756e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@ -194,11 +194,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1708335038,
|
||||
"narHash": "sha256-ETLZNFBVCabo7lJrpjD6cAbnE11eDOjaQnznmg/6hAE=",
|
||||
"lastModified": 1719749022,
|
||||
"narHash": "sha256-ddPKHcqaKCIFSFc/cvxS14goUhCOAwsM1PbMr0ZtHMg=",
|
||||
"owner": "numtide",
|
||||
"repo": "treefmt-nix",
|
||||
"rev": "e504621290a1fd896631ddbc5e9c16f4366c9f65",
|
||||
"rev": "8df5ff62195d4e67e2264df0b7f5e8c9995fd0bd",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
description = "PLACEHOLDER";
|
||||
description = "A webserver to create files for tetsing purposes";
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
|
||||
|
32
src/main.py
32
src/main.py
@ -4,7 +4,7 @@ import argparse
|
||||
import json
|
||||
from os.path import exists
|
||||
|
||||
from fastapi import FastAPI, Request, HTTPException
|
||||
from fastapi import FastAPI, Request, HTTPException, Query
|
||||
from fastapi.responses import StreamingResponse
|
||||
from fastapi import status
|
||||
from hypercorn.config import Config
|
||||
@ -32,7 +32,7 @@ if not exists(DATABASE):
|
||||
save_database(DATABASE, {'data-used': 0})
|
||||
|
||||
|
||||
api = FastAPI()
|
||||
api = FastAPI(docs_url=None, redoc_url=None)
|
||||
|
||||
|
||||
class MaxSizePerRequestError(Exception):
|
||||
@ -44,7 +44,7 @@ class MinSizePerRequestError(Exception):
|
||||
|
||||
|
||||
@api.get('/')
|
||||
def test_data(api_key: str, size: str, request: Request) -> StreamingResponse:
|
||||
async def test_data(api_key: str, size: str) -> StreamingResponse:
|
||||
try:
|
||||
if api_key not in AUTHORIZED_KEYS:
|
||||
raise HTTPException(
|
||||
@ -52,7 +52,13 @@ def test_data(api_key: str, size: str, request: Request) -> StreamingResponse:
|
||||
detail='Invalid API Key.'
|
||||
)
|
||||
|
||||
size = convert_to_bytes(size)
|
||||
try:
|
||||
size = convert_to_bytes(size)
|
||||
except ValueError as err:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail='Invalid format format for size.'
|
||||
) from err
|
||||
|
||||
if size < 0:
|
||||
raise MinSizePerRequestError
|
||||
@ -71,26 +77,30 @@ def test_data(api_key: str, size: str, request: Request) -> StreamingResponse:
|
||||
|
||||
return StreamingResponse(
|
||||
status_code=status.HTTP_200_OK,
|
||||
content=generate_data(size, BUFFER_SIZE)
|
||||
content=generate_data(size, BUFFER_SIZE),
|
||||
media_type='application/octet-stream',
|
||||
headers={
|
||||
'Content-Length': size
|
||||
}
|
||||
)
|
||||
|
||||
except MinSizePerRequestError:
|
||||
except MinSizePerRequestError as err:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE,
|
||||
detail=f'Size has to be not-negative.'
|
||||
)
|
||||
except MaxSizePerRequestError:
|
||||
detail='Size has to be not-negative.'
|
||||
) from err
|
||||
except MaxSizePerRequestError as err:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE,
|
||||
detail=f'Exceeded max size per request of {MAX_SIZE} Bytes.'
|
||||
)
|
||||
) from err
|
||||
|
||||
|
||||
def main():
|
||||
asyncio.run(serve(
|
||||
api,
|
||||
Config().from_mapping(
|
||||
bind=[f"{CONFIG['host']}:{CONFIG['port']}"],
|
||||
bind=CONFIG['binds'],
|
||||
accesslog='-'
|
||||
)
|
||||
))
|
||||
|
29
src/utils.py
29
src/utils.py
@ -1,14 +1,15 @@
|
||||
import json
|
||||
import asyncio
|
||||
|
||||
def convert_to_bytes(size: int | str) -> int:
|
||||
try:
|
||||
return int(size)
|
||||
except ValueError: # treat as string
|
||||
units = {
|
||||
'TB': 10 ** 12, 'TiB': 2 ** 40,
|
||||
'GB': 10 ** 9, 'GiB': 2 ** 30,
|
||||
'MB': 10 ** 6, 'MiB': 2 ** 20,
|
||||
'KB': 10 ** 3, 'KiB': 2 ** 10,
|
||||
'TB': 1000 ** 4, 'TiB': 1024 ** 4,
|
||||
'GB': 1000 ** 3, 'GiB': 1024 ** 3,
|
||||
'MB': 1000 ** 2, 'MiB': 1024 ** 2,
|
||||
'KB': 1000, 'KiB': 1024,
|
||||
'B': 1
|
||||
}
|
||||
|
||||
@ -17,15 +18,25 @@ def convert_to_bytes(size: int | str) -> int:
|
||||
return int(float(size.removesuffix(unit)) * units[unit])
|
||||
break
|
||||
|
||||
raise ValueError
|
||||
|
||||
|
||||
async def generate_data(size: int, buffer_size: int = 4 * 1024) -> bytes:
|
||||
size_left = size
|
||||
|
||||
while size_left > buffer_size:
|
||||
size_left -= buffer_size
|
||||
yield b'\0' * buffer_size
|
||||
else:
|
||||
yield b'\0' * size_left
|
||||
# https://github.com/tiangolo/fastapi/issues/5183
|
||||
# https://github.com/encode/starlette/discussions/1776#discussioncomment-3207518
|
||||
|
||||
try:
|
||||
while size_left > buffer_size:
|
||||
size_left -= buffer_size
|
||||
yield b'\0' * buffer_size
|
||||
await asyncio.sleep(0)
|
||||
else:
|
||||
yield b'\0' * size_left
|
||||
await asyncio.sleep(0)
|
||||
except asyncio.CancelledError:
|
||||
raise GeneratorExit
|
||||
|
||||
|
||||
def check_policies(ip: str) -> None:
|
||||
|
Reference in New Issue
Block a user