REST API framework designed for human beings

Overview

Eve

https://img.shields.io/pypi/v/eve.svg?style=flat-square https://img.shields.io/travis/pyeve/eve.svg?branch=master&style=flat-square https://img.shields.io/pypi/pyversions/eve.svg?style=flat-square https://img.shields.io/badge/license-BSD-blue.svg?style=flat-square

Eve is an open source Python REST API framework designed for human beings. It allows to effortlessly build and deploy highly customizable, fully featured RESTful Web Services. Eve offers native support for MongoDB, and SQL backends via community extensions.

Eve is Simple

from eve import Eve

app = Eve()
app.run()

The API is now live, ready to be consumed:

$ curl -i http://example.com/people
HTTP/1.1 200 OK

All you need to bring your API online is a database, a configuration file (defaults to settings.py) and a launch script. Overall, you will find that configuring and fine-tuning your API is a very simple process.

Check out the Eve Website

Features

  • Emphasis on REST
  • Full range of CRUD operations
  • Customizable resource endpoints
  • Customizable, multiple item endpoints
  • Filtering and Sorting
  • Pagination
  • HATEOAS
  • JSON and XML Rendering
  • Conditional Requests
  • Data Integrity and Concurrency Control
  • Bulk Inserts
  • Data Validation
  • Extensible Data Validation
  • Resource-level Cache Control
  • API Versioning
  • Document Versioning
  • Authentication
  • CORS Cross-Origin Resource Sharing
  • JSONP
  • Read-only by default
  • Default Values
  • Predefined Database Filters
  • Projections
  • Embedded Resource Serialization
  • Event Hooks
  • Rate Limiting
  • Custom ID Fields
  • File Storage
  • GeoJSON
  • Internal Resources
  • Enhanced Logging
  • Operations Log
  • MongoDB Aggregation Framework
  • MongoDB and SQL Support
  • Powered by Flask

Funding

Eve REST framework is a open source, collaboratively funded project. If you run a business and are using Eve in a revenue-generating product, it would make business sense to sponsor Eve development: it ensures the project that your product relies on stays healthy and actively maintained. Individual users are also welcome to make a recurring pledge or a one time donation if Eve has helped you in your work or personal projects.

Every single sign-up makes a significant impact towards making Eve possible. To learn more, check out our funding page.

License

Eve is a Nicola Iarocci open source project, distributed under the BSD license.

Comments
  • Versioned Documents

    Versioned Documents

    Hey @nicolaiarocci, I'm trying to find a way to leverage Eve to create versioned documents. This feature might end up being a standalone extension, but I thought I'd start an "issue" here so that there was a recording of the conversion.

    I'd like to extend the common pattern of /resource/ and /resource/_id_/ endpoints with /resource/_id_/versions/ and /resource/_id_/versions/_version_/. I'd like to implement versioning by storing shadow copies of a model as opposed to storing the changes between versions. In my intended application, I'll actually be referencing / retrieving a specific version of a resource resource often than I would retrieve the latest version of a resource. Only GET methods would be allowed on the two additional version endpoints, and a PATCH/UPDATE to /resource/_id_/ would also insert a new shadow copy.

    I originally liked the idea of storing shadow copies within the object itself, but storing the copies as separate documents in a separate collection probably lends itself better to the MongoDB document size limit Your support for sub-modules lends itself well to storing the shadow copies in a second collection. I think I would then make use of the hooks to automatically write to the shadow collection on update. Could you give me an example of how to write to a different resource from inside of a hook other then the resource in request? I don't see an example of this in the event hooks documentation.

    Once the shadow copies are actually stored in the database, the next step is to support a versioned document reference. I guess I'd have to create a custom data type for this and then extend the validation rules.

    I'd like to use this versioned resource pattern for many (if not all) of the models in my database. I'd likely create a reusable function to generate the required configuration bits for me. However, it would be pretty darn sweet if all i had to do was flip a "version_controlled" flag in the resource configuration... :)

    What do you think? Any suggestions on how to implement something like this?

    Thanks!

    feature request planned 
    opened by joshvillbrandt 53
  • DELETE on a versioned item should (probably optionally) not delete archived versions.

    DELETE on a versioned item should (probably optionally) not delete archived versions.

    In my app, the reason I'm wanting to keep versioned documents in the first place is for auditing purposes. Without going into too much detail, events occur in our system, and we process those events according to a constantly-evolving set of rules that are defined in a MongoDB collection that is managed via an Eve API (if I have my wish). "Evolving" means that individual rules are frequently updated but also occasionally DELETED. When a rule is applied to an event, we record it (e.g. "Rule X, version N, was applied.") Later, if anything erroneous is found to have happened, we can go look at exactly how the rule was defined at the time. This currently breaks with DELETE, though, because deletion results in removal of the archived versions of the document, as well.

    The workaround I currently have in mind is to basically have a deleted boolean field, and filter them out by default for that resource. This is clunky because it means that deletion would be done with PATCH/PUT and it just leaves the primary collection cluttered. IMO, there needs to be a way to support DELETE on the resource items while still preserving the auditability.

    The behavior I would expect is that if item X is deleted, /resource/X would result in a 404, but that /resource/X?version=N would still work. Clearly, though, there's plenty of room for interpretation as to what the right semantics would be, so I haven't done any work on this. I'm just throwing it up here for consideration for the time being.

    enhancement 
    opened by mikenerone 33
  • AUTH_FIELD should be configured so that a user can query for his/her user document

    AUTH_FIELD should be configured so that a user can query for his/her user document

    Take a look at this documentation: http://python-eve.org/authentication.html#user-restricted

    Right now, it suggests:

    AUTH_FIELD = 'user_id'
    

    and

    class BCryptAuth(BasicAuth):
        def check_auth():
            ...
            self.user_id = account['_Id']
            return ...
    

    There are a few problems here. First, this update is required:

    if account and '_id' in account:
         self.user_id = account['_id']
    

    Second, if you want a user to be able to query his/her own user object...

    • /users/ should return a list with a single user
    • /users/<_id> should return a single user

    ...then the AUTH_FIELD property needs to be a property that the user object has. That's why I would suggest implementing the following change:

    • ensure that the user schema has a user_id field, and updating the self.user_id = account['_id'] line to self.user_id = account['user_id']

    (EDIT: I had another suggestion, but then I realized that it doesn't actually work)

    documentation 
    opened by shea256 28
  • Prevent the creation of admins/superusers with Token Authentication

    Prevent the creation of admins/superusers with Token Authentication

    On the account management page (http://python-eve.org/tutorials/account_management.html), under "Accounts with Token Authentication", it seems like a malicious user can just create an admin or superuser through the "/accounts/" endpoint, which would be troublesome.

    Shouldn't the "/accounts/" endpoint be secured so that accounts that are created only have the "user" role? Then, an existing admin or superuser can just manually go into the database and update a newly created user so that he/she has the admin or superuser role.

    I might be missing something, so if that is the case please let me know.

    opened by shea256 28
  • Resource-specific auth fields are broken

    Resource-specific auth fields are broken

    Updates:

    1. Location: line 287 of base.py getattr(self.app.auth, auth_field) ==> self.app.auth.user_id

    2. Location: line 114 of post.py getattr(app.auth, auth_field) ==> app.auth.user_id

    The reason:

    In auth.py, self.user_id is hard_coded:

    def __init__(self):
        self.user_id = None
    

    With curr_req_auth_value = getattr(self.app.auth, auth_field), resource-specified auth_field's will not work.

    (NOTE: put.py is already correct)

    enhancement planned 
    opened by shea256 27
  • Update the naming system for event hooks to be more robust

    Update the naming system for event hooks to be more robust

    The downside of the current naming system for Eve's event hooks is that a resource can never be named "items", or else problems will arise.

    A more robust naming scheme would be something like this:

    "on_getting_resource" "on_getting_resource_%s" % resource "on_getting_item" "on_getting_item_%s" % item_title

    enhancement planned wip 
    opened by shea256 21
  • Fix for database concurrency issues.

    Fix for database concurrency issues.

    Ensure we handle database concurrency in case there are concurrent accesses to the database that modify the same objects. The current implementation will ensure "_etag" is consistent and retry the PUT/PATCH operation if not.

    The diff is messy as there's been a lot of indented lines, but in a nutshell the PUT/PATCH operations are surrounded by a while True loop that's continued if there's a mid-air collision, otherwise the loop carries on in execution and either throws or returns.

    There was a suggested use of find_and_modify(), but I couldn't find a solution using this function beside the use of etag that would allow us not to modify the database if there was indeed a collision. I also noted when I tried this solution that there was somehow date mismatches between what find_and_modify() returns and the original document which would cause comparisons to fail (some would be offset-aware while other wouldn't).

    Let me know what you think.

    enhancement 
    opened by kapouille 18
  • Why do the POST and PUT endpoints take in multiple documents? I'd suggest changing this.

    Why do the POST and PUT endpoints take in multiple documents? I'd suggest changing this.

    Currently, the POST and PUT endpoints require the following format:

    single object:

    POST /user
    {
    "user1": { "email": "[email protected]", "password": "iRock"}
    }
    

    multiple objects:

    {
    "user1": { "email": "[email protected]", "password": "iRock"},
    "user2": { "email": "[email protected]", "password": "madskillz"},
    }
    

    This seems quite strange to me, as every API that I've worked with up to this point asks for the API user to specify a single object when posting (Facebook, [Instagram](Instagram also expects single documents to be posted: http://instagram.com/developer/endpoints/comments/), Twitter etc.).

    From http://stackoverflow.com/questions/411462/restful-way-to-create-multiple-items-in-one-request:

    Although Bulk operations (batch create) are essential in many systems, [they are] not formally addressed by the RESTful architecture style.

    From http://stackoverflow.com/a/1081601/1530754:

    This is what it might look like: POST /user fname=John&lname=Doe&age=25 The server responds: 200 OK Location: /user/123

    From http://stackoverflow.com/questions/7172784/how-to-post-json-data-with-curl-from-terminal-commandline-to-test-spring-rest:

    curl -X POST -H "Content-Type: application/json" -d '{"username":"xyz","password":"xyz"}' http://localhost:3000/api/login

    AngularJS posts a single object like this as well.

    I'd like to POST or PUT an object like so:

    POST /user
    { "email": "[email protected]", "password": "iRock"}
    
    enhancement planned 
    opened by shea256 18
  • If-Modified-Since GET on collection returns incorrect 304 after item deletion

    If-Modified-Since GET on collection returns incorrect 304 after item deletion

    • Have collection of more than one item
    • Make request to collection index and make note of time T
    • Delete 1 item
    • Make request to collection index with If-Modified-Since of time T
    • Observe resulting HTTP 304

    This is very similar to Bug #243, except that the collection is not empty afterwards.

    In the short term, can you suggest a way to ignore If-Modified-Since headers on requests to collections?

    bug 
    opened by leth 17
  • build_defaults: argument of type 'bool' is not iterable

    build_defaults: argument of type 'bool' is not iterable

    While updating my Eve app to test #331, I started getting the following error:

    [Mon May 12 05:15:21 2014] [error] [client 10.1.41.216]   File "/usr/local/lib/python2.7/dist-packages/Eve-0.4_dev-py2.7.egg/eve/flaskapp.py", line 151, in __init__
    [Mon May 12 05:15:21 2014] [error] [client 10.1.41.216]     self.register_resource(resource, settings)
    [Mon May 12 05:15:21 2014] [error] [client 10.1.41.216]   File "/usr/local/lib/python2.7/dist-packages/Eve-0.4_dev-py2.7.egg/eve/flaskapp.py", line 699, in register_resource
    [Mon May 12 05:15:21 2014] [error] [client 10.1.41.216]     self._set_resource_defaults(resource, settings)
    [Mon May 12 05:15:21 2014] [error] [client 10.1.41.216]   File "/usr/local/lib/python2.7/dist-packages/Eve-0.4_dev-py2.7.egg/eve/flaskapp.py", line 545, in _set_resource_defaults
    [Mon May 12 05:15:21 2014] [error] [client 10.1.41.216]     settings['defaults'] = build_defaults(schema)
    [Mon May 12 05:15:21 2014] [error] [client 10.1.41.216]   File "/usr/local/lib/python2.7/dist-packages/Eve-0.4_dev-py2.7.egg/eve/default_values.py", line 39, in build_defaults
    [Mon May 12 05:15:21 2014] [error] [client 10.1.41.216]     if 'default' in value:
    [Mon May 12 05:15:21 2014] [error] [client 10.1.41.216] TypeError: argument of type 'bool' is not iterable
    

    This seems to be related to #327. The build_defaults() function is expecting something to be iterable, but it isn't in my resource schema. I haven't been able to track down in the last fifteen minutes. My best guess is that the function is chocking on my custom validator triggers (which should be valid syntax.) Any ideas, @nicolaiarocci / @graffic?

    By the way, I know Eve has a change log, but it'd be really nice to start a migration guide... My app has broken more than once when updating to a new version and it always requires lots of a manual digging. A migration guide could really help with that.

    bug 
    opened by joshvillbrandt 17
  • use flask blueprint for eve app

    use flask blueprint for eve app

    It will be more convenient for composing eve app with existing flask app if eve app is a blueprint. Current eve flask app can be just a thin wrapper of the eve blueprint.

    for example:

    class EveBlueprint(Blueprint):
       pass
    
    class Eve(Flask):
       register_blueprint(EveBlueprint)
    
    opened by ilovenwd 17
  • etag generation fails if 'uuidRepresentation' is not set in MONGO_OPTIONS

    etag generation fails if 'uuidRepresentation' is not set in MONGO_OPTIONS

    This issue tracker is a tool to address bugs in Eve itself. Please use Stack Overflow for general questions about using Eve or issues not related to Eve (see http://python-eve.org/support).

    If you'd like to report a bug in Eve, fill out the template below. Provide any any extra information that may be useful / related to your problem. Ideally, create an MCVE, which helps us understand the problem and helps check that it is not caused by something in your code.


    Expected Behavior

    When uuidRepresentation is not set in MONGO_OPTIONS generating etags should still be possible.

    
    -- app.py
    my_settings = {
        'MONGO_HOST': 'localhost',
        'MONGO_PORT': 27017,
        'MONGO_DBNAME': 'the_db_name',
        'DOMAIN': {'contacts': {}}
    }
    
    app = Eve(settings=my_settings)
    app.run()
    
    
    -- some_test.py
    from eve import post_internal
    post_internal('contacts', {'a_valid_contact': 'this must be'}, skip_validation=True)
    

    Actual Behavior

    Since no uuidRepresentation is present in MONGO_OPTIONS, the default option is selected, which is an int, not a string. A simple fix would be changing line 350 in eve/utils.py from config.MONGO_OPTIONS.get("uuidRepresentation", UuidRepresentation.STANDARD) to config.MONGO_OPTIONS.get("uuidRepresentation", "standard")

    or add a field 4 to the uuid_map on line 343:

    uuid_map = {
                "standard": UuidRepresentation.STANDARD,
                4: UuidRepresentation.STANDARD,
                "unspecified": UuidRepresentation.UNSPECIFIED,
                "pythonLegacy": UuidRepresentation.PYTHON_LEGACY,
                "csharpLegacy": UuidRepresentation.CSHARP_LEGACY,
                "javaLegacy": UuidRepresentation.JAVA_LEGACY,
            }
    
        def uuid_representation_as_string():
            uuid_map = {
                "standard": UuidRepresentation.STANDARD,
                "unspecified": UuidRepresentation.UNSPECIFIED,
                "pythonLegacy": UuidRepresentation.PYTHON_LEGACY,
                "csharpLegacy": UuidRepresentation.CSHARP_LEGACY,
                "javaLegacy": UuidRepresentation.JAVA_LEGACY,
            }
    >       return uuid_map[
                config.MONGO_OPTIONS.get("uuidRepresentation", UuidRepresentation.STANDARD)
            ]
    E       KeyError: 4
    

    Environment

    • Python version: 3.9.2
    • Eve version: 2.0.1
    opened by tgm-git 1
  • Tests fail with Flask 2.2

    Tests fail with Flask 2.2

    Since Flask 2.2, all tests relying on app.add_url_rule are failing. Flask changelogfor v2.2 reports significant changes.

    For the time being, I'm pinning Flask dependency to <2.2.

    Anybody willing to take up this task?

    opened by nicolaiarocci 2
  • deleteitem_internal on media resource, KeyError: 'media'

    deleteitem_internal on media resource, KeyError: 'media'

    Environment

    • Python version: Python 3.9.2
    • Eve version: Eve==2.0

    EXTENDED_MEDIA_INFO = ['content_type', 'name', 'length'] RETURN_MEDIA_AS_BASE64_STRING = False RETURN_MEDIA_AS_URL = True MEDIA_ENDPOINT = 'media'

    I'm trying to delete files on the media endpoint, with deleteitem_internal, but apparently deleteitem_internal does not consider the media endpoint when is enabled, the same could be happening for other internal methods. It will also be valuable if when deleting an item from media (with deleteitem_internal), related items in the fs.files and fs.chunks collections are also deleted

    Example:

    fs.files:

    _id: 62fa8c38f4c4954b8fef7e71 filename: "pic.jpg" contentType: "image/jpg" chunkSize: 261120 length: 48640 uploadDate: 2022-08-15T18:11:04.278+00:00

    fs.chunks: _id: 62fa8c38f4c4954b8fef7e72 files_id :62fa8c38f4c4954b8fef7e71 n: 0 data: BinData(0, '/9j/4AAQSkZJRgABAgAAAQABAAD//gAQTGF2YzU4LjkxLjEwMAD/2wBDAAgKCgsKCw0NDQ0NDRAPEBAQEBAQEBAQEBASEhIVFRUS…')

    media_lookup = {'_id': 62fa8c38f4c4954b8fef7e71 } deleteitem_internal('media', concurrency_check=False, suppress_callbacks=True, original=None, **media_lookup)

    File "/home/trz/pushpull/lib/python3.9/site-packages/eve/methods/delete.py", line 99, in deleteitem_internal resource_def = config.DOMAIN[resource] KeyError: 'media'

    same error is triggered when trying : deleteitem_internal('fs.files', concurrency_check=False, suppress_callbacks=True, original=None, **media_lookup)

    Regards

    opened by zaterio 0
  • MongoDB auth related issue in MONGO_URI

    MongoDB auth related issue in MONGO_URI

    Actual Behavior

    MONGO_URI's username, password, and authSource in uri are not parsed correctly

    https://github.com/pyeve/eve/blob/master/eve/io/mongo/flask_pymongo.py#L76
    

    It uses dbname as authSource, but the authSource should be parsed from options https://pymongo.readthedocs.io/en/stable/api/pymongo/uri_parser.html#pymongo.uri_parser.parse_uri

    See URI format https://www.mongodb.com/docs/manual/reference/connection-string/

    Environment

    • Python version: 3.10
    • Eve version: 2.0

    I am willing to open a PR to resolve the issue. Thanks

    opened by smeng9 10
  • 422 UNPROCESSABLE ENTITY when using user_id and data_relation on PATCH

    422 UNPROCESSABLE ENTITY when using user_id and data_relation on PATCH

    Expected Behavior: 200 OK

    Actual Behavior: 422 UNPROCESSABLE ENTITY

    If using set_request_auth_value on a schema and having defined a data_relation to a schema that is not using any auth value, a PATCH operation will fail with the follwoing error:

    value 'XXX' must exist in resource 'YYY', field '_id'
    

    POST works fine.

    The only workaround is not to define any data_relation.

    According to my research, the _filter variable contains the user_id in an $and condition when PATCH but not on POST.

    https://github.com/pyeve/eve/blob/c62941992b2f66fa02b822581891bd7c18e76d9c/eve/io/mongo/mongo.py#L335

    Environment

    • Python version: 3.8.10
    • Eve version: 1.1.5
    opened by xibriz 0
Owner
eve
REST API framework designed for human beings
eve
Endpoints is a lightweight REST api framework written in python and used in multiple production systems that handle millions of requests daily.

Endpoints Quickest API builder in the West! Endpoints is a lightweight REST api framework written in python and used in multiple production systems th

Jay Marcyes 30 Mar 5, 2022
FPS, fast pluggable server, is a framework designed to compose and run a web-server based on plugins.

FPS, fast pluggable server, is a framework designed to compose and run a web-server based on plugins. It is based on top of fastAPI, uvicorn, typer, and pluggy.

Adrien Delsalle 1 Nov 16, 2021
The no-nonsense, minimalist REST and app backend framework for Python developers, with a focus on reliability, correctness, and performance at scale.

The Falcon Web Framework Falcon is a reliable, high-performance Python web framework for building large-scale app backends and microservices. It encou

Falconry 8.9k Nov 21, 2022
Django Ninja - Fast Django REST Framework

Django Ninja is a web framework for building APIs with Django and Python 3.6+ type hints.

Vitaliy Kucheryaviy 3.7k Nov 23, 2022
Goblet is an easy-to-use framework that enables developers to quickly spin up fully featured REST APIs with python on GCP

GOBLET Goblet is a framework for writing serverless rest apis in python in google cloud. It allows you to quickly create and deploy python apis backed

Austen 72 Nov 2, 2022
An alternative serializer implementation for REST framework written in cython built for speed.

drf-turbo An alternative serializer implementation for REST framework written in cython built for speed. Free software: MIT license Documentation: htt

Mng 75 Oct 14, 2022
A Flask API REST to access words' definition

A Flask API to access words' definitions

Pablo Emídio S.S 9 Jul 22, 2022
Pretty tornado wrapper for making lightweight REST API services

CleanAPI Pretty tornado wrapper for making lightweight REST API services Installation: pip install cleanapi Example: Project folders structure: . ├──

Vladimir Kirievskiy 26 Sep 11, 2022
Free & open source Rest API for YTDislike

RestAPI Free & open source Rest API for YTDislike, read docs.ytdislike.com for implementing. Todo Add websockets Installation Git clone git clone http

null 1 Nov 25, 2021
Containers And REST APIs Workshop

Containers & REST APIs Workshop Containers vs Virtual Machines Ferramentas Podman: https://podman.io/ Docker: https://www.docker.com/ IBM CLI: https:/

Vanderlei Munhoz 8 Dec 16, 2021
Pyrin is an application framework built on top of Flask micro-framework to make life easier for developers who want to develop an enterprise application using Flask

Pyrin A rich, fast, performant and easy to use application framework to build apps using Flask on top of it. Pyrin is an application framework built o

Mohamad Nobakht 10 Jan 25, 2022
Asita is a web application framework for python based on express-js framework.

Asita is a web application framework for python. It is designed to be easy to use and be more easy for javascript users to use python frameworks because it is based on express-js framework.

Mattéo 4 Nov 16, 2021
Restful API framework wrapped around MongoEngine

Flask-MongoRest A Restful API framework wrapped around MongoEngine. Setup from flask import Flask from flask_mongoengine import MongoEngine from flask

Close 526 Nov 8, 2022
Fully featured framework for fast, easy and documented API development with Flask

Flask RestPlus IMPORTANT NOTICE: This project has been forked to Flask-RESTX and will be maintained by by the python-restx organization. Flask-RESTPlu

Axel H. 2.7k Nov 22, 2022
Flask-Potion is a RESTful API framework for Flask and SQLAlchemy, Peewee or MongoEngine

Flask-Potion Description Flask-Potion is a powerful Flask extension for building RESTful JSON APIs. Potion features include validation, model resource

DTU Biosustain 491 Oct 23, 2022
Restful API framework wrapped around MongoEngine

Flask-MongoRest A Restful API framework wrapped around MongoEngine. Setup from flask import Flask from flask_mongoengine import MongoEngine from flask

Close 505 Feb 11, 2021
Fully featured framework for fast, easy and documented API development with Flask

Flask RestPlus IMPORTANT NOTICE: This project has been forked to Flask-RESTX and will be maintained by by the python-restx organization. Flask-RESTPlu

Axel H. 2.5k Feb 17, 2021
Flask-Potion is a RESTful API framework for Flask and SQLAlchemy, Peewee or MongoEngine

Flask-Potion Description Flask-Potion is a powerful Flask extension for building RESTful JSON APIs. Potion features include validation, model resource

DTU Biosustain 484 Feb 3, 2021
Lemon is an async and lightweight API framework for python

Lemon is an async and lightweight API framework for python . Inspired by Koa and Sanic .

Joway 29 Nov 20, 2022