Skip to content

Latest commit

 

History

History
190 lines (121 loc) · 4.98 KB

File metadata and controls

190 lines (121 loc) · 4.98 KB

Controllers

The Controller is the heart of Endpoints. Every request will go through a controller class.

Create your first controller class

Create a file named controllers.py with the following contents:

from endpoints import Controller

class Hello(Controller):
    async def GET(self):
        return "hello world"

Now you can make a request:

$ curl http://localhost:8000/hello
"hello world"

Now let's try some different stuff:

$ curl http://localhost:8000/hello -d "name=Alice"
{"errno": 501, "errmsg": "POST /hello not implemented"}

We received a 501 response because our Hello controller has no POST method, let's add one:

from endpoints import Controller

class Hello(Controller):
    async def GET(self):
        return "hello world"

    async def POST(self, name: str):
        return "hello {}".format(name)

Let's see if it worked:

$ curl http://localhost:8000/hello -d "name=Alice"
"hello Alice"

Handling path parameters and query vars

You can define your controller methods to accept certain path params and to accept query params:

class Foo(Controller):
  async def GET(self, one, two=None, **params): pass
  async def POST(self, **params): pass

your call requests would be translated like this:

HTTP Request Path Followed
GET /foo/one controllers.Default.GET()
GET /foo/one?param1=val1&param2=val2 controllers.Foo.GET("one", param1="val1", param2="val2")
GET /foo 405, no one path param to pass to GET
GET /foo/one/two controllers.Foo.GET("one", "two")

Post requests are also merged with the **params on the controller method, with the POST params taking precedence:

For example, if the HTTP request is:

POST /foo?param1=GET1&param2=GET2 with body: param1=POST1&param3=val3

The following path would be:

prefix.Foo.POST(param1="POST1", param2="GET2", param3="val3")

CORS support

Every Endpoints Controller can activate Cors support. This support will handle all the OPTION requests, and setting all the appropriate headers, so you don't have to worry about them (unless you want to).

from endpoints import Controller, CORSMixin

class Default(Controller, CORSMixin):
  async def GET(self):
    return "This will have CORS support"

Default Controllers

If a suitable controller can't be found using the path then Endpoints will default to a Controller class named Default.

For example:

# controllers.py

from endpoints import Controller

class Default(Controller):
	async def GET(self, *args, **kwargs):
		return "GET {}".format("/".join(args))
	
	async def POST(self, *args, **kwargs):
		return "POST {}".format("/".join(args))

The request:

POST /foo/bar

would be handled by controllers.Default and return:

POST foo/bar

This makes it possible for you to define your paths in multiple different ways, for example:

#controllers.py

from endpoints import Controller

class User(Controller):
	async def GET(self): pass

could be equivalent to:

# controllers/user.py

from endpoints import Controller

class Default(Controller):
	async def GET(self): pass

Endpoints first checks module paths, then it checks classes in the found module, then defaults to the Default class if no other suitable class is found.

Another Example

Imagine a folder structure like this:

controllers/
  __init__.py
  foo.py

With controllers/__init__.py having content:

from endpoints import Controller

class Default(Controller):
    async def GET(self, *args, **kwargs):
        pass

And controllers/foo.py having content:

from endpoints import Controller

class Default(Controller):
    async def GET(self, *args, **kwargs):
        pass

class Bar(Controller):
    async def GET(self, *args, **kwargs):
        pass
        
    async def POST(self, *args, **kwargs):
        pass

Below are how the HTTP requests would be interpreted using endpoints using controllers as the prefix.

HTTP Request Path Followed
GET / controllers.Default.GET()
GET /foo controllers.foo.Default.GET()
POST /foo/bar controllers.foo.Bar.POST()
GET /foo/bar/che controllers.foo.Bar.GET(che)
GET /foo/bar/che?baz=foo controllers.foo.Bar.GET(che, baz=foo)
POST /foo/bar/che with body: baz=foo controllers.foo.Bar.POST(che, baz=foo)