Quick Start

Dependencies

Installation

$ pip install flask flask_shell2http

Example Program

Create a file called app.py.

from flask import Flask
from flask_executor import Executor
from flask_shell2http import Shell2HTTP

# Flask application instance
app = Flask(__name__)

executor = Executor(app)
shell2http = Shell2HTTP(app=app, executor=executor, base_url_prefix="/commands/")

def my_callback_fn(context, future):
  # optional user-defined callback function
  print(context, future.result())

shell2http.register_command(endpoint="saythis", command_name="echo", callback_fn=my_callback_fn, decorators=[])

Run the application server with, $ flask run -p 4000.

With <10 lines of code, we succesfully mapped the shell command echo to the endpoint /commands/saythis.

Making HTTP calls

This section demonstrates how we can now call/ execute commands over HTTP that we just mapped in the example above.

$ curl -X POST -H 'Content-Type: application/json' -d '{"args": ["Hello", "World!"]}' http://localhost:4000/commands/saythis
or using python's requests module,
# You can also add a timeout if you want, default value is 3600 seconds
data = {"args": ["Hello", "World!"], "timeout": 60, "force_unique_key": False}
resp = requests.post("http://localhost:4000/commands/saythis", json=data)
print("Result:", resp.json())

returns JSON,

{
   "key": "ddbe0a94",
   "result_url": "http://localhost:4000/commands/saythis?key=ddbe0a94&wait=false",
   "status": "running"
}

Then using this key you can query for the result or just by going to the result_url,

$ curl http://localhost:4000/commands/saythis?key=ddbe0a94&wait=true # wait=true so we don't need to poll

Returns result in JSON,

{
  "report": "Hello World!\n",
  "key": "ddbe0a94",
  "start_time": 1593019807.7754705,
  "end_time": 1593019807.782958,
  "process_time": 0.00748753547668457,
  "returncode": 0,
  "error": null,
}

Hint

Use wait=true when you don't wish to HTTP poll and want the result in a single request only. This is especially ideal in case you specified a low timeout value in the POST request.

Hint

By default, the key is the SHA1 sum of the command + args POSTed to the API. This is done as a rate limiting measure so as to prevent multiple jobs with same parameters, if one such job is already running. If force_unique_key is set to true, the API will bypass this default behaviour and a psuedorandom key will be returned instead.

Note

You can see the full JSON schema for the POST request, here.

Bonus

You can also define callback functions or use signals for reactive programming. There may be cases where the process doesn’t print result to standard output but to a file/database. In such cases, you may want to intercept the future object and update it’s result attribute. I request you to take a look at Examples.md for such use-cases.