Examples

Resources

#    Copyright 2011-2014 Codernity (http://codernity.com)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


from functools import wraps
import time

import colander

from CodernityREST.router_ex import ResourceRouter, ExceptionMap


class BaseSchema(colander.MappingSchema):
    pass


class SmallEchoSchema(BaseSchema):
    echo_int = colander.SchemaNode(colander.Int())
    echo_str = colander.SchemaNode(colander.String())


class EchoSchema(SmallEchoSchema):

    @colander.instantiate()
    class others(colander.SequenceSchema):
        data = colander.SchemaNode(colander.String())


class SomeException(Exception):
    pass


class ApiClose(Exception):
    pass


def check_time(f):
    @wraps(f)
    def _inner(req, resp, *args, **kwargs):
        if time.time() % 86400 > 41818:
            raise ApiClose()

        return f(req, resp, *args, **kwargs)

    return _inner


def echo(req, resp, echo_int, echo_str, others):
    """Returns request data with custom option from router"""
    return {
        'echo_int': echo_int,
        'echo_str': echo_str,
        'others': others,
        'custom_option': req.opts.get('custom_option', None)
    }


def echo_re(req, resp, echo_int, echo_str):
    """Returns request data with custom option from router"""
    return {
        'echo_int': echo_int,
        'echo_str': echo_str,
    }


def h(req, resp):
    return


def raise_exception(req, resp):
    """Raises exception which will be catched and mapped to 409 error"""
    raise SomeException()


def get_routes():
    """Returns list of ResourceRouters"""

    routes = []

    r = ResourceRouter('/')
    r.add_str('GET', '/echo', echo, validator=(9, EchoSchema()))
    r.add_str('POST', '/echo', echo, validator=(9, EchoSchema()))
    r.add_re('GET',
             r'/echo/(?P<echo_int>[-]?[0-9]+)/(?P<echo_str>\w+)', echo_re,
             validator=(9, SmallEchoSchema()))
    r.add_str('GET', '/raise', raise_exception)

    ex_map = ExceptionMap()
    ex_map.add(SomeException, 409, 'Some message')
    r.set_ex_map(ex_map)
    routes.append(r)

    # 9 and 10 numbers are validator/decorator priorities
    r_check = ResourceRouter('/check', dec=((10, check_time), ),
                             custom_option='Hello')
    r_check.add_str('POST', '/echo', echo, validator=(9, EchoSchema()))
    r_check.add_str('PUT', '/echo', echo, validator=(9, EchoSchema()))
    r_check.add_str('DELETE', '/echo', echo, validator=(9, EchoSchema()))
    r_check.add_str('HEAD', '/echo', echo, validator=(9, EchoSchema()))
    ex_map = ExceptionMap()
    ex_map.add(ApiClose, 503)
    r_check.set_ex_map(ex_map)
    routes.append(r_check)

    return routes
#    Copyright 2011-2014 Codernity (http://codernity.com)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


from CodernityREST.router_ex import R


def hello(req, resp):
    return req.opts


def get_routes():

    with R('/with', a=1) as r:
        with r('/a', a=2):
            r.s('GET', '/', hello)

            with r('/b', b=3):
                r.s('GET', '/', hello)

                with r('/c', a=3, b=4):
                    r.s('GET', '/', hello)
        r.s('GET', '/', hello)

    return r

Outputs

  • GET method

    $ http :3007/echo echo_int=5 echo_str="test" others:='["other var"]'
    
    HTTP/1.1 200 OK
    Connection: close
    Content-Length: 76
    Content-Type: application/json
    
    {
        "custom_option": null,
        "echo_int": 5,
        "echo_str": "test",
        "others": [
            "other var"
        ]
    }
    
  • POST method

    $ http post :3007/echo echo_int:=5 echo_str=test others:='["other var"]'
    
    HTTP/1.1 200 OK
    Connection: close
    Content-Length: 76
    Content-Type: application/json
    
    {
        "custom_option": null,
        "echo_int": 5,
        "echo_str": "test",
        "others": [
            "other var"
        ]
    }
    
  • Validation error

    $ http :3007/echo
    
    HTTP/1.1 450 Invalid schema
    Connection: close
    Content-Length: 65
    Content-Type: application/json
    
    {
        "echo_int": "Required",
        "echo_str": "Required",
        "others": "Required"
    }
    
  • POST method with decorator

    • If decorator wants to return 503 response no validation is done, because of priorities

      $ http post :3007/check/echo
      HTTP/1.1 503 Service Unavailable
      Connection: close
      Content-Length: 21
      Content-Type: application/json
      
      "Service Unavailable"
      
    • Otherwise

      $ http post :3007/auth/echo echo_int:=5 echo_str=test others:='["other var"]'
      
      HTTP/1.1 200 OK
      Connection: close
      Content-Length: 79
      Content-Type: application/json
      
      {
          "custom_option": "Hello",
          "echo_int": 5,
          "echo_str": "test",
          "others": [
              "other var"
          ]
      }
      
  • Mapped exception

    $ http :3007/raise
    
    HTTP/1.1 409 Conflict
    Connection: close
    Content-Length: 14
    Content-Type: application/json
    
    "Some message"