# Actions Server
A very simple, multi-threaded HTTP server.
Mainly designed for a very simple tasks, f.ex. 3 json-based endpoints with a simple logic
It utilizes a concept of "Actions" - the functions that can be executed to provide HTTP response.
## Important note:
This server DOES NOT cover all HTTP functionality. This is intentional and probably will not be changed in the future.
# Usage
```python
from actions_server import *
ACTIONS = [
JsonGet("/get", lambda params: {"response": "ok from GET action"}),
JsonPost("/post", lambda params, body: {"response": "ok from POST action"}),
Redirect("/", "/get"),
StaticResources("/static", "./src/web")
]
server = http_server(port=80, actions=ACTIONS, thread_count=5)
try:
server.start(block_caller_thread=True)
finally:
server.stop()
```
In this example, a server will be started on port 80 and the main thread will be blocked. The server will react on
several requests:
* `curl -X GET "http://localhost:80/get"` will produce `{"response": "ok from GET action"}` response
* `curl -X POST "http://localhost:8080/post` will produce `{"response": "ok from POST action"}` response
* `curl -X GET "http://localhost:80/` will send HTTP 301 Redirect to `http://localhost:80/get"
* `curl -X GET "http://localhost:80/static/aaa.png` will return an image `./src/web/aaa.png`
## Actions out-of-the-box
### `JsonGet(endpoint, callable)`
Will listen to the endpoint `endpoint`, call `callable(params)` (where params is a dict of arguments; note - values are
always an array!) and convert resulting dict into JSON
### `JsonPost(endpoint, callable, body)`
Will listen to the endpoint `endpoint`, call `callable(params, body)` (where params is a dict of arguments; note -
values are always an array!, and body is a parsed the request body into dict) and convert resulting dict into JSON
### `Redirect(from, to)`
Will send HTTP 301 Redirect
### `StaticResources(path, dir)`
Will server all files from `dir` under path `path`
## Implementing custom action
```python
from actions_server import *
class MyCustomResponse(Response):
def __init__(self, payload):
self._payload = payload
def headers(self) -> dict:
return {'Content-type': 'text/plain'}
def response_body_bytes(self):
return self._payload.encode('utf-8')
class MyCustomAction(Action):
def can_handle(self, method, path, params, payload):
return method == 'GET' and path == '/hello'
def handle(self, method, path, params, payload) -> Response:
return MyCustomResponse("hello there!")
```
Notes:
* parameter `method` may contain two strings - `GET` or `POST`
* response body must be bytes!
Raw data
{
"_id": null,
"home_page": "https://github.com/rzarajczyk/actions-server",
"name": "actions-server",
"maintainer": "",
"docs_url": null,
"requires_python": "",
"maintainer_email": "",
"keywords": "HTTP,SERVER",
"author": "Rafa\u0142 Zarajczyk",
"author_email": "rzarajczyk@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/c6/7f/7f6a791c62d23c66d94e38a28062aff340543e3348707bb5fae7fb7555c3/actions-server-0.0.10.tar.gz",
"platform": null,
"description": "# Actions Server\n\nA very simple, multi-threaded HTTP server.\n\nMainly designed for a very simple tasks, f.ex. 3 json-based endpoints with a simple logic\n\nIt utilizes a concept of \"Actions\" - the functions that can be executed to provide HTTP response.\n\n## Important note:\n\nThis server DOES NOT cover all HTTP functionality. This is intentional and probably will not be changed in the future.\n\n# Usage\n\n```python\nfrom actions_server import *\n\nACTIONS = [\n JsonGet(\"/get\", lambda params: {\"response\": \"ok from GET action\"}),\n JsonPost(\"/post\", lambda params, body: {\"response\": \"ok from POST action\"}),\n Redirect(\"/\", \"/get\"),\n StaticResources(\"/static\", \"./src/web\")\n]\n\nserver = http_server(port=80, actions=ACTIONS, thread_count=5)\n\ntry:\n server.start(block_caller_thread=True)\nfinally:\n server.stop()\n\n```\n\nIn this example, a server will be started on port 80 and the main thread will be blocked. The server will react on\nseveral requests:\n\n* `curl -X GET \"http://localhost:80/get\"` will produce `{\"response\": \"ok from GET action\"}` response\n* `curl -X POST \"http://localhost:8080/post` will produce `{\"response\": \"ok from POST action\"}` response\n* `curl -X GET \"http://localhost:80/` will send HTTP 301 Redirect to `http://localhost:80/get\"\n* `curl -X GET \"http://localhost:80/static/aaa.png` will return an image `./src/web/aaa.png`\n\n## Actions out-of-the-box\n\n### `JsonGet(endpoint, callable)`\n\nWill listen to the endpoint `endpoint`, call `callable(params)` (where params is a dict of arguments; note - values are\nalways an array!) and convert resulting dict into JSON\n\n### `JsonPost(endpoint, callable, body)`\n\nWill listen to the endpoint `endpoint`, call `callable(params, body)` (where params is a dict of arguments; note -\nvalues are always an array!, and body is a parsed the request body into dict) and convert resulting dict into JSON\n\n### `Redirect(from, to)`\n\nWill send HTTP 301 Redirect\n\n### `StaticResources(path, dir)`\n\nWill server all files from `dir` under path `path`\n\n## Implementing custom action\n\n```python\nfrom actions_server import *\n\nclass MyCustomResponse(Response):\n def __init__(self, payload):\n self._payload = payload\n\n def headers(self) -> dict:\n return {'Content-type': 'text/plain'}\n\n def response_body_bytes(self):\n return self._payload.encode('utf-8')\n\nclass MyCustomAction(Action):\n def can_handle(self, method, path, params, payload):\n return method == 'GET' and path == '/hello'\n\n def handle(self, method, path, params, payload) -> Response:\n return MyCustomResponse(\"hello there!\")\n```\n\nNotes:\n * parameter `method` may contain two strings - `GET` or `POST`\n * response body must be bytes!\n",
"bugtrack_url": null,
"license": "",
"summary": "A very simple, multi-threaded HTTP server",
"version": "0.0.10",
"project_urls": {
"Homepage": "https://github.com/rzarajczyk/actions-server"
},
"split_keywords": [
"http",
"server"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "46d4069a0ddfca82c32ae051935b4652d616c146482468e60de1b4ee5a800c67",
"md5": "c8ddf91ab61554f221c41e34a39d0590",
"sha256": "a6d62481d02d9a219becf39ee6e305549f0c306e5c0af066026ee14d9f4cb72c"
},
"downloads": -1,
"filename": "actions_server-0.0.10-py3-none-any.whl",
"has_sig": false,
"md5_digest": "c8ddf91ab61554f221c41e34a39d0590",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 8698,
"upload_time": "2024-01-23T22:55:53",
"upload_time_iso_8601": "2024-01-23T22:55:53.589494Z",
"url": "https://files.pythonhosted.org/packages/46/d4/069a0ddfca82c32ae051935b4652d616c146482468e60de1b4ee5a800c67/actions_server-0.0.10-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "c67f7f6a791c62d23c66d94e38a28062aff340543e3348707bb5fae7fb7555c3",
"md5": "7d24510ecbfa1bdb64e92567032661da",
"sha256": "183099a85c5c25b12df7ed010d525aa807e48b2117906e67bb226bd080f8a521"
},
"downloads": -1,
"filename": "actions-server-0.0.10.tar.gz",
"has_sig": false,
"md5_digest": "7d24510ecbfa1bdb64e92567032661da",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 8045,
"upload_time": "2024-01-23T22:55:55",
"upload_time_iso_8601": "2024-01-23T22:55:55.259223Z",
"url": "https://files.pythonhosted.org/packages/c6/7f/7f6a791c62d23c66d94e38a28062aff340543e3348707bb5fae7fb7555c3/actions-server-0.0.10.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-01-23 22:55:55",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "rzarajczyk",
"github_project": "actions-server",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"requirements": [
{
"name": "pytest",
"specs": [
[
"~=",
"7.1.2"
]
]
},
{
"name": "requests",
"specs": [
[
"~=",
"2.31.0"
]
]
},
{
"name": "multipart",
"specs": [
[
"~=",
"0.2.4"
]
]
},
{
"name": "deser",
"specs": [
[
"~=",
"0.0.1"
]
]
}
],
"lcname": "actions-server"
}