{"id":17000264,"url":"https://github.com/zmwangx/yodo","last_synced_at":"2025-04-12T06:09:12.831Z","repository":{"id":50630575,"uuid":"182479468","full_name":"zmwangx/YODO","owner":"zmwangx","description":"Dead simple ephemeral file hosting service","archived":false,"fork":false,"pushed_at":"2019-04-21T04:12:56.000Z","size":11,"stargazers_count":5,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-12T06:09:03.573Z","etag":null,"topics":["ephemeral","file-hosting","file-sharing","flask"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"wtfpl","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zmwangx.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-04-21T02:37:12.000Z","updated_at":"2022-07-31T03:52:12.000Z","dependencies_parsed_at":"2022-09-04T18:53:45.682Z","dependency_job_id":null,"html_url":"https://github.com/zmwangx/YODO","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zmwangx%2FYODO","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zmwangx%2FYODO/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zmwangx%2FYODO/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zmwangx%2FYODO/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zmwangx","download_url":"https://codeload.github.com/zmwangx/YODO/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248525139,"owners_count":21118619,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ephemeral","file-hosting","file-sharing","flask"],"created_at":"2024-10-14T04:11:40.434Z","updated_at":"2025-04-12T06:09:12.801Z","avatar_url":"https://github.com/zmwangx.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# YODO - You Only Download Once\n\n![Python 3.6, 3.7](https://img.shields.io/badge/python-3.6,%203.7-blue.svg?maxAge=86400)\n![Powered by Flask](https://img.shields.io/badge/powered%20by-Flask-blue.svg?logo=flask\u0026maxAge=86400)\n[![CircleCI](https://img.shields.io/circleci/project/github/zmwangx/YODO.svg)](https://circleci.com/gh/zmwangx/YODO)\n\nYODO (pronounced *you\u0026middot;dough*) is a dead simple, database-less ephemeral file hosting service powered by Flask.\n\nYou upload a file via a POST request; you receive a URL as response; you get to download the file via that URL, after which the file is destroyed. It's that simple.\n\n**Security isn't a primary concern of this app. Don't host it on the public Internet!**\n\n\u003c!-- START doctoc generated TOC please keep comment here to allow auto update --\u003e\n\u003c!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --\u003e\n## Contents\n\n- [Usage](#usage)\n- [Deployment](#deployment)\n- [Environment variables](#environment-variables)\n- [Motivation](#motivation)\n- [License](#license)\n\n\u003c!-- END doctoc generated TOC please keep comment here to allow auto update --\u003e\n\n## Usage\n\nUsage instructions (reproduced below) can be accessed at the root of the service via a GET request:\n\n```console\n$ ./app.py\n* Serving Flask app \"app\" (lazy loading)\n...\n$ curl http://127.0.0.1:14641/\nYODO - You Only Download Once\n=============================\n\nYODO is an ephemeral file hosting service.\n\nThere are two ways to upload a file (say, image.png):\n\n    $ curl --header 'Content-Type: image/png' --data-binary @image.png http://127.0.0.1:14641/\n    $ curl --form 'file=@image.png;type=image/png' http://127.0.0.1:14641/\n\nApparently these are just different flavors of POST requests. The former\nsimply uses the content of the file as request body, and identifies\nitself via the Content-Type header, but there is no way to provide a\nfilename. The latter is a multipart/form-data request where the content\nis uploaded through the 'file' part; both Content-Type and filename may\nbe specified this way. Note that application/x-www-form-urlencoded\nrequests are not allowed.\n\nThere is an upload size limit of 10485760 bytes.\n\nThe response should be HTTP 201 with the URL of the newly uploaded file,\ne.g.,\n\n    $ curl --dump-header - --form 'file=@image.png;type=image/png' http://127.0.0.1:14641/\n    HTTP/1.1 100 Continue\n\n    HTTP/1.0 201 CREATED\n    Content-Type: text/html; charset=utf-8\n    Content-Length: 60\n\n    http://127.0.0.1:14641/2c8000bc-7c10-4700-9cc3-eb0dce0a9d1a\n\nThe URL is available for download exactly once; the file is destroyed\nafter the first GET request (but not HEAD). Content-Type, if not\nspecified at upload time, is guessed. The Content-Disposition header\nis available if filename was specified at upload time.\n\n    $ curl --head http://127.0.0.1:14641/2c8000bc-7c10-4700-9cc3-eb0dce0a9d1a\n    HTTP/1.0 200 OK\n    Content-Type: image/png\n    Content-Disposition: attachment; filename=\"image.png\"\n    Content-Length: 25715\n```\n\n## Deployment\n\nA sample gunicorn + systemd deployment setup is shown in [`etc/gunicorn-systemd.service`](etc/gunicorn-systemd.service).\n\nAgain, do NOT deploy this to a public facing network.\n\n## Environment variables\n\n- `STATE_DIRECTORY`: required. Absolute path to the directory for file storage. This directory should support atomic file creation and renaming.\n- `MAX_CONTENT_LENGTH`: optional, defaults to 10,485,760 (10MiB). The server rejects larger requests with 413 Request Entity Too Large.\n\n## Motivation\n\nI have a Dockerized chat bot that only accepts HTTP URLs for images. I need to send real time, generated-on-the-fly tables/charts through it. The images become useless quickly so there's no point in archival (and I have all the historical data in a database anyway). While a dedicated, periodically wiped directory served by nginx would be enough, I figured that a service that cleans up after itself without cron intervention would be nicer. Hence this.\n\n## License\n\nCopyright (c) 2019 Zhiming Wang \u003ci@zhimingwang.org\u003e\n\nThis work is free. You can redistribute it and/or modify it under the\nterms of the Do What The Fuck You Want To Public License, Version 2,\nas published by Sam Hocevar.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzmwangx%2Fyodo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzmwangx%2Fyodo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzmwangx%2Fyodo/lists"}