Extended Guide¶
Welcome to the interest’s extended guide. We will try to cover all framework aspects. If you’re interested in concrete topic use left menu to pick it.
under development
Terminology¶
Flow model¶
Routing¶
Logging¶
Testing¶
Debugging¶
Serving static¶
Template engines¶
Database integration¶
Putting all together¶
We’ll put all features together to the example:
# server.py
import json
import asyncio
import logging
from interest import Service, Middleware, http
from interest import Logger, Handler, Router, Parser, Provider, Endpoint
class Restful(Middleware):
# Public
@asyncio.coroutine
def process(self, request):
try:
response = http.Response()
payload = yield from self.next(request)
except http.Exception as exception:
response = exception
payload = {'message': str(response)}
response.text = json.dumps(payload)
response.content_type = 'application/json'
return response
class Session(Middleware):
# Public
@asyncio.coroutine
def process(self, request):
assert self.main == self.service.over
assert self.over == self.service
assert self.prev == self.service['restful']
assert self.next == self.service['comment']['read'].over
request.user = False
response = yield from self.next(request)
return response
class MyEndpoint(Endpoint):
# Public
@asyncio.coroutine
def __call__(self, request):
for header in self.extra.get('headers', []):
if header not in request.headers:
return (yield from self.next(request))
return (yield from super().__call__(request))
class Auth(Middleware):
# Public
METHODS = ['POST']
@asyncio.coroutine
def process(self, request):
assert self.service.match(request, root='/api/v1')
assert self.service.match(request, path=request.path)
assert self.service.match(request, methods=['POST'])
if not request.user:
raise http.Unauthorized()
response = yield from self.next(request)
return response
class Comment(Middleware):
# Public
PREFIX = '/comment'
ENDPOINT = MyEndpoint
MIDDLEWARES = [Auth]
@http.get('/key=<key:myint>')
def read(self, request, key):
url = '/api/v1/comment/key=' + str(key)
assert url == self.service.url('comment.read', key=key)
assert url == self.service.url('read', base=self, key=key)
return {'key': key}
@http.put
@http.post # Auth
def upsert(self, request):
self.service.log('info', 'Adding custom header!')
raise http.Created(headers={'endpoint': 'upsert'})
@http.delete(headers=['ACCEPT'])
def delete(self, request):
assert self.service.db == '<connection>'
raise http.Forbidden()
class Database(Provider):
# Public
@asyncio.coroutine
def provide(self, service):
self.service.db = '<connection>'
# Create restful service
restful = Service(
prefix='/api/v1',
middlewares=[Restful, Session, Comment],
providers=[Database],
router=Router.config(
parsers={'myint': Parser.config(
pattern=r'[1-9]+', convert=int)}))
# Create main service
service = Service(
logger=Logger.config(
template='%(request)s | %(status)s | %(<endpoint:res>)s'),
handler=Handler.config(
connection_timeout=25, request_timeout=5))
# Add restful to main
service.push(restful)
# Listen forever with logging
logging.basicConfig(level=logging.DEBUG)
service.listen(host='127.0.0.1', port=9000, override=True, forever=True)
Run the server in the terminal and use another to interact:
$ python3 server.py
INFO:interest:Start listening host="127.0.0.1" port="9000"
... <see log here> ...
$ curl -X GET http://127.0.0.1:9000/api/v1/comment/key=1; echo
{"key": 1}
$ curl -X PUT http://127.0.0.1:9000/api/v1/comment; echo
{"message": "Created"}
$ curl -X POST http://127.0.0.1:9000/api/v1/comment; echo
{"message": "Unauthorized"}