[
  {
    "path": ".gitignore",
    "content": "__pycache__\n"
  },
  {
    "path": "Dockerfile",
    "content": "FROM registry.opensource.zalan.do/stups/python:3.6.5-22\n\nCOPY Pipfile /\nCOPY Pipfile.lock /\n\nRUN pipenv install --system --deploy --ignore-pipfile\n\nCOPY app.py /\nCOPY swagger.yaml /\n\nWORKDIR /data\nCMD /app.py\n"
  },
  {
    "path": "LICENSE",
    "content": "Copyright 2015 Henning Jacobs\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n  http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n"
  },
  {
    "path": "MAINTAINERS",
    "content": "Henning Jacobs <henning.jacobs@zalando.de>\n"
  },
  {
    "path": "Pipfile",
    "content": "[[source]]\nurl = \"https://pypi.org/simple\"\nverify_ssl = true\nname = \"pypi\"\n\n[packages]\nconnexion = \"*\"\ngevent = \"*\"\ngreenlet = {version = \"*\", platform_python_implementation=\"=='CPython'\"}\n\n[dev-packages]\n\n[requires]\npython_version = \"3.6\"\n"
  },
  {
    "path": "README.rst",
    "content": "==============================\nConnexion Example REST Service\n==============================\n\nThis example application implements a very basic \"pet shop\" REST service using the `Connexion`_ Python library.\n\nConnexion is a framework on top of Flask_ to automagically handle your REST API requests\nbased on `Swagger 2.0 Specification`_ files in YAML.\n\n👉 Please also have a look at the `Connexion Example with Redis database and Kubernetes deployment manifests`_.\n\n\nFeatures\n========\n\nThis example application shows various features supported by the Connexion library:\n\n* mapping of REST operations to Python functions (using the ``operationId`` in ``swagger.yaml``)\n\n  * maps path, query and body parameters to keyword arguments\n\n* bundled Swagger UI (served on `/ui/`_ path)\n* automatic JSON serialization for ``application/json`` content type\n* schema validation for the HTTP request body and query parameters:\n\n  * required object properties\n  * primitive JSON types (string, integers, etc)\n  * date/time values\n  * string lengths\n  * minimum/maximum values\n  * regular expression patterns\n\n* gevent WSGI server\n* OAuth2 protection\n\n\nFiles\n=====\n\nThe example application only needs very few files:\n\n* ``swagger.yaml``: the pet shop REST API Swagger definition\n* ``app.py``: implementation of the pet shop operations with in-memory storage\n* ``Pipfile``: list of required Python libraries (used by Pipenv)\n* ``Dockerfile``: to build the example as a runnable Docker image\n* ``test.sh``: shell script to execute example HTTP requests against the pet shop API\n\n\nRunning Locally\n===============\n\nYou can run the Python application directly on your local operating system (this requires Python 3 and `Pipenv <https://docs.pipenv.org/>`_):\n\n.. code-block:: bash\n\n    $ pipenv install --dev && pipenv shell\n    $ ./app.py # start the HTTP server\n    $ xdg-open http://localhost:8080/ui/\n    $ ./test.sh # do some test HTTP requests\n\n\nRunning with Docker\n===================\n\nYou can build the example application as a Docker image and run it:\n\n.. code-block:: bash\n\n    $ docker build -t connexion-example .\n    $ docker run -d -p 8080:8080 connexion-example\n    $ ./test.sh # do some test HTTP requests\n\n\nUsing OAuth2 Security\n=====================\n\nTo enable OAuth2 security (token verification), you need to pass the URL to the \"tokeninfo\" endpoint:\n\n.. code-block:: bash\n\n    $ docker run -d -p 8080:8080 -e HTTP_TOKENINFO_URL=https://auth.example.org/tokeninfo connexion-example\n\nUsing Connexion with a WSGI container\n=====================================\n\nYou can use the Flask WSGI app with any WSGI container, e.g. `using Flask with uWSGI`_:\n\n.. code-block:: bash\n\n    $ sudo pip3 install uwsgi\n    $ uwsgi --http :8080 -w app\n\nYou can run uwsgi with a large number of worker processes to get high concurrency.\nThis obviously makes no sense for the in-memory pet store example (every worker would have its own pet store dictionary):\n\n.. code-block:: bash\n\n    $ uwsgi --http :8080 -w app -p 16  # use 16 worker processes\n\nSee the `uWSGI documentation`_ for more information.\n\n.. _Connexion: https://pypi.python.org/pypi/connexion\n.. _Flask: http://flask.pocoo.org/\n.. _Swagger 2.0 Specification: https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md\n.. _/ui/: http://localhost:8080/ui/\n.. _using Flask with uWSGI: http://flask.pocoo.org/docs/latest/deploying/uwsgi/\n.. _uWSGI documentation: https://uwsgi-docs.readthedocs.org/\n.. _Connexion Example with Redis database and Kubernetes deployment manifests: https://github.com/hjacobs/connexion-example-redis-kubernetes\n"
  },
  {
    "path": "app.py",
    "content": "#!/usr/bin/env python3\nimport connexion\nimport datetime\nimport logging\n\nfrom connexion import NoContent\n\n# our memory-only pet storage\nPETS = {}\n\n\ndef get_pets(limit, animal_type=None):\n    return {\"pets\": [pet for pet in PETS.values() if not animal_type or pet['animal_type'] == animal_type][:limit]}\n\n\ndef get_pet(pet_id):\n    pet = PETS.get(pet_id)\n    return pet or ('Not found', 404)\n\n\ndef put_pet(pet_id, pet):\n    exists = pet_id in PETS\n    pet['id'] = pet_id\n    if exists:\n        logging.info('Updating pet %s..', pet_id)\n        PETS[pet_id].update(pet)\n    else:\n        logging.info('Creating pet %s..', pet_id)\n        pet['created'] = datetime.datetime.utcnow()\n        PETS[pet_id] = pet\n    return NoContent, (200 if exists else 201)\n\n\ndef delete_pet(pet_id):\n    if pet_id in PETS:\n        logging.info('Deleting pet %s..', pet_id)\n        del PETS[pet_id]\n        return NoContent, 204\n    else:\n        return NoContent, 404\n\n\nlogging.basicConfig(level=logging.INFO)\napp = connexion.App(__name__)\napp.add_api('swagger.yaml')\n# set the WSGI application callable to allow using uWSGI:\n# uwsgi --http :8080 -w app\napplication = app.app\n\nif __name__ == '__main__':\n    # run our standalone gevent server\n    app.run(port=8080, server='gevent')\n"
  },
  {
    "path": "swagger.yaml",
    "content": "swagger: '2.0'\ninfo:\n  title: Pet Shop Example API\n  version: \"0.1\"\n  description: Simple example API to store and retrieve pets\nconsumes:\n  - application/json\nproduces:\n  - application/json\nsecurity:\n  # enable OAuth protection for all REST endpoints\n  # (only active if the TOKENINFO_URL environment variable is set)\n  - oauth2: [uid]\npaths:\n  /pets:\n    get:\n      tags: [Pets]\n      operationId: app.get_pets\n      summary: Get all pets\n      parameters:\n        - name: animal_type\n          in: query\n          type: string\n          pattern: \"^[a-zA-Z0-9]*$\"\n        - name: limit\n          in: query\n          type: integer\n          format: int32\n          minimum: 0\n          default: 100\n      responses:\n        200:\n          description: Return pets\n          schema:\n            type: object\n            properties:\n              pets:\n                type: array\n                items:\n                  $ref: '#/definitions/Pet'\n  /pets/{pet_id}:\n    get:\n      tags: [Pets]\n      operationId: app.get_pet\n      summary: Get a single pet\n      parameters:\n        - $ref: '#/parameters/pet_id'\n      responses:\n        200:\n          description: Return pet\n          schema:\n            $ref: '#/definitions/Pet'\n        404:\n          description: Pet does not exist\n    put:\n      tags: [Pets]\n      operationId: app.put_pet\n      summary: Create or update a pet\n      parameters:\n        - $ref: '#/parameters/pet_id'\n        - name: pet\n          in: body\n          schema:\n            $ref: '#/definitions/Pet'\n      responses:\n        200:\n          description: Pet updated\n        201:\n          description: New pet created\n    delete:\n      tags: [Pets]\n      operationId: app.delete_pet\n      summary: Remove a pet\n      parameters:\n        - $ref: '#/parameters/pet_id'\n      responses:\n        204:\n          description: Pet was deleted\n        404:\n          description: Pet does not exist\n\n\nparameters:\n  pet_id:\n    name: pet_id\n    description: Pet's Unique identifier\n    in: path\n    type: string\n    required: true\n    pattern: \"^[a-zA-Z0-9-]+$\"\n\ndefinitions:\n  Pet:\n    type: object\n    required:\n      - name\n      - animal_type\n    properties:\n      id:\n        type: string\n        description: Unique identifier\n        example: \"123\"\n        readOnly: true\n      name:\n        type: string\n        description: Pet's name\n        example: \"Susie\"\n        minLength: 1\n        maxLength: 100\n      animal_type:\n        type: string\n        description: Kind of animal\n        example: \"cat\"\n        minLength: 1\n      tags:\n        type: object\n        description: Custom tags\n      created:\n        type: string\n        format: date-time\n        description: Creation time\n        example: \"2015-07-07T15:49:51.230+02:00\"\n        readOnly: true\n\n\nsecurityDefinitions:\n  oauth2:\n    type: oauth2\n    flow: implicit\n    authorizationUrl: https://example.com/oauth2/dialog\n    scopes:\n      uid: Unique identifier of the user accessing the service.\n"
  },
  {
    "path": "test.sh",
    "content": "#!/bin/bash\n\nHTTP=$(which http)\n\nif [ ! -x \"$HTTP\" ]; then\n    echo 'You need HTTPie to run this script!'\n    echo 'sudo pip3 install httpie'\n    exit 1\nfi\n\nURL=:8080\n\nset -x\n\nhttp PUT $URL/pets/1 name=foo animal_type=test\nhttp $URL/pets/1\nhttp PUT $URL/pets/1 name=foo animal_type=test tags:='{\"color\": \"brown\"}'\nhttp $URL/pets/1\nhttp $URL/pets animal_type==test\nhttp DELETE $URL/pets/1\n"
  }
]