{"id":13806554,"url":"https://github.com/Eshaan7/Flask-Shell2HTTP","last_synced_at":"2025-05-13T22:30:22.716Z","repository":{"id":41663282,"uuid":"274753742","full_name":"eshaan7/Flask-Shell2HTTP","owner":"eshaan7","description":"Execute shell commands via HTTP server (via flask's endpoints). ","archived":false,"fork":false,"pushed_at":"2024-11-22T17:03:07.000Z","size":143,"stargazers_count":181,"open_issues_count":12,"forks_count":29,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-04-20T16:38:43.986Z","etag":null,"topics":["asynchronously","callback","executor","flask","flask-endpoints","flask-extension","flask-shell2http","hacktoberfest","python","shell","shell2http","subprocess","webhook"],"latest_commit_sha":null,"homepage":"https://flask-shell2http.readthedocs.io/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/eshaan7.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"custom":["https://xscode.com/eshaan7/flask-shell2http"]}},"created_at":"2020-06-24T19:35:02.000Z","updated_at":"2025-04-17T16:10:16.000Z","dependencies_parsed_at":"2024-12-29T00:23:11.843Z","dependency_job_id":"7193b451-f8cf-42a1-a801-e2060e6578bc","html_url":"https://github.com/eshaan7/Flask-Shell2HTTP","commit_stats":{"total_commits":71,"total_committers":6,"mean_commits":"11.833333333333334","dds":"0.14084507042253525","last_synced_commit":"92c71e3a0da1159dbca1578d50c32909ad6f3792"},"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eshaan7%2FFlask-Shell2HTTP","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eshaan7%2FFlask-Shell2HTTP/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eshaan7%2FFlask-Shell2HTTP/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eshaan7%2FFlask-Shell2HTTP/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eshaan7","download_url":"https://codeload.github.com/eshaan7/Flask-Shell2HTTP/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254036812,"owners_count":22003655,"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":["asynchronously","callback","executor","flask","flask-endpoints","flask-extension","flask-shell2http","hacktoberfest","python","shell","shell2http","subprocess","webhook"],"created_at":"2024-08-04T01:01:13.201Z","updated_at":"2025-05-13T22:30:22.378Z","avatar_url":"https://github.com/eshaan7.png","language":"Python","readme":"# Flask-Shell2HTTP\n\n[![flask-shell2http on pypi](https://img.shields.io/pypi/v/flask-shell2http)](https://pypi.org/project/Flask-Shell2HTTP/)\n[![Build Status](https://github.com/Eshaan7/flask-shell2http/workflows/Linter%20\u0026%20Tests/badge.svg?branch=master)](https://github.com/Eshaan7/flask-shell2http/actions?query=workflow%3A%22Linter+%26+Tests%22)\n[![codecov](https://codecov.io/gh/Eshaan7/Flask-Shell2HTTP/branch/master/graph/badge.svg?token=UQ43PYQPMR)](https://codecov.io/gh/Eshaan7/flask-shell2http/)\n[![CodeFactor](https://www.codefactor.io/repository/github/eshaan7/flask-shell2http/badge)](https://www.codefactor.io/repository/github/eshaan7/flask-shell2http)\n\u003ca href=\"https://lgtm.com/projects/g/Eshaan7/Flask-Shell2HTTP/context:python\"\u003e\n\u003cimg alt=\"Language grade: Python\" src=\"https://img.shields.io/lgtm/grade/python/g/Eshaan7/Flask-Shell2HTTP.svg?logo=lgtm\u0026logoWidth=18\"/\u003e\n\u003c/a\u003e\n\nA minimalist [Flask](https://github.com/pallets/flask) extension that serves as a RESTful/HTTP wrapper for python's subprocess API.\n\n- **Convert any command-line tool into a REST API service.**\n- Execute pre-defined shell commands asynchronously and securely via flask's endpoints with dynamic arguments, file upload, callback function capabilities.\n- Designed for binary to binary/HTTP communication, development, prototyping, remote control and [more](https://flask-shell2http.readthedocs.io/en/stable/Examples.html).\n\n## Use Cases\n\n- Set a script that runs on a succesful POST request to an endpoint of your choice. See [Example code](examples/run_script.py).\n- Map a base command to an endpoint and pass dynamic arguments to it. See [Example code](examples/basic.py).\n- Can also process multiple uploaded files in one command. See [Example code](examples/multiple_files.py).\n- This is useful for internal docker-to-docker communications if you have different binaries distributed in micro-containers. See [real-life example](https://github.com/intelowlproject/IntelOwl/blob/master/integrations/malware_tools_analyzers/app.py).\n- You can define a callback function/ use signals to listen for process completion. See [Example code](examples/with_callback.py).\n  - Maybe want to pass some additional context to the callback function ?\n  - Maybe intercept on completion and update the result ? See [Example code](examples/custom_save_fn.py)\n- You can also apply [View Decorators](https://flask.palletsprojects.com/en/1.1.x/patterns/viewdecorators/) to the exposed endpoint. See [Example code](examples/with_decorators.py).\n\n\u003e Note: This extension is primarily meant for executing long-running\n\u003e shell commands/scripts (like nmap, code-analysis' tools) in background from an HTTP request and getting the result at a later time.\n\n## Documentation\n\n[![Documentation Status](https://readthedocs.org/projects/flask-shell2http/badge/?version=latest)](https://flask-shell2http.readthedocs.io/en/latest/?badge=latest)\n\n- Read the [Quickstart](https://flask-shell2http.readthedocs.io/en/stable/Quickstart.html) from the [documentation](https://flask-shell2http.readthedocs.io/) to get started!\n- I also highly recommend the [Examples](https://flask-shell2http.readthedocs.io/en/stable/Examples.html) section.\n- [CHANGELOG](https://github.com/eshaan7/Flask-Shell2HTTP/blob/master/.github/CHANGELOG.md).\n\n## Quick Start\n\n##### Dependencies\n\n- Python: `\u003e=v3.6`\n- [Flask](https://pypi.org/project/Flask/)\n- [Flask-Executor](https://pypi.org/project/Flask-Executor)\n\n##### Installation\n\n```bash\n$ pip install flask flask_shell2http\n```\n\n##### Example Program\n\nCreate a file called `app.py`.\n\n```python\nfrom flask import Flask\nfrom flask_executor import Executor\nfrom flask_shell2http import Shell2HTTP\n\n# Flask application instance\napp = Flask(__name__)\n\nexecutor = Executor(app)\nshell2http = Shell2HTTP(app=app, executor=executor, base_url_prefix=\"/commands/\")\n\ndef my_callback_fn(context, future):\n  # optional user-defined callback function\n  print(context, future.result())\n\nshell2http.register_command(endpoint=\"saythis\", command_name=\"echo\", callback_fn=my_callback_fn, decorators=[])\n```\n\nRun the application server with, `$ flask run -p 4000`.\n\nWith \u003c10 lines of code, we succesfully mapped the shell command `echo` to the endpoint `/commands/saythis`.\n\n##### Making HTTP calls\n\nThis section demonstrates how we can now call/ execute commands over HTTP that we just mapped in the [example](#example-program) above.\n\n```bash\n$ curl -X POST -H 'Content-Type: application/json' -d '{\"args\": [\"Hello\", \"World!\"]}' http://localhost:4000/commands/saythis\n```\n\n\u003cdetails\u003e\u003csummary\u003eor using python's requests module,\u003c/summary\u003e\n\n```python\n# You can also add a timeout if you want, default value is 3600 seconds\ndata = {\"args\": [\"Hello\", \"World!\"], \"timeout\": 60}\nresp = requests.post(\"http://localhost:4000/commands/saythis\", json=data)\nprint(\"Result:\", resp.json())\n```\n\n\u003c/details\u003e\n\n\u003e Note: You can see the JSON schema for the POST request [here](https://github.com/Eshaan7/Flask-Shell2HTTP/blob/master/post-request-schema.json).\n\nreturns JSON,\n\n```json\n{\n  \"key\": \"ddbe0a94\",\n  \"result_url\": \"http://localhost:4000/commands/saythis?key=ddbe0a94\u0026wait=false\",\n  \"status\": \"running\"\n}\n```\n\nThen using this `key` you can query for the result or just by going to the `result_url`,\n\n```bash\n$ curl http://localhost:4000/commands/saythis?key=ddbe0a94\u0026wait=true # wait=true so we do not have to poll\n```\n\nReturns result in JSON,\n\n```json\n{\n  \"report\": \"Hello World!\\n\",\n  \"key\": \"ddbe0a94\",\n  \"start_time\": 1593019807.7754705,\n  \"end_time\": 1593019807.782958,\n  \"process_time\": 0.00748753547668457,\n  \"returncode\": 0,\n  \"error\": null\n}\n```\n\n## Inspiration\n\nThis was initially made to integrate various command-line tools easily with [Intel Owl](https://github.com/intelowlproject/IntelOwl), which I am working on as part of Google Summer of Code.\n\nThe name was inspired by the awesome folks over at [msoap/shell2http](https://github.com/msoap/shell2http).\n","funding_links":["https://xscode.com/eshaan7/flask-shell2http"],"categories":["Third-Party Extensions"],"sub_categories":["Utils"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FEshaan7%2FFlask-Shell2HTTP","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FEshaan7%2FFlask-Shell2HTTP","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FEshaan7%2FFlask-Shell2HTTP/lists"}