Git Product home page Git Product logo

roll's Introduction

Let’s roll.

Philosophy

Async, simple, fast: pick three! Roll is a pico framework with performances and aesthetic in mind.

Documentation

Check out the latest documentation for an extended overview of what can and cannot be achieved.

roll's People

Contributors

davidbgk avatar dependabot-preview[bot] avatar dependabot[bot] avatar ioo avatar magopian avatar trollfot avatar vinyll avatar ydrasil avatar yohanboniface avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

roll's Issues

Allow websockets 8.0.2

Can you create a new release of roll which supports websockets 8.0.2?

I just installed it and in my simple tests, it works, so it might be enough to relax the version constraint to >=7,<9

Document how to handle views in multiple different python files?

Hi (hope you're doing great !), and thanks for the project, love it so far :-) I'm trying to find a way to split the views in different python files, but as the views are all relying on the app, I'm not sure how to do it.

In the Flask project, they're using an intermediate concept named Blueprints for this, and I believe what I'm looking for seems similar.

Did you already face this issue? Any idea on how do deal with this? Thanks !

url_for `already exist` errors when using decorators

When you use decorators (not using native functools.wrap or wrapt lib) before routes, you get the following error:

ValueError: Route with name wrapper already exists: foo.wrapper

Either we document that all decorators must use an explicit way of definition or we force to name every route or something else.

404 missing from logger

I think it's from 7655d0e

Not sure why we moved the request hook after the dispatching.
Was it to have request.route set before?

Catch HttpParserInvalidMethodError

Jul 06 05:59:49 slz025 Trefle[26087]: Unhandled exception in event loop
Jul 06 05:59:49 slz025 Trefle[26087]: Traceback (most recent call last):
Jul 06 05:59:49 slz025 Trefle[26087]:   File "/srv/trefle/venv/lib/python3.6/site-packages/roll/__init__.py", line 420, in data_received
Jul 06 05:59:49 slz025 Trefle[26087]:     self.parser.feed_data(data)
Jul 06 05:59:49 slz025 Trefle[26087]:   File "httptools/parser/parser.pyx", line 193, in httptools.parser.parser.HttpParser.feed_data
Jul 06 05:59:49 slz025 Trefle[26087]: httptools.parser.errors.HttpParserInvalidMethodError: invalid HTTP method
Jul 06 05:59:49 slz025 Trefle[26087]: During handling of the above exception, another exception occurred:
Jul 06 05:59:49 slz025 Trefle[26087]: Traceback (most recent call last):
Jul 06 05:59:49 slz025 Trefle[26087]:   File "uvloop/handles/stream.pyx", line 784, in uvloop.loop.__uv_stream_on_read_impl
Jul 06 05:59:49 slz025 Trefle[26087]:   File "uvloop/handles/stream.pyx", line 563, in uvloop.loop.UVStream._on_read
Jul 06 05:59:49 slz025 Trefle[26087]:   File "/srv/trefle/venv/lib/python3.6/site-packages/roll/__init__.py", line 437, in data_received
Jul 06 05:59:49 slz025 Trefle[26087]:     self.write()
Jul 06 05:59:49 slz025 Trefle[26087]:   File "/srv/trefle/venv/lib/python3.6/site-packages/roll/__init__.py", line 509, in write
Jul 06 05:59:49 slz025 Trefle[26087]:     self.request.method in self._BODYLESS_METHODS))
Jul 06 05:59:49 slz025 Trefle[26087]: AttributeError: method

For the record, we have some funny players in the access_logs:

185.222.211.18 - - [06/Jul/2018:19:03:07 +0000] "\x03\x00\x00/*\xE0\x00\x00\x00\x00\x00Cookie: mstshash=Administr" 400 182 "-" "-"
112.66.78.59 - - [06/Jul/2018:23:35:56 +0000] "\x01\x00\x00\x00\x01\x00\x00\x00\x08\x08" 400 182 "-" "-"
46.161.9.31 - - [07/Jul/2018:12:27:08 +0000] "\x05\x01\x00" 400 182 "-" "-"
46.161.9.31 - - [07/Jul/2018:12:30:09 +0000] "\x04\x01\x00P.\xA1\x09\x1F\x00" 400 182 "-" "-"
185.224.134.205 - - [07/Jul/2018:01:59:46 +0000] "SSH-2.0-libssh2_1.7.0" 400 182 "-" "-"
46.165.243.209 - - [07/Jul/2018:03:55:40 +0000] "\x16\x03\x01\x00\xCF\x01\x00\x00\xCB\x03\x03\xB6/\xBFs\x06C\x92\xC9\x8B\x87\xBB\xE1\x0F\xC9\x8F\x9E\x092\x1D\xD5F\xFB\xD1\x06\x93\xC2;L\xBC\xDE\x8F\xDE\x00\x00\x5C\xC0,\xC00\xC0+\xC0/\xCC\xA9\xCC\xA8\x00\xA3\x00\x9F\x00\xA2\x00\x9E\xCC\xAA\xC0\xAF\xC0\xAD\xC0$\xC0(\xC0" 400 182 "-" "-"
123.127.189.9 - - [06/Jul/2018:05:59:50 +0000] "\x16\x03\x01\x02\x00\x01\x00\x01\xFC\x03\x03\x98x#\xBF%\x9A&0\xA2\x056\xE1.$\x09\x03\x88\xCEN\xC5\x84\xDA\xA1\x012P\xD1\x93#\xFE}\xBD\x00\x00\xB2\x00\x05\x00\x04\x00\x02\x00\x01\x00\x16\x003\x009\x00:\x00\x18\x005\x00" 400 182 "-" "-"
123.127.189.9 - - [06/Jul/2018:05:59:56 +0000] "LMTJ / HTTP/1.1" 499 0 "-" "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)"
123.127.189.9 - - [06/Jul/2018:05:59:57 +0000] "\x16\x03\x01\x02\x00\x01\x00\x01\xFC\x03\x03\xDCk\x14T\xFB\x10\x9D\xFFHd4L\xF8\x7F\xD1\x16\x89\xD2\x9Ee\xA2\xE2\x15\xA3[\x9F\x8B\x03\xBC\x1D\x9B\xAD\x00\x00\xB2\x00\x05\x00\x04\x00\x02\x00\x01\x00\x16\x003\x009\x00:\x00\x18\x005\x00" 400 182 "-" "-"
123.127.189.9 - - [06/Jul/2018:05:59:59 +0000] "\x16\x03\x01\x02\x00\x01\x00\x01\xFC\x03\x03x\xFFZo\xBB\xB2-\x1C\x8C\xF9o\x0B0eUg\xD6\xDD\x8C\xB2*\x98\xE7\x91\x7F\xBB\x1Ee\x83 \xB0z\x00\x00\xB2\x00\x05\x00\x04\x00\x02\x00\x01\x00\x16\x003\x009\x00:\x00\x18\x005\x00" 400 182 "-" "-"
66.240.205.34 - - [05/Jul/2018:08:19:46 +0000] "Gh0st\xAD\x00\x00\x00\xE0\x00\x00\x00x\x9CKS``\x98\xC3\xC0\xC0\xC0\x06\xC4\x8C@\xBCQ\x96\x81\x81\x09H\x07\xA7\x16\x95e&\xA7*\x04$&g+\x182\x94\
xF6\xB000\xAC\xA8rc\x00\x01\x11\xA0\x82\x1F\x5C`&\x83\xC7K7\x86\x19\xE5n\x0C9\x95n\x0C;\x84\x0F3\xAC\xE8sch\xA8^\xCF4'J\x97\xA9\x82\xE30\xC3\x91h]&\x90\xF8\xCE\x97S\xCBA4L?2=\xE1\xC4\x92\x86
\x0B@\xF5`\x0CT\x1F\xAE\xAF]" 400 182 "-" "-"

View

import inspect
from abc import ABC

class View(ABC):
    pass

def view_methods(cls):
   members = dict(inspect.getmembers(cls, predicate=inspect.isfunction))
   valid_methods = set(members.keys()) & set({'GET', 'POST'})
   for key in valid_methods:
       yield key, members[key]


class Roll:
    ...
    def view(self, path: str, **payload):
        def wrapper(cls):
            for meth, handler in view_methods(cls):
                    payload[meth] = handler
            self.routes.add(path, **payload)
            return cls
        return wrapper

Custom exceptions

We now have a few place where we raise exceptions, we currently only raise built-in exceptions, maybe it's time to have custom ones, easier to catch and understand for Roll users.

cf #136

Access-Control-Allow-Headers wildcard rejected in Firefox

Similarly to #64 the implementation of 'Access-Control-Allow-Headers': '*' does not work on Firefox rejecting with a preflight error.

Example sending Access-Control-Request-Headers: authorization in Firefox:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:3579/user. (Reason: missing token ‘authorization’ in CORS header ‘Access-Control-Allow-Headers’ from CORS preflight channel).[Learn More]

Works as expected on Chromium.
Also works on Firefox when explicitely using cors(app, "*", methods="*", headers=["Authorization"]) instead of headers="*"

url_for and routes defined twice

Sometimes, you want to define two routes for the same handler, for instance:

@app.route("/url")
@app.route("/old-url")
async def handler():

(Think legacy)

In that case, which route to return with url_for? Maybe only the named one? Maybe a regular redirection for the old route is the correct way to do?

websockets

Hello Pyrates,

I forked Roll yesterday and added websockets capabilities based on the "websockets" async package.
It's working quite well. I had to create "liveserver" to test the websockets requests in "real" conditions, as the mock Transport was causing problems. This creates a dependency on 'aiohttp', to use the http client they have (maybe there are alternatives ?).

Is this something you'd be interested in, for the core of Roll, of should I move it all in an extension package ?

Cheers.

Roll on Curio

As a mere curiosity (rightly so), I ported Roll on Curio and named it "Granite".
https://github.com/trollfot/granite
If you're interested, it may have pointers for the actuall asyncio Roll, maybe to take it down a notch and don't use a Protocol but the sockets directly. This provides much more flexiblity, especially what I did on Granite : not read the body on request reception but rather wait to see if the body is useful to extract it.

HTTP/2 support

Hello,

do you plan to add HTTP/2 support to Roll in the future ?

File API for streamed Response ?

I was thinking this morning while working on a project that outputs a lot of CSV that that would be very handy if Response would obey to the file API, so one would do something like:

import csv

@app.route('/')
async def my_view(request, response):
    writer = csv.writer(response)
    writer.writerow(xxxx)

Meaning that at first response.write call, the Response would send the headers and first chunk, and then stream chunks at each later calls.

I remember we did discuss this some time ago, but can't remember the conclusion, so just put here a reminder to either implement this, or explain it would not be a good idea. :)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.