Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
asyncio-simple-http-server
Advanced tools
This package contains a really Simple Http API Server using asyncio. It is not meant to be used in production. It is more a lightweight alternative to SimpleHTTPServer but for writing HTTP APIs.
You can find the package at https://pypi.org/project/asyncio-simple-http-server.
Python >=3.8 is required. To install or upgrade you can use:
$ pip install --upgrade asyncio-simple-http-server
To start the server is the usual straightforward asyncio server code, plus some registration for your HTTP API handlers.
from asyncio_simple_http_server import HttpServer
import asyncio
async def main():
# Create an instance of the HTTP Server
http_server = HttpServer()
# Register one or more handlers
# The handlers are classes containing your APIs
# See below for an example and more information.
http_server.add_handler(MyHandler())
# If you need to enable CORS to call the APIs
# from a web console that you are building (e.g. angular, react, ...)
# just add the following line,
# to add the required header to all the responses.
http_server.add_default_response_headers({
'Access-Control-Allow-Origin': '*'
})
# start the server and serve/wait forever
await http_server.start('127.0.0.1', 8888)
await http_server.serve_forever()
if __name__ == '__main__':
asyncio.run(main())
An handler is a simple class where some methods can be exposed as an HTTP API, using a simple annotation. It also tries to simplify things for REST by converting the request body from json to a dict and the response object to json using the json.loads() and json.dumps() methods.
from asyncio_simple_http_server import uri_mapping
class MyHandler:
# The @uri_mapping decorator exposes this method as an HTTP API
# so you can just do a HTTP GET /test-get
# and you'll get back a 200 OK with a json body of {a: 10}
# return values will be converted with json.dumps()
@uri_mapping('/test-get')
def test_get(self):
return {'a': 10}
# In this case the mapping says that we want a POST method
# and by passing an argument named 'body' we will get the
# body passed to the endpoint parsed with json.loads()
# We execute "some logic" and we return the body
@uri_mapping('/test-post', method='POST')
def test_post(self, body):
foo = body.get('foo')
print('foo:', foo)
return body
To receive the data of the HTTP request we use special parameter names, so if name a variable:
You can return an HttpResponse object to customize the response with your status code, headers and body encoding. You can also send a file by specifying the file path instead of the body.
from asyncio_simple_http_server import uri_mapping, HttpResponse, HttpHeaders
class MyHandler:
# You can return an HttpResponse object to set
# custom status code, headers and body
@uri_mapping('/test-custom-response')
def test_custom_resp(self) -> HttpResponse:
headers = HttpHeaders()
headers.set('X-Foo', 'custom stuff')
return HttpResponse(200, headers, b'test-body')
# With an HttpResponse object
# you can also send a file that is on disk
@uri_pattern_mapping('/send-my-file')
def test_file(self) -> HttpResponse:
return HttpResponse(200, file_path='/path/of/my-file')
You can also control the flow using HttpResponseException. If not catched by your code it will result in a response with the http status code, headers and body specified.
@uri_mapping('/test-exception')
def test_exception(self):
headers = HttpHeaders()
headers.set('X-Foo', 'custom stuff')
raise HttpResponseException(400, headers, b'custom-body')
Sometimes static routes are not enough. and you want a dynamic pattern. You can use @uri_variable_mapping and @uri_pattern_mapping to do exactly that.
from asyncio_simple_http_server import HttpRequest, uri_variable_mapping, uri_pattern_mapping
class MyHandler:
# You can also map routes with variables
# for example you can call this one with /aaa/FOO/ccc/BAR
# and you'll get {'bbb': 'FOO', 'ddd', 'BAR'} as uri_variables
@uri_variable_mapping('/aaa/{bbb}/ccc/{ddd}')
def test_due(self, uri_variables: dict):
return uri_variables
# Or you can use regex patterns to match what you want
# for example here you can call it as /any/FOO/BAR or /any/ZOO
@uri_pattern_mapping('/any/(.*)')
def test_pattern(self, request: HttpRequest):
return request.path
Oh yeah, I almost forgot. This server uses asyncio, so your function can be async too. just add async to the method and use all the awaits that you want.
class MyHandler:
@uri_mapping('/async-sleep')
async def test_async_sleep(self):
await asyncio.sleep(4)
FAQs
A Simple Http API Server using asyncio
We found that asyncio-simple-http-server demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.