NAME

Protocol::UWSGI - handle the UWSGI wire protocol

VERSION

Version 1.000

SYNOPSIS

use strict;
use warnings;
use Protocol::UWSGI qw(:all);
# Encode...
my $req = build_request(
  uri    => 'http://localhost',
  method => 'GET',
  remote => '1.2.3.4:1234',
);
# ... and decode again
warn "URI was " . uri_from_env(
  extract_frame(\$req)
);

DESCRIPTION

Provides protocol-level support for UWSGI packet generation/decoding, as defined by http://uwsgi-docs.readthedocs.org/en/latest/Protocol.html. Currently expects to deal with PSGI data (modifier 1 == 5), although this may be extended later if there's any demand for the other packet types.

This is unlikely to be useful in an application - it's intended to provide support for dealing with the protocol in an existing framework: it deals with the abstract protocol only, and has no network transport handling at all. Try Net::Async::UWSGI for an implementation that actually does something useful.

Typically you'd create a UNIX socket and listen for requests, passing any data to the "extract_frame" function and handling the resulting data if that function returns something other than undef:

# Detect read - first packet is usually the UWSGI header, everything
# after that would be the HTTP request body if there is one:
sub on_read {
  my ($self, $buffref) = @_;
  while(my $pkt = extract_frame($buffref)) {
    $self->handle_uwsgi($pkt);
  }
}

# and probably an EOF handler to detect client hangup
# sub on_eof { ... }

IMPLEMENTATION - Server

A server implementation typically accepts requests from a reverse proxy, such as nginx, and returns HTTP responses.

Import the :server tag to get "uri_from_env", "extract_frame" and in future maybe "psgi_from_env" functions:

use Protocol::UWSGI qw(:server);

IMPLEMENTATION - Client

A client implementation typically accepts HTTP requests and converts them to UWSGI for passing to a UWSGI-capable application.

Import the :client tag to get "build_request":

use Protocol::UWSGI qw(:client);

FUNCTIONS

If you're handling incoming UWSGI requests, you'll need to instantiate via "new" then decode the request using "extract_frame".

If you're making UWSGI requests against an external UWSGI server, that'll be "build_request".

Just want to decode captured traffic? "extract_frame" again.

extract_frame

Attempts to extract a single UWSGI packet from the given buffer (which should be passed as a scalar ref, e.g.

my $buffref = \"...";
my $req = Protocol::UWSGI->extract_frame($buffref)
  or die "could not find UWSGI frame";

If we had enough data for a packet, that packet will be removed from the buffer and returned. There may be additional packet data that can be extracted, or non-UWSGI data such as HTTP request body.

If this returns undef, there's not enough data to process - in this case, the buffer is guaranteed not to be modified.

This may be called as a class method or an instance method. The instance state will remain unchanged after calling this method.

Note that there is no constructor provided in this class - if you want to call this as an instance method, you'll need to bless manually or be applying this as a role/mixin.

bytes_required

Returns the number of additional bytes we'll need in order to proceed.

If zero, this means we should be able to extract a valid frame.

build_request

Builds an UWSGI request using the given modifier, defaulting to modifier1 == 5 and modifier2 == 0, i.e. PSGI request.

Takes the following named parameters:

  • modifier1 - the modifier1 value, defaults to 5 if not provided

  • modifier2 - the modifier2 value, defaults to 0 if not provided

  • method - the HTTP request method

  • uri - which URI we're requesting, can be passed as a plain string in which case we'll upgrade to a URI object internally

  • headers - a hashref of HTTP headers, e.g. { 'Content-Type' => 'text/html' }

Returns a scalar containing packet data or raises an exception on failure.

extract_modifier

Used internally to extract and handle the modifier-specific data.

uri_from_env

Returns a URI object parsed from a request ("environment").

INHERITED METHODS

Exporter

as_heavy, export, export_fail, export_ok_tags, export_tags, export_to_level, import, require_version

AUTHOR

Tom Molesworth <cpan@perlsite.co.uk>

LICENSE

Copyright Tom Molesworth 2013-2014. Licensed under the same terms as Perl itself.