{ "info": { "author": "EAB tech", "author_email": "opensource@eab.com", "bugtrack_url": null, "classifiers": [ "Environment :: Web Environment", "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "Minik: Serverless Web Framework\n===============================\n\n\n|circle| |pypi version| |apache license|\n\nA web framework that facilitates the development of serverless applications using\nAWS resources. Minik natively supports request from the API Gateway and the\nApplication Load Balancer.\n\nInstalling\n**********\n\nInstall the latest release:\n\n>>> pip install minik\n\u2728\ud83c\udf70\u2728\n\nOnly **Python 3.6+** is supported.\n\nSimple Example\n**************\nIn it's most basic form; quite honestly, it's only form. This is how your lambda\nfunction should look like:\n\n.. code-block:: python\n\n from minik.core import Minik, BadRequestError\n\n app = Minik()\n\n @app.route('/hello/{name}')\n def hello_view(name: str):\n\n if name == 'FINDME':\n # Returns a 400 status code with the message as the body.\n raise BadRequestError(msg='This is not a supported name.')\n\n # A simple way of getting the current request as json.\n request_payload = app.request.json_body\n return {'hello': name}\n\nHTTP Methods\n************\nWith minik you can also specify the HTTP methods for a given view. If you don't\ndefine the methods, every single HTTP method will be allowed by default.\n\n.. code-block:: python\n\n from minik.core import Minik\n\n app = Minik()\n\n @app.route('/events/{location}')\n def events_view(location: str):\n # This route will be invoked for GET, POST, PUT, PATCH, DELETE...\n return {'data': ['granfondo MD', 'Silver Spring Century']}\n\n @app.route('/events', methods=['POST', 'PUT'])\n def create_event_view():\n create_event(app.request.json_body)\n return {'result': 'complete'}\n\nIf your view is associated with a single HTTP method, you can use the decorator\nversion.\n\n.. code-block:: python\n\n from minik.core import Minik\n\n app = Minik()\n\n @app.get('/events/{location}')\n def get_view(location: str):\n return {'data': ['granfondo MD', 'Silver Spring Century']}\n\n @app.post('/events')\n def post_view():\n create_event(app.request.json_body)\n return {'result': 'complete'}\n\nRoute Parameter Validation\n**************************\nMinik uses `function annotations`_ to validate the value of a route. If the type\nof an expected parameter is not valid, minik will respond with a 404 not found\nstatus code.\n\n.. code:: python\n\n @app.route('/articles/{author}/{year}/')\n def get_articles_view(author: str, year: int):\n # Type conversion: isinstance(author, str) and isinstance(year, int)\n return {'author_name': author, 'year': year}\n\n\nTo learn more checkout out the `route validation`_ page.\n\n.. _`function annotations`: https://www.python.org/dev/peps/pep-3107/\n.. _`route validation`: https://eabglobal.github.io/minik/features\n\n\nCustom Headers\n**************\nTo update the values of the HTTP response, minik exposes a response object at\nthe app level. By default minik will create a Response instance with a status code\nof 200 and a set of default headers. The headers include a default content-type\nvalue of `application/json`.\n\nFor instance, to set the CORS headers in a view and change the content type, a\nview would look like:\n\n.. code:: python\n\n app = Minik()\n\n @app.get('/articles/{author}/{year}/')\n def get_articles_view(author: str, year: int):\n app.response.headers = {\n \"Content-Type\": \"Content-Type\": \"text/html; charset=utf-8\",\n \"Access-Control-Allow-Origin\": \"*\",\n \"Access-Control-Allow-Methods\": \"GET\",\n \"Access-Control-Allow-Headers\": \"Content-Type,X-Amz-Date\",\n \"Authorization\": \"X-Api-Key,X-Amz-Security-Token\"\n }\n\n return f\"A very short article by {author}\"\n\n\nDebug Mode\n**********\nFor unhandled exceptions, minik will respond with a 500 status code and\na generic error message. To get more details from the response including the stack\ntrace and information about the exception, run the app in debug mode.\n\nBy default the debug mode is set to False.\n\n.. code:: python\n\n app = Minik(debug=True)\n\nInitializing the app in debug mode will relay the stack trace back to the consumer.\n\n\nALB Support\n***********\nAlong with having a native integration with the API Gateway, minik can now be used\nto handle requests coming from an Application Load Balancer (ALB). The definition\nof the web application is identical in both cases. There is no additional code required\nto use minik with an ALB.\n\nIf a lambda function is the `target of an ALB`_, minik will parse the raw event,\nfind the view associated with the route and execute the view with the correct context.\n\n.. code-block:: python\n\n from minik.core import Minik\n\n app = Minik()\n\n @app.get('/greetings')\n def get_greetings():\n app.response.headers = {\"Content-Type\": \"text/html; charset=utf-8\"}\n\n return \"\"\"\n \n
\nHello World!
\n \n \"\"\"\n\nNotice that there is nothing specific about the source that will eventually invoke\nthis lambda function. This codeblock can be used to handle a request either\nfrom the API Gateway or from an ALB.\n\n.. _`target of an ALB`: https://aws.amazon.com/blogs/networking-and-content-delivery/lambda-functions-as-targets-for-application-load-balancers/\n\n\nRequest Object\n**************\nAny view has access to the **app.request** instance as a way to retrieve the general\ninformation of a request. The fields of this object include the query parameters,\nthe path parameters, headers, payload... Given that different sources might have\na set of additional fields, minik will store a copy of the original event in the\n**app.request** instance.\n\nFor instance, the API Gateway has the concept of stage variables that is missing\nfrom an event received from the ALB. In this case, the generic app.request instance will\nnot have a field called stage_variables. Instead, minik keeps a copy of the original\nevent and context objects in the request. In this case a developer can access these\nvalues using the app.request.aws_event['StageVariables']. Where the aws_event is\nthe event minik received as the handler of the lambda function.\n\n.. code-block:: python\n\n from minik.core import Minik\n\n app = Minik()\n\n @app.post('/events')\n def post_view():\n # app.request.json_body: The payload of a post request as a JSON object.\n # app.request.aws_event: The raw event sent by a source to the lambda function.\n # app.request.aws_context: The context of the lambda function.\n return {'result': 'complete'}\n\n\nMotivation\n**********\nThe team behind this framework is adopting a very minimal set of features to enhance\nand streamline web development in the serverless space. These were the business\nneeds that encouraged us to build minik:\n\n- Ability to write an API using a familiar (Flask like) syntax using serverless\n services.\n- Flexibility on how to build and deploy lambda functions. I do not want\n my framework to dictate these processes for me. I want to own them!\n- When installing a web framework, I want to get only the framework. I don\u2019t\n want any additional tooling or any additional process-based workflows.\n- When using the microframework I am responsible for the configuration\n required to associate my lambda function to its endpoints.\n\nThe features of this library should be absolutely driven by a very specific\nbusiness need. So far, the minimal approach has been sufficient for our team to\nwrite and expose an API using AWS services.\n\n\nJust the framework\n******************\nThings to be aware of when working using minik:\n\n- When used in your lambda function, you're responsible for including the source\n code of minik in your .zip artifact. For packaging purposes we recommend using\n `Juniper`_.\n- Minik is service agnostic, as a web framework it natively supports requests\n from the API Gateway and an Application Load Balancer (ALB).\n- Unlike other frameworks like Flask or Django, where using the decorator is\n sufficient to define the routes of the web app, in minik, you\u2019re responsible\n for linking a lambda function to the API Gateway. We recommend using a\n `SAM`_ template.\n- Minik does not include a local development server! For testing purposes, you can\n either deploy your lambda to AWS using `sam package` and `sam deploy`. For local\n deployment purposes you can use `sam local`.\n\nQuickstart\n**********\nMinik is just one of the pieces that you need to build serverless APIs. If you\nare curious to learn more about best practices and how to get started with this\nmicroframework, checkout out `getting started