Pyjo.Message - HTTP message base class

import Pyjo.Message

class MyMessage(Pyjo.Message.object):

    def cookies(self):
        ...

    def extract_start_line(self, buf):
        ...

    def get_start_line_chunk(self):
        ...

Pyjo.Message is an abstract base class for HTTP messages based on RFC 7230, RFC 7231 and RFC 2388.

Events

Pyjo.Message inherits all events from Pyjo.EventEmitter and can emit the following new ones.

finish

@msg.on
def finish(msg):
    ...

Emitted after message building or parsing is finished.

from Pyjo.Util import steady_time
before = steady_time()

@msg.on
def finish(msg):
    msg.headers.header('X-Parser-Time', int(steady_time() - before))

progress

@msg.on
def progress(msg, state, offset):
    ...

Emitted when message building or parsing makes progress.

# Building
@msg.on
def progress(msg, state, offset):
    print("Building {0} at offset {1}".format(state, offset))

# Parsing
@msg.on
def progress(msg, state, offset):
    length = msg.headers.content_length
    if length:
        size = msg.content.progress
        print("Progress: {0}%".format(100 if size == length
                                      else int(size / (length / 100))))

Classes

class Pyjo.Message.Pyjo_Message(**kwargs)

Pyjo.Message inherits all attributes and methods from Pyjo.EventEmitter and implements the following new ones.

body
bytes = msg.body
msg.body = b'Hello!'

Slurp or replace content, Mojo.Content.MultiPart will be automatically downgraded to Pyjo.Content.Single.

body_params
params = msg.body_params

POST parameters extracted from application/x-www-form-urlencoded or multipart/form-data message body, usually a Pyjo.Parameters object. Note that this method caches all data, so it should not be called before the entire message body has been received. Parts of the message body need to be loaded into memory to parse POST parameters, so you have to make sure it is not excessively large, there’s a 16MB limit by default.

# Get POST parameter names and values
params_dict = msg.body_params.to_dict()
body_size
size = msg.body_size

Content size in bytes.

build_body()
chunk = msg.build_body()

Render whole body.

build_headers()
chunk = msg.build_headers()

Render all headers.

build_start_line()
chunk = msg.build_start_line()

Render start-line.

content = None
content = msg.content
msg.content = Pyjo.Content.Single.new()

Message content, defaults to a Pyjo.Content.Single object.

cookie(name)
cookie = msg.cookie('foo')

Access message cookies, usually Pyjo.Cookie.Request or Pyjo.Cookie.Response objects. If there are multiple cookies sharing the same name, and you want to access more than just the last one, you can use every_cookie(). Note that this method caches all data, so it should not be called before all headers have been received.

# Get cookie value
print(msg.cookie('foo').value)
cookies(*args, **kwargs)
cookies = msg.cookies

Access message cookies. Meant to be overloaded in a subclass.

default_charset = None
charset = msg.default_charset
msg.default_charset = 'utf-8'

Default charset used by text and to extract data from application/x-www-form-urlencoded or multipart/form-data message body, defaults to utf-8.

dom(pattern=None)
dom = msg.dom()
collection = msg.dom('a[href]')

Retrieve message body from text and turn it into a Pyjo.DOM object, an optional selector can be used to call the method Pyjo.DOM.find() on it right away, which then returns a Pyjo.Collection object. Note that this method caches all data, so it should not be called before the entire message body has been received. The whole message body needs to be loaded into memory to parse it, so you have to make sure it is not excessively large, there’s a 16MB limit by default.

# Perform "find" right away
print(msg.dom('h1, h2, h3').map('text').join("\n"))

# Use everything else Mojo::DOM has to offer
print(msg.dom.at('title').text)
print(msg.dom.at('body').children().map('tag').uniq().join("\n"))
error
err = msg.error

Get message error, a None return value indicates that there is no error.

cookies = msg.every_cookie('foo')

Similar to cookie(), but returns all message cookies sharing the same name as an array reference.

# Get first cookie value
print(msg.every_cookie('foo')[0].value)
every_upload(name)
uploads = msg.every_upload('foo')

Similar to upload(), but returns all file uploads sharing the same name as an array reference.

# Get content of first uploaded file
print(msg.every_upload('foo')[0].asset.slurp())
extract_start_line(*args, **kwargs)
boolean = msg.extract_start_line(buf)

Extract start-line from string. Meant to be overloaded in a subclass.

finish()
msg = msg.finish()

Finish message parser/generator.

fix_headers()
msg = msg.fix_headers()

Make sure message has all required headers.

get_body_chunk(offset)
chunk = msg.get_body_chunk(offset)

Get a chunk of body data starting from a specific position.

get_header_chunk(offset)
chunk = msg.get_header_chunk(offset)

Get a chunk of header data, starting from a specific position.

get_start_line_chunk(*args, **kwargs)
chunk = msg.get_start_line_chunk(offset)

Get a chunk of start-line data starting from a specific position. Meant to be overloaded in a subclass.

header_size
size = msg.header_size

Size of headers in bytes.

headers
headers = msg.headers

Message headers, usually a Pyjo.Headers object.

# Longer version
headers = msg.content.headers
is_finished
boolean = msg.is_finished

Check if message parser/generator is finished.

is_limit_exceeded
boolean = msg.is_limit_exceeded

Check if message has exceeded max_line_size, max_message_size, Pyjo.Content.max_buffer_size or Pyjo.Headers.max_line_size.

json(pointer=None)
value = msg.json()
value = msg.json('/foo/bar')

Decode JSON message body directly using Pyjo.JSON if possible, an None return value indicates a bare null or that decoding failed. An optional JSON Pointer can be used to extract a specific value with Pyjo.JSON.Pointer. Note that this method caches all data, so it should not be called before the entire message body has been received. The whole message body needs to be loaded into memory to parse it, so you have to make sure it is not excessively large, there’s a 16MB limit by default.

# Extract JSON values
print(msg.json()['foo']['bar'][23])
print(msg.json('/foo/bar/23'))
max_line_size = None
size = msg.max_line_size
msg.max_line_size = 8192

Maximum start-line size in bytes, defaults to the value of the PYJO_MAX_LINE_SIZE environment variable or 8192 (8KB).

max_message_size = None
size = msg.max_message_size
msg.max_message_size = 16777216

Maximum message size in bytes, defaults to the value of the PYJO_MAX_MESSAGE_SIZE environment variable or 16777216 (16MB). Setting the value to 0 will allow messages of indefinite size. Note that increasing this value can also drastically increase memory usage, should you for example attempt to parse an excessively large message body with the body_params, dom() or json() methods.

parse(chunk='')
msg = msg.parse('HTTP/1.1 200 OK...')

Parse message chunk.

set_error(message=None, code=None)
msg = msg.set_error(message, code)

Set message error, a None for message indicates that there is no error.

# Connection or parser error
msg.set_error(message='Connection refused')

# 4xx/5xx response
msg.set_error(message='Internal Server Error', code=500)
start_line_size
size = msg.start_line_size

Size of the start-line in bytes.

text
string = msg.text

Retrieve body and try to decode it with Pyjo.Content.charset or default_charset.

to_bytes()
bstring = msg.to_bytes()

Render whole message.

upload(name)
upload = msg.upload('foo')

Access multipart/form-data file uploads, usually Pyjo.Upload objects. If there are multiple uploads sharing the same name, and you want to access more than just the last one, you can use every_upload(). Note that this method caches all data, so it should not be called before the entire message body has been received.

# Get content of uploaded file
print(msg.upload('foo').asset.slurp())
uploads
uploads = msg.uploads

All multipart/form-data file uploads, usually Pyjo.Upload objects.

# Names of all uploads
for upload in msg.uploads:
    print(upload.name)
version = None
version = msg.version
msg.version = '1.1'

HTTP version of message, defaults to 1.1.

Pyjo.Message.object

alias of Pyjo_Message