Skip to content

yanxurui/Snapfile

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Snapfile

An anonymous file transfer application that enables you to access files from any device without any account

Features

  • anonymous chat room
  • file transfer across any devices where a modern browswer is available
  • secure:
    • all user data (messages and files) will be encrypted. Since passcode is never persisted in the server side, no one except the owner can decrypt the data
    • expires automatically after one day

Install & Run

Project layout

Snapfile/
├── client/          # Vue 3 + Vite single-page app
├── server/          # Python backend (setup.py, snapfile/, tests/)
├── deploy/          # Production configuration & install script
├── docs/            # Design notes, changelog, etc.

Getting started quickly

Prerequisites

  • Python 3.12 (pyenv recommended)
  • Redis
  • Node.js 18+ (for the Vue-based client build)
# 1. download source code
git clone https://github.com/yanxurui/Snapfile
cd Snapfile

# 2. build the client
cd client
npm install
npm run build
cd ..

# 3. configure the server (see server/snapfile/config.py)

# 4. install the backend package
cd server
pip install -e .

# 5. start the app (installed "snapfile" console entry point)
snapfile

some default configuration

  • PORT: The server will listen to port 8090
  • LOG_FILE: Logs are output to test.log in the current workding directory (i.e., CWD)
  • UPLOAD_ROOT_DIRECTORY: Files are stored in ./upload in CWD

Deploy in production mode (CentOS)

Change the prefix and user in deploy/install.sh and then run it as root

git pull
cd deploy
bash install.sh

The directory structure of prefix(/var/www/snapfile for example)

`-- snapfile
    |-- db
    |   `-- appendonly.aof
    |   `-- dump.rdb
    |-- files
    |   `-- 324
    |       `-- thfaxm
    |           `-- 1
    |-- logs
    |   |-- nginx_access.log
    |   |-- nginx_err.log
    |   |-- snapfile.log
    |   `-- snapfile.out
    `-- static
        |-- assets
        |   `-- *.js / *.css (generated by Vite)
        |-- index.html
        `-- login.html

client/dist is generated by the Vue build. Edit the source under client/ and run npm run build whenever you need to update the UI assets. When running locally or in test mode, the Python backend automatically serves files directly from this directory. In production (ENV=PROD) static files are expected to be served by NGINX.

Development

AIOHttp

This is a web app based on aiohttp (built on top of asyncio) which is an asynchronous http libaray. That means, its networking operations are non-blocking and all http requests can be processed in a concurrent manner in a single thread. So far, it's the best choice in the Python world for constructing a high performance web server.

It supports websocket (long connection) which allows to implement the instant messaging or chat very easily.

NGINX

  1. serve static files, such as html, css, etc
  2. handle download efficiently
  3. prevent from brute force attack
  4. sharing port 443 with other services and forwarding to the backend (python web app in our case)

Redis

keys:

  • #files:<folder identity> int: the last file id in a given folder
  • folder:<folder identity> str: meta data of a folder serialized in json format, like created time, quota, size, etc
  • messages::<folder identity> list: messages (including file meta data) serialized in json format

Client (Vue + Vite)

The legacy jQuery UI has been migrated to Vue 3 with Vite.

cd client

# install dependencies
npm install

# start Vite dev server with backend proxying to the Python app on :8080
npm run dev

# produce production assets into dist/ (copied to /var/www/snapfile/static by install.sh)
npm run build

# locally preview the production build
npm run preview

Supervisord

manage the lifecycle of the service To restart the service, run the command below as root:

supervisorctl restart snapfile

Test

need to install packages: websocket-client

test_api.py

Functional test for APIs of python backend: using the classical python unittest

cd tests
python -m unittest -v test_api.py
  • use a separate port 8090
  • select db 0 of Redis
  • clean all data at startup

some known issues:

The error below is due to a bug in package requests: Revert PR 1440, do not modify cookie value by yanxurui · Pull Request #5459 · psf/requests

json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)

There might be a chance that test_api.TestExpire fails because the orphan process is cleang the data.

AssertionError: '1 folders found and 0 folders deleted' not found in 'xxx

test_nginx.py

Functional test for NGINX config in a production environment.

benchmark.py

stress test for aiohttp.

About

My web app for transferring files across devices

Resources

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •