📜 ⬆️ ⬇️

Full-featured REST API for perfectionists in 5 minutes



Hi, Habr! My name is Vladimir, I'm 28 years old and I'm a drug addict. My drug is simplicity. I got addicted to simplicity because of my perfectionism, which I was awarded at birth.

Doctors say that it is interconnected, they say perfectionism is the pursuit of perfection, and simplicity allows you to get close to this mythical perfection. The simpler the solution, the fewer mistakes you can make, so I am hooked. I did not argue with them and instead of looking for the perpetrators of my story, I decided to live with it and try to improve the quality of this very life.
')
The world around is not perfect, it’s incredibly difficult to do a complicated thing, so everything is overly complicated. People like to feel like professionals, so they operate with complex terms when this is not necessary, because they feel their importance and fill the void that was formed because of the fear of lost time.

You can complicate everything: you / you / you
Why should I constantly remember whether I spoke with this person or not? Have we switched to you? I am writing some kind of commercial offer and I need to "Vyknut" or is it an answer to an ordinary letter and a rather simple "you". Why do I constantly have to get upset when a completely unfamiliar person starts to “poke” me from the doorway, as if I am his friend from the smoking room?

I basically “vykayut” all with a small letter and I am convinced that this has its price. Surely there are people who do not like that they were called with a small letter and they will not respond to my letter.

So why these difficulties?

When I mentioned improving the quality of life, I meant some rules that help to make quick decisions and not regret it. For example, I do not use complex things all the time, I do not communicate with people who like to complicate things. If the thing you use every day is complicated, it only means that you didn’t pay enough attention to it. If a person cannot explain to you even a difficult topic to understand in simple language, it means that he himself does not fully understand what he is talking about.

There is something else that is equally important - time. Time is an invaluable resource, and the expression “Time is money” from the mouth of smart people makes me smile with disappointment ( you look like an idiot and feel the same way ). I still do not know a single billionaire who was helped by money to live longer than other people.

Introduction


It's about a tool that allows you to build a complete and easy-to-use REST API in the minimum amount of time. It is called - Python Eve .

Unfortunately, there are many instructions on the Internet on this topic, but they are all misleading. Beginner developers, after reading such articles, think that the REST API is GET / POST / PUT / DELETE . Customers think that this is a matter of a couple of hours. And when they meet together, magic happens in the form of Express.js / Mongoose / Passport and a lot of rubbish that flows and sometimes blocks the event-loop. All this is started with the help of some supervisor , because sometimes it falls and you need to somehow restart.

And everything would be fine, but yesterday I had a conversation with a habr-user who suggested using " Express.js, MongoDB, Mongoose, Passport, WebStorm debugger and head on shoulders ". Similar conversations happened often, so I decided to write this article and “send” a link to it.

Full REST API?


This includes not only the implementation of the architectural style of the REST API , but also the HTTP protocol , validation and caching , and HATEOAS ( wikipedia ), which, it seems, they generally prefer not to recall. Then we will need to filter the results and sort , page by page navigation and partially update the records. Then we think about data integrity and conditional queries . Surely we need authentication , maybe we want to display the data not only in JSON, but also in XML . This is about the versioning and nested entries, I did not mention. Then, as is usually the case, some # $% $% ^ will begin to hammer into our powerful API with a heavy query and we will need to limit the frequency of requests .

Even if we imagine that an incredibly cool developer with 3 monitors, a WebStorm debugger and a head on his shoulders will be engaged in developing such an API, he will spend not only a lot of time, but a lot of it. Support of the code base will be costly, and the introduction of new functions will be long.



But we love simplicity with you, and we respect time. So let's get started!

Installation


This is a regular python package, so it is installed in the standard way:

$ pip install eve 

If you are interested in alternative installation methods, you can look at the official documentation .

Fast start


Before we begin to “create” magic, we need a MongoDB database. If you do not have it, you can use any free service, for example MongoLab . Registration will take no more than a minute. After registration, create a database and user for this database.

Now let's write the minimum version of our REST API . First, create the main run.py file with the following contents:

 from eve import Eve app = Eve() if __name__ == '__main__': app.run() 

Now we need to create the settings.py file:

 #  user, password, ds049945.mongolab.com, example      . MONGO_URI = "mongodb://user:password@ds049945.mongolab.com:49945/example" #   Eve  API   "read-only" (..   GET ), #     POST, PUT, PATCH, DELETE. RESOURCE_METHODS = ['GET', 'POST', 'DELETE'] ITEM_METHODS = ['GET', 'PATCH', 'PUT', 'DELETE'] DOMAIN = { #   `/users` 'users': { #     .     Cerberus   Eve. #          http://docs.python-cerberus.org/en/stable/. #       EVE http://python-eve.org/validation.html#validation. 'schema': { 'username': { 'type': 'string', 'minlength': 5, 'maxlength': 32, 'required': True, #   (  ,     ) 'unique': True, }, 'firstname': { 'type': 'string', 'minlength': 1, 'maxlength': 10, 'required': True, }, 'lastname': { 'type': 'string', 'minlength': 1, 'maxlength': 15, 'required': True, }, 'role': { 'type': 'list', # :  'allowed': ["author", "contributor"], #   : "author", "contributor" }, 'location': { 'type': 'dict', # :  #  ""  'schema': { 'address': {'type': 'string'}, 'city': {'type': 'string'} }, }, 'born': { 'type': 'datetime', }, 'active': { 'type': 'boolean', 'default': True } } }, #   `/groups` 'groups': { #    (. ). 'schema': { 'title': { 'type': 'string', 'minlength': 5, 'maxlength': 32, 'required': True, 'unique': True }, 'users': { 'type': 'list', # :  'default': [], #  :   #  ""  'schema': { 'type': 'objectid', #  : objectid #       'data_relation': { 'resource': 'users', #   `users` (   ) 'field': '_id', #   `_id` 'embeddable': True } } } } } } 

In my opinion, everything is quite simple here and there should be no questions. If this is not the case - welcome to the comments. A complete list of configuration options can be found in the documentation .

Everything is ready, run:

 $ python3.5 run.py * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit) 


Prelude


You have already thought that now we will start to curse godlessly, but I have to disappoint you. We, with peculiar perfectionism, will use the tool of the author, who has a sense of beauty:


The tool is called HTTPie and put in one click one command:

 $ pip install httpie 

Games and fun


HTTPie is called with the " http " command. In order to send a GET request to our API , execute:

 $ http http://0.0.0.0:5000/ HTTP/1.0 200 OK Content-Length: 99 Content-Type: application/json Date: Sun, 07 Feb 2016 18:13:33 GMT Server: Eve/0.6.1 Werkzeug/0.10.4 Python/3.5.0 { "_links": { "child": [ { "href": "users", "title": "users" }, { "href": "groups", "title": "groups" } ] } } 

Thanks to HATEOAS, we see that we have 2 resources: users and groups . Let's look inside:

 » http http://0.0.0.0:5000/users HTTP/1.0 200 OK Content-Length: 166 Content-Type: application/json Date: Sun, 07 Feb 2016 18:20:41 GMT Server: Eve/0.6.1 Werkzeug/0.10.4 Python/3.5.0 X-Total-Count: 0 { "_items": [], "_links": { "parent": { "href": "/", "title": "home" }, "self": { "href": "users", "title": "users" } }, "_meta": { "max_results": 25, "page": 1, "total": 0 } } 

Let's create the user johndoe :

 $ http http://0.0.0.0:5000/users username=johndoe HTTP/1.0 422 UNPROCESSABLE ENTITY Content-Length: 184 Content-Type: application/json Date: Sun, 07 Feb 2016 18:22:44 GMT Server: Eve/0.6.1 Werkzeug/0.10.4 Python/3.5.0 { "_error": { "code": 422, "message": "Insertion failure: 1 document(s) contain(s) error(s)" }, "_issues": { "firstname": "required field", "lastname": "required field" }, "_status": "ERR" } 

The first thing you should pay attention to is our team:

 $ http http://0.0.0.0:5000/users username=johndoe 

HTTPie saw that we send the username parameter and turned it into JSON :

 { "username": "johndoe" } 

Then sent to our API using the POST method. Let's pay attention to errors:

 "_issues": { "firstname": "required field", "lastname": "required field" } 

We immediately see the entire list of validation errors, and this is great. Correct them and rerun the query:

 $ http http://0.0.0.0:5000/users username=johndoe firstname=John lastname=Doe HTTP/1.0 201 CREATED Content-Length: 276 Content-Type: application/json Date: Sun, 07 Feb 2016 18:34:42 GMT Server: Eve/0.6.1 Werkzeug/0.10.4 Python/3.5.0 { "_created": "Sun, 07 Feb 2016 18:34:41 GMT", "_etag": "24509359443095dd05dece6d0eb7d98cce70b076", "_id": "56b78e41cf7b35255aa5a1e6", "_links": { "self": { "href": "users/56b78e41cf7b35255aa5a1e6", "title": "User" } }, "_status": "OK", "_updated": "Sun, 07 Feb 2016 18:34:41 GMT" } 

Well, we have just successfully created a new user. Let's check this:

 $ http http://0.0.0.0:5000/users HTTP/1.0 200 OK Content-Length: 504 Content-Type: application/json Date: Sun, 07 Feb 2016 18:36:00 GMT Last-Modified: Sun, 07 Feb 2016 18:34:41 GMT Server: Eve/0.6.1 Werkzeug/0.10.4 Python/3.5.0 X-Total-Count: 1 { "_items": [ { "_created": "Sun, 07 Feb 2016 18:34:41 GMT", "_etag": "24509359443095dd05dece6d0eb7d98cce70b076", "_id": "56b78e41cf7b35255aa5a1e6", "_links": { "self": { "href": "users/56b78e41cf7b35255aa5a1e6", "title": "User" } }, "_updated": "Sun, 07 Feb 2016 18:34:41 GMT", "active": true, "firstname": "John", "lastname": "Doe", "username": "johndoe" } ], "_links": { "parent": { "href": "/", "title": "home" }, "self": { "href": "users", "title": "users" } }, "_meta": { "max_results": 25, "page": 1, "total": 1 } } 

There is no doubt that this is so. It's time to try to overwrite ( note, not edit, and overwrite ) the user. This is done using the PUT method, which must be explicitly specified ( if not specified, POST will be performed ):

 $ http put http://0.0.0.0:5000/users/56b78e41cf7b35255aa5a1e6 username=janedoe firstname="Jane" lastname="Doe" HTTP/1.0 403 FORBIDDEN Content-Length: 101 Content-Type: application/json Date: Sun, 07 Feb 2016 18:43:04 GMT Server: Eve/0.6.1 Werkzeug/0.10.4 Python/3.5.0 { "_error": { "code": 403, "message": "An etag must be provided to edit a document" }, "_status": "ERR" } 

Oops, mistake. I mentioned data integrity above . The fact is that a situation may occur in which someone has already changed the record that you want to change. And when you edit it, you will think that you have changed one record, but in fact it is already completely different.

In order for us not to be in such a situation, the ETag identifier is used . In a nutshell, this is a unique identifier that is generated by Eve with each change of record. Using this identifier, we can tell our API that we only want to change the record of a certain version and if it has been edited since then, our changes will not be made. This is done using a conditional request with the HTTP header " If-Match ":

 $ http put http://0.0.0.0:5000/users/56b78e41cf7b35255aa5a1e6 "If-Match":"24509359443095dd05dece6d0eb7d98cce70b076" username=janedoe firstname="Jane" lastname="Doe" HTTP/1.0 200 OK Content-Length: 276 Content-Type: application/json Date: Sun, 07 Feb 2016 18:46:56 GMT ETag: 0138d193174528c205827ba9af25b7b8fb93940e Last-Modified: Sun, 07 Feb 2016 18:46:56 GMT Server: Eve/0.6.1 Werkzeug/0.10.4 Python/3.5.0 { "_created": "Sun, 07 Feb 2016 18:34:41 GMT", "_etag": "0138d193174528c205827ba9af25b7b8fb93940e", "_id": "56b78e41cf7b35255aa5a1e6", "_links": { "self": { "href": "users/56b78e41cf7b35255aa5a1e6", "title": "User" } }, "_status": "OK", "_updated": "Sun, 07 Feb 2016 18:46:56 GMT" } 

Notice how we passed the HTTPie HTTPie header. This is not the only thing for which the ETag identifier and conditional queries can be used. I will not dwell on this here, but I advise you to familiarize yourself with this topic, if you have not done it yet.

It's time to create a new group. To begin, let's try to create a group with a nonexistent user:

 $ http http://0.0.0.0:5000/groups title="Friends" users:='["56b77466cf7b352414deb451"]' HTTP/1.0 422 UNPROCESSABLE ENTITY Content-Length: 220 Content-Type: application/json Date: Sun, 07 Feb 2016 19:14:31 GMT Server: Eve/0.6.1 Werkzeug/0.10.4 Python/3.5.0 { "_error": { "code": 422, "message": "Insertion failure: 1 document(s) contain(s) error(s)" }, "_issues": { "users": { "0": "value '56b77466cf7b352414deb451' must exist in resource 'users', field '_id'." } }, "_status": "ERR" } 

And indeed, a user with such _id does not exist. Notice how we pass the list of users:

 users:='["56b77466cf7b352414deb451"]' 

You can read more in the official documentation for the HTTPie, which is as good as the tool itself.

This time we will indicate the correct _id :

 » http http://0.0.0.0:5000/groups title="Friends" users:='["56b78e41cf7b35255aa5a1e6"]' HTTP/1.0 201 CREATED Content-Length: 278 Content-Type: application/json Date: Sun, 07 Feb 2016 19:21:42 GMT Server: Eve/0.6.1 Werkzeug/0.10.4 Python/3.5.0 { "_created": "Sun, 07 Feb 2016 19:21:41 GMT", "_etag": "c6fc02a0bd4bae92a1310be0748ff8bc971ff209", "_id": "56b79945cf7b35255aa5a1e7", "_links": { "self": { "href": "groups/56b79945cf7b35255aa5a1e7", "title": "Group" } }, "_status": "OK", "_updated": "Sun, 07 Feb 2016 19:21:41 GMT" } 

"Truth is good," as my great-grandmother used to say. Check:

 $ http http://0.0.0.0:5000/groups HTTP/1.0 200 OK Content-Length: 488 Content-Type: application/json Date: Sun, 07 Feb 2016 19:24:50 GMT Last-Modified: Sun, 07 Feb 2016 19:21:41 GMT Server: Eve/0.6.1 Werkzeug/0.10.4 Python/3.5.0 X-Total-Count: 1 { "_items": [ { "_created": "Sun, 07 Feb 2016 19:21:41 GMT", "_etag": "c6fc02a0bd4bae92a1310be0748ff8bc971ff209", "_id": "56b79945cf7b35255aa5a1e7", "_links": { "self": { "href": "groups/56b79945cf7b35255aa5a1e7", "title": "Group" } }, "_updated": "Sun, 07 Feb 2016 19:21:41 GMT", "title": "Friends", "users": [ "56b78e41cf7b35255aa5a1e6" ] } ], "_links": { "parent": { "href": "/", "title": "home" }, "self": { "href": "groups", "title": "groups" } }, "_meta": { "max_results": 25, "page": 1, "total": 1 } } 

Great-grandmother would be right. This could be finished, but we will act differently.

We will get a group with users who are included in it, in expanded form:

 $ http http://0.0.0.0:5000/groups/56b79945cf7b35255aa5a1e7/\?embedded='{"users":1}' HTTP/1.0 200 OK Content-Length: 646 Content-Type: application/json Date: Sun, 07 Feb 2016 19:38:27 GMT ETag: c6fc02a0bd4bae92a1310be0748ff8bc971ff209 Last-Modified: Sun, 07 Feb 2016 19:21:41 GMT Server: Eve/0.6.1 Werkzeug/0.10.4 Python/3.5.0 { "_created": "Sun, 07 Feb 2016 19:21:41 GMT", "_etag": "c6fc02a0bd4bae92a1310be0748ff8bc971ff209", "_id": "56b79945cf7b35255aa5a1e7", "_links": { "collection": { "href": "groups", "title": "groups" }, "parent": { "href": "/", "title": "home" }, "self": { "href": "groups/56b79945cf7b35255aa5a1e7", "title": "Group" } }, "_updated": "Sun, 07 Feb 2016 19:21:41 GMT", "title": "Friends", "users": [ { "_created": "Sun, 07 Feb 2016 18:34:41 GMT", "_etag": "0138d193174528c205827ba9af25b7b8fb93940e", "_id": "56b78e41cf7b35255aa5a1e6", "_updated": "Sun, 07 Feb 2016 18:46:56 GMT", "active": true, "firstname": "Jane", "lastname": "Doe", "username": "janedoe" } ] } 

Ask for the same in XML :

 $ http http://0.0.0.0:5000/groups/56b79945cf7b35255aa5a1e7/\?embedded='{"users":1}' "Accept":"application/xml" HTTP/1.0 200 OK Content-Length: 690 Content-Type: application/xml; charset=utf-8 Date: Sun, 07 Feb 2016 19:43:36 GMT ETag: c6fc02a0bd4bae92a1310be0748ff8bc971ff209 Last-Modified: Sun, 07 Feb 2016 19:21:41 GMT Server: Eve/0.6.1 Werkzeug/0.10.4 Python/3.5.0 <resource href="groups/56b79945cf7b35255aa5a1e7" title="Group"> <link href="groups" rel="collection" title="groups" /> <link href="/" rel="parent" title="home" /> <_created>Sun, 07 Feb 2016 19:21:41 GMT</_created> <_etag>c6fc02a0bd4bae92a1310be0748ff8bc971ff209</_etag> <_id>56b79945cf7b35255aa5a1e7</_id> <_updated>Sun, 07 Feb 2016 19:21:41 GMT</_updated> <title>Friends</title> <users> <_created>Sun, 07 Feb 2016 18:34:41 GMT</_created> <_etag>0138d193174528c205827ba9af25b7b8fb93940e</_etag> <_id>56b78e41cf7b35255aa5a1e6</_id> <_updated>Sun, 07 Feb 2016 18:46:56 GMT</_updated> <active>True</active> <firstname>Jane</firstname> <lastname>Doe</lastname> <username>janedoe</username> </users> </resource> 

Let's try to change only the name of our user ( without full rewriting ). To do this, use the HTTP method PATCH :

 $ http patch http://0.0.0.0:5000/users/56b78e41cf7b35255aa5a1e6 firstname=John "If-Match":"0138d193174528c205827ba9af25b7b8fb93940e" HTTP/1.0 200 OK Content-Length: 276 Content-Type: application/json Date: Sun, 07 Feb 2016 19:46:48 GMT ETag: 86f3495cf1d6edf301e25563099844bd816c5a3c Server: Eve/0.6.1 Werkzeug/0.10.4 Python/3.5.0 { "_created": "Sun, 07 Feb 2016 18:34:41 GMT", "_etag": "86f3495cf1d6edf301e25563099844bd816c5a3c", "_id": "56b78e41cf7b35255aa5a1e6", "_links": { "self": { "href": "users/56b78e41cf7b35255aa5a1e6", "title": "User" } }, "_status": "OK", "_updated": "Sun, 07 Feb 2016 19:46:47 GMT" } 

What would grandma say?

 » http http://0.0.0.0:5000/users/56b78e41cf7b35255aa5a1e6 HTTP/1.0 200 OK Content-Length: 431 Content-Type: application/json Date: Sun, 07 Feb 2016 19:50:06 GMT ETag: 86f3495cf1d6edf301e25563099844bd816c5a3c Last-Modified: Sun, 07 Feb 2016 19:46:47 GMT Server: Eve/0.6.1 Werkzeug/0.10.4 Python/3.5.0 { "_created": "Sun, 07 Feb 2016 18:34:41 GMT", "_etag": "86f3495cf1d6edf301e25563099844bd816c5a3c", "_id": "56b78e41cf7b35255aa5a1e6", "_links": { "collection": { "href": "users", "title": "users" }, "parent": { "href": "/", "title": "home" }, "self": { "href": "users/56b78e41cf7b35255aa5a1e6", "title": "User" } }, "_updated": "Sun, 07 Feb 2016 19:46:47 GMT", "active": true, "firstname": "John", "lastname": "Doe", "username": "janedoe" } 

"Barring good." I liked it so much that I would create users in batches:

 $ echo '[{"username": "userone", "firstname": "First", "lastname":"Last"},{"username":"usertwo", "firstname":"First", "lastname":"Last"}]' | http http://0.0.0.0:5000/users HTTP/1.0 201 CREATED Content-Length: 585 Content-Type: application/json Date: Sun, 07 Feb 2016 20:01:33 GMT Server: Eve/0.6.1 Werkzeug/0.10.4 Python/3.5.0 { "_items": [ { "_created": "Sun, 07 Feb 2016 20:01:33 GMT", "_etag": "6f397b570ef12769d372c902fa6149bb7e9eaf89", "_id": "56b7a29dcf7b35255aa5a1e8", "_links": { "self": { "href": "users/56b7a29dcf7b35255aa5a1e8", "title": "User" } }, "_status": "OK", "_updated": "Sun, 07 Feb 2016 20:01:33 GMT" }, { "_created": "Sun, 07 Feb 2016 20:01:33 GMT", "_etag": "378f30b37724139c213a85079185226ab2b209f3", "_id": "56b7a29dcf7b35255aa5a1e9", "_links": { "self": { "href": "users/56b7a29dcf7b35255aa5a1e9", "title": "User" } }, "_status": "OK", "_updated": "Sun, 07 Feb 2016 20:01:33 GMT" } ], "_status": "OK" } 

Find the user " John Doe " by his name:

 $ http http://0.0.0.0:5000/users\?where='{"firstname":"John"}' HTTP/1.0 200 OK Content-Length: 535 Content-Type: application/json Date: Sun, 07 Feb 2016 20:05:28 GMT Last-Modified: Sun, 07 Feb 2016 19:46:47 GMT Server: Eve/0.6.1 Werkzeug/0.10.4 Python/3.5.0 X-Total-Count: 1 { "_items": [ { "_created": "Sun, 07 Feb 2016 18:34:41 GMT", "_etag": "86f3495cf1d6edf301e25563099844bd816c5a3c", "_id": "56b78e41cf7b35255aa5a1e6", "_links": { "self": { "href": "users/56b78e41cf7b35255aa5a1e6", "title": "User" } }, "_updated": "Sun, 07 Feb 2016 19:46:47 GMT", "active": true, "firstname": "John", "lastname": "Doe", "username": "janedoe" } ], "_links": { "parent": { "href": "/", "title": "home" }, "self": { "href": "users?where={\"firstname\":\"John\"}", "title": "users" } }, "_meta": { "max_results": 25, "page": 1, "total": 1 } } 

We sort the users by their login in the reverse order:

 $ http http://0.0.0.0:5000/users\?sort\=-username HTTP/1.0 200 OK Content-Length: 1203 Content-Type: application/json Date: Sun, 07 Feb 2016 20:08:08 GMT Last-Modified: Sun, 07 Feb 2016 20:01:33 GMT Server: Eve/0.6.1 Werkzeug/0.10.4 Python/3.5.0 X-Total-Count: 3 { "_items": [ { "_created": "Sun, 07 Feb 2016 20:01:33 GMT", "_etag": "378f30b37724139c213a85079185226ab2b209f3", "_id": "56b7a29dcf7b35255aa5a1e9", "_links": { "self": { "href": "users/56b7a29dcf7b35255aa5a1e9", "title": "User" } }, "_updated": "Sun, 07 Feb 2016 20:01:33 GMT", "active": true, "firstname": "First", "lastname": "Last", "username": "usertwo" }, { "_created": "Sun, 07 Feb 2016 20:01:33 GMT", "_etag": "6f397b570ef12769d372c902fa6149bb7e9eaf89", "_id": "56b7a29dcf7b35255aa5a1e8", "_links": { "self": { "href": "users/56b7a29dcf7b35255aa5a1e8", "title": "User" } }, "_updated": "Sun, 07 Feb 2016 20:01:33 GMT", "active": true, "firstname": "First", "lastname": "Last", "username": "userone" }, { "_created": "Sun, 07 Feb 2016 18:34:41 GMT", "_etag": "86f3495cf1d6edf301e25563099844bd816c5a3c", "_id": "56b78e41cf7b35255aa5a1e6", "_links": { "self": { "href": "users/56b78e41cf7b35255aa5a1e6", "title": "User" } }, "_updated": "Sun, 07 Feb 2016 19:46:47 GMT", "active": true, "firstname": "John", "lastname": "Doe", "username": "janedoe" } ], "_links": { "parent": { "href": "/", "title": "home" }, "self": { "href": "users?sort=-username", "title": "users" } }, "_meta": { "max_results": 25, "page": 1, "total": 3 } } 

Well, finally remove all users:

 $ http delete http://0.0.0.0:5000/users HTTP/1.0 204 NO CONTENT Content-Length: 0 Content-Type: application/json Date: Sun, 07 Feb 2016 20:10:06 GMT Server: Eve/0.6.1 Werkzeug/0.10.4 Python/3.5.0 

I would not include this feature in production . This is indicated in the RESOURCE_METHODS parameter ( remove from the DELETE list ):

 RESOURCE_METHODS = ['GET', 'POST', 'DELETE'] 

Conclusion


We did not consider all the features of Eve, but even taking this into account, we received a complete version of the REST API .

In this article I wanted to draw attention to the fact that a real RESTful service is much more than a couple of modules for Node.js and in most cases there is no need to develop such things from scratch, and even more so to write articles on how to do it in one hour. Just look at the history of the project , to once again make sure that a couple of hours / days / weeks is not enough even for a good team.

Nicola Iarocci , the author of Eve , has created an excellent tool for quickly deploying the REST API , has given it enough attention and retained its ease of use.

Links



Follow me on Twitter , I talk about working in a startup, my mistakes and the right decisions, about python and everything related to web development.

PS I'm looking for developers to the company, the details in my profile .

Source: https://habr.com/ru/post/276731/


All Articles