Densaugeo / uploadserver

Python's http.server extended to include a file upload page
MIT License
233 stars 48 forks source link

uploadserver

Python's http.server extended to include a file upload page

License: MIT Build Status

Supported Platforms

Platform Supported? Notes
Python 3.8+ Yes Tested on 3.8 through 3.12 every release.
Python 3.6-3.7 No Was supported by previous versions.
Python 3.5- No
Linux Yes Tested on Fedora and Ubuntu every release.
Windows Yes Occasional manual testing. Haven't noticed any obvious problems.
Mac No idea I don't have a Mac. Idk if it works or not.

Installation

python3 -m pip install --user uploadserver

Usage

python3 -m uploadserver

Accepts the same options as http.server, plus a couple extras (documented below).

After the server starts, the upload page is at /upload. For example, if the server is running at http://localhost:8000/ go to http://localhost:8000/upload .

Warning: This is an upload server, and running it will allow uploads.

Now supports uploading multiple files at once! Select multiple files in the web page's file selector, or upload with cURL:

curl -X POST http://127.0.0.1:8000/upload -F 'files=@multiple-example-1.txt' -F 'files=@multiple-example-2.txt'

Basic Authentication (downloads and uploads)

python3 -m uploadserver --basic-auth hello:world

Now you can upload with basic authentication. For example:

curl -X POST http://127.0.0.1:8000/upload -F 'files=@basicauth-example.txt' -u hello:world

All requests without authentication will be rejected. Note that basic authentication credentials can be stolen if sent over plain HTTP, so this option is best used with HTTPS.

Basic Authentication (uploads only)

python3 -m uploadserver --basic-auth-upload hello:world

The same as above, but authentication is only required for upload operations.

If both --basic-auth and --basic-auth-upload are specified, all requests will require one of the two credentials, but only the --basic-auth-upload credentials will be able to upload files.

Theme Option

The upload page supports a dark mode for showing white text on black background. If no option is specified, the color scheme is chosen from the client’s browser’s preference (which typically matches their operating system’s setting, if light or dark mode is supported by the OS). To enforce the light or dark theme, the CLI parameter --theme can be used:

python3 -m uploadserver --theme light

or

python3 -m uploadserver --theme dark

HTTPS Option

Run with HTTPS and without client authentication:

# Generate self-signed server certificate
openssl req -x509 -out server.pem -keyout server.pem -newkey rsa:2048 -nodes -sha256 -subj '/CN=server'

# The server root should not contain the certificate, for security reasons
cd server-root
python3 -m uploadserver --server-certificate server.pem

# Connect as a client
curl -X POST https://localhost:8000/upload --insecure -F files=@simple-example.txt

Run with HTTPS and with client authentication:

# Generate self-signed server certificate
openssl req -x509 -out server.pem -keyout server.pem -newkey rsa:2048 -nodes -sha256 -subj '/CN=server'

# Generate self-signed client certificate
openssl req -x509 -out client.pem -keyout client.pem -newkey rsa:2048 -nodes -sha256 -subj '/CN=client'

# Extract public key from self-signed client certificate
openssl x509 -in client.pem -out client.crt

# The server root should not contain the certificates, for security reasons
cd server-root
python3 -m uploadserver --server-certificate server.pem --client-certificate client.crt

# Connect as a client
curl -X POST https://localhost:8000/upload --insecure --cert client.pem -F files=@mtls-example.txt

Note: This uses a self-signed server certificate which clients such as web browser and cURL will warn about. Most browsers will allow you to proceed after adding an exception, and cURL will work if given the -k/--insecure option. Using your own certificate from a certificate authority will avoid these warnings.

Breaking Changes in 5.0.0

Breaking Changes in 4.0.0

Breaking Changes in 3.0.0

Breaking Changes in 2.0.0

Breaking Changes in 1.0.0

Acknowledgements

Much of main() was copied from Python's http.server.

Thanks to lishoujun for sending the first pull request! (Added the token option.)

Thanks to NteRySin for several improvements including mTLS support and refactoring to support use by other modules.

Thanks to marvinruder for work on the upload progress indicator, theme option, and pre-validation of tokens before upload.

Thanks to shuangye for finding an easy way to handle large file uploads, and improved handling of filename collisions.

Thanks to abbbe for adding HTTP basic auth (has now replaced the token option).