API Reference

Base Application Class

class yhttp.BaseApplication(version=None)
settings = None

Instance of pymlconf.Root as the global configuration instance.

when(func)

Return decorator to registers the func into Application.events by its name.

Currently these hooks are suuported:

  • ready

  • shutdown

  • endresponse

The hook name will be choosed by the func.__name__, so if you need to aware when app.ready is called write something like this:

@app.when
def ready(app):
    ...

@app.when
def shutdown(app):
    ...

@app.when
def endresponse(response):
    ...
hook(name, *a, **kw)

Only way to fire registered hooks.

Hooks can registered by Application.when() with the name.

app.hook('endresponse')

Extra parameters: *a, **kw will be passed to event handlers.

Normally, users no need to call this method.

ready()

Call the ready hook().

You need to call this method before using the instance as the WSGI application.

Typical usage:

from yhttp import Application, text


app = Application()

@app.route()
@text
def get(req):
    return 'Hello World!'

if __name__ != '__main__':
    app.ready()
shutdown()

Call the shutdown hook().

climain(argv=None)

Provide a callable to call as the CLI entry point.

import sys


if __name__ == '__main__':
    sys.exit(app.climain(sys.argv))

You can use this method as the setuptools entry point for Automatic Script Creation

setup.py

from setuptools import setup


setup(
    name='foo',
    ...
    entry_points={
        'console_scripts': [
            'foo = foo:app.climain'
        ]
    }
)

Application Class

class yhttp.Application(version=None)

Bases: BaseApplication

WSGI Web Application.

Instance of this class can be used as a WSGI application.

route(pattern='/', flags=0, verb=None, insert=None)

Return a decorator to register a handler for given regex pattern.

if verb is None then the function name will used instead.

@app.route(r'/.*')
def get(req):
    ...

You can bypass this behavior by passing verb keyword argument:

@app.route(r'/', verb='get')
def somethingelse(req):
    ...

To catch any verb by the handler use *.

@app.route(r'/', verb='*')
def any(req):
    ...

Regular expression groups will be capture and dispatched as the positional arguments of the handler after req:

@app.route(r'/(\\d+)/(\\w*)')
def get(req, id, name):
    ...

This method returns a decorator for handler fucntions. So, you can use it like:

books = app.route(r'/books/(.*)')

@books
def get(req, id):
    ...

@books
def post(req, id):
    ...

See also

Routing

Parameters:
  • pattern – Regular expression to match the request.

  • flags – Regular expression flags. see re.compile().

  • verb – If not given then handler.__name__ will be used to match HTYP verb, Use * to catch all verbs.

  • insert – If not given, route will be appended to the end of the Application.routes. Otherwise it must be an integer indicating the place to insert the new route into Application.routes attribute.

New in version 2.9: insert

staticfile(pattern, filename, **kw)

Register a filename with a regular expression pattern to be served.

app.staticfile('/a.txt', 'physical/path/to/a.txt')

See also

Static Contents

staticdirectory(pattern, directory, default=None, autoindex=True, fallback=None, **kw)

Register a directory with a regular expression pattern.

So the files inside the directory are accessible by their names:

app.staticdirectory('/foo/', 'physical/path/to/foo')

You you can do:

curl localhost:8080/foo/a.txt

See also

Static Contents

Parameters:
  • pattern – Regular expression to match the requests.

  • directory – Static files are here.

  • default – if None, the app.settings.staticdir.default (which default is index.html) will be used as the default document.

  • autoindex – Automatic directory indexing, default True.

  • fallback – if True, the app.settings.staticdir.fallback (which default is index.html) will be used as the fallback document if the requested resource was not found. if str, the value will be used instead of app.settings.staticdir.fallback.

New in version 2.13: The default and fallback keyword arguments.

New in version 3.8: The autoindex keyword argument.

__call__(environ, startresponse)

Actual WSGI Application.

So, will be called on every request.

from yhttp import Application


app = Application()
result = app(environ, start_response)

Checkout the PEP 333 for more info.

Rewrite Class

class yhttp.Rewrite(default=None)

Bases: BaseApplication

Useful to route specific requests to other WSGI application.

New in version 3.2.

import yhttp

root = yhttp.Application()
foo = yhttp.Application()
bar = yhttp.Application()

app = yhttp.Rewrite(default=root)
app.route(r'/foo/?', r'/', foo)
app.route(r'/bar/?(.*)', r'/b/\1', bar)
app.ready()

@root.route()
def get(req):
    return 'root'

@foo.route()
def get(req):
    return 'foo'

@bar.route(r'/b')
def get(req):
    return 'bar'
Parameters:

default – Fallback application.

route(pattern, repl, handler)

Register an application for specific url.

import yhttp

root = yhttp.Application()
foo = yhttp.Application()
bar = yhttp.Application()

app = yhttp.Rewrite(default=root)
app.route(r'/foo/([a-z]+)/(\d+)', r'/books/\2/\1', foo)
# Add other applications
app.ready()

See re.sub() for more info about pattern and repl arguments.

Parameters:
  • pattern – A regex pattern to match the environ['PATH_INFO'].

  • repl – URL Rewrite rule, See re.sub()

  • handler – An instance of yhttp.BaseApplication.

__call__(environ, startresponse)

Find the registred apllication, rewrite and forward the request.

Request Class

class yhttp.Request(app, environ, response)

Represent an HTTP request.

Application.__call__() instantiates this class on each call.

HeadersMask Class

class yhttp.HeadersMask(environ)

A simple proxy over Request.environ.

Useful to get headers by their original name without the HTTP_ prefix, which is the python’s WSGI servers default behavior.

@app.route()
def get(req):
    foo = req.headers['foo']
    bar = req.headers.get('bar')
    if 'baz' in req.headers:
        baz = True

     ...

Response Class

class yhttp.Response(app, environ, startresponse)

Represent the HTTP response.

Which accessible by Request.response inside handlers.

status = '200 Ok'

HTTP Status code

charset = None

Response encoding, None for binary

length = None

Response content length

type = None

Response content type without charset.

contenttype

Response content type incuding charset.

headers = None

An instance of HeaderSet class.

conclude()

Conclude the response.

Calls WSGI start_response callback and encode response body to transfer to the client.

Returns:

response body

startstream()

Start streaming the response.

Transfer data chunk by chunk instead of what conclude() does.

start()

Start the response.

Usualy Application calls this method when response is ready to transfered to user.

HeaderSet Class

class yhttp.HeaderSet(items=None)

A mutable case-insensitive ordered dictionary to keep HTTP headers.

@app.route()
def get(req):
    req.response.headers.add('x-foo', 'a', 'b')
    req.response.headers['x-bar'] = 'bar'
    req.response.headers += ['x-baz: qux']

HTTPStatus Class

class yhttp.HTTPStatus(code, text, keepheaders=False, headers=None, nobody=False)

Base class for all HTTP Exceptions.

Parameters:
  • code – HTTP status code.

  • text – HTTP status text.

  • keepheaders – If set, appliation keeps the Response.headers when exception is occured.

  • headers – Some extra HTTP headers to be added to the Response.headers when exception is raised.

contenttype decorators

yhttp.contenttype(contenttype=None, charset=None, dump=None)

Yield a decorator to set response content type and encoding.

import json

from yhttp import contenttype

@app.route()
@contenttype('application/json', 'utf8', json.dumps)
def get(req):
    return {'foo': 'bar'}

There are ready to use contenttype decorators which can importes from yhttp package, like: json().

You may create your very own content type decorator by calling this function with desired arguments, for example:

invoice = contenttype('application/pdf', None, dump=makeinvoicepdf)

@app.route('/invoices/(\d+)')
@invoice
def get(req, id):
    ...

The json() decorator is created with something like:

json = contenttype('application/json', 'utf8', dump=json.dumps)
Parameters:
  • contenttype – HTTP Content-Type, example: application/json

  • charset – Character set, example: utf8

  • dump – A callable(body) -> body to transform the body to appropriate content type.

Returns:

decorator for HTTP handlers.

yhttp.binary(handler)

Sets the Response.contenttype to application/octet-stream.

Handlers must return bytes when this decorator is used.

from yhttp import binary


@app.route()
@binary
def get(req):
    return b'binarydata'
yhttp.json(handler)

Sets the Response.contenttype to application/json;charset=utf-8 and encode the returned value by handler to json byte-string format.

Handlers must return dict when this decorator is used.

from yhttp import json


@app.route()
@json
def get(req):
    return {'foo': 'bar'}
yhttp.text(handler)

Sets the Response.contenttype to text/text; charset=utf-8.

Handlers must return str when this decorator is used.

New in version 2.8.

from yhttp import text


@app.route()
@text
def get(req):
    return 'Unicode String'
yhttp.html(handler)

Sets the Response.contenttype to text/html; charset=utf-8.

Handlers must return str when this decorator is used.

New in version 2.8.

from yhttp import html


@app.route()
@html
def get(req):
    return 'Unicode String'

validate decorator

yhttp.validate(nobody=None, fields=None, strict=False)

see Request Valiation

statuses Module

yhttp.statuses.status(code, text)

Alias for HTTPStatus

yhttp.statuses.badrequest()

HTTP 400 Bad Request exception factory

yhttp.statuses.unauthorized()

HTTP 401 Unauthorized exception factory

yhttp.statuses.forbidden()

HTTP 403 Forbidden exception factory

yhttp.statuses.notfound()

HTTP 404 Not Found exception factory

yhttp.statuses.methodnotallowed()

HTTP 405 Method Not Allowed exception factory

yhttp.statuses.conflict()

HTTP 409 Conflict exception factory

yhttp.statuses.gone()

HTTP 410 Gone exception factory

yhttp.statuses.preconditionfailed()

HTTP 412 Precondition Failed exception factory

yhttp.statuses.notmodified()

HTTP 304 Not Modified exception factory

yhttp.statuses.internalservererror()

HTTP 500 Internal Server Error exception factory

yhttp.statuses.badgateway()

HTTP 502 Bad Gateway exception factory

yhttp.statuses.movedpermanently(url)

HTTP 301 Moved Permanently exception factory

yhttp.statuses.found(url)

HTTP 302 Found exception factory

yhttp.statuses.statuscode(code)

Set the Response.status to code.

@app.route()
@statuscode('201 Created')
def post(req):
    ...

with Given(app, verb='POST'):
    assert status == '201 Created'

New in version 2.5.