<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">package Mojo::Content::Single;
use Mojo::Base 'Mojo::Content';

use Mojo::Asset::Memory;
use Mojo::Content::MultiPart;

has asset =&gt; sub { Mojo::Asset::Memory-&gt;new(auto_upgrade =&gt; 1) };
has auto_upgrade =&gt; 1;

sub new {
  my $self = shift-&gt;SUPER::new(@_);
  $self-&gt;{read}
    = $self-&gt;on(read =&gt; sub { $_[0]-&gt;asset($_[0]-&gt;asset-&gt;add_chunk($_[1])) });
  return $self;
}

sub body_contains { shift-&gt;asset-&gt;contains(shift) &gt;= 0 }

sub body_size {
  my $self = shift;
  return ($self-&gt;headers-&gt;content_length || 0) if $self-&gt;{dynamic};
  return $self-&gt;asset-&gt;size;
}

sub clone {
  my $self = shift;
  return undef unless my $clone = $self-&gt;SUPER::clone();
  return $clone-&gt;asset($self-&gt;asset);
}

sub get_body_chunk {
  my ($self, $offset) = @_;
  return $self-&gt;generate_body_chunk($offset) if $self-&gt;{dynamic};
  return $self-&gt;asset-&gt;get_chunk($offset);
}

sub parse {
  my $self = shift;

  # Parse headers
  $self-&gt;_parse_until_body(@_);

  # Parse body
  return $self-&gt;SUPER::parse
    unless $self-&gt;auto_upgrade &amp;&amp; defined $self-&gt;boundary;

  # Content needs to be upgraded to multipart
  $self-&gt;unsubscribe(read =&gt; $self-&gt;{read});
  my $multi = Mojo::Content::MultiPart-&gt;new(%$self);
  $self-&gt;emit(upgrade =&gt; $multi);
  return $multi-&gt;parse;
}

1;

=encoding utf8

=head1 NAME

Mojo::Content::Single - HTTP content

=head1 SYNOPSIS

  use Mojo::Content::Single;

  my $single = Mojo::Content::Single-&gt;new;
  $single-&gt;parse("Content-Length: 12\x0d\x0a\x0d\x0aHello World!");
  say $single-&gt;headers-&gt;content_length;

=head1 DESCRIPTION

L&lt;Mojo::Content::Single&gt; is a container for HTTP content as described in RFC
2616.

=head1 EVENTS

L&lt;Mojo::Content::Single&gt; inherits all events from L&lt;Mojo::Content&gt; and can
emit the following new ones.

=head2 upgrade

  $single-&gt;on(upgrade =&gt; sub {
    my ($single, $multi) = @_;
    ...
  });

Emitted when content gets upgraded to a L&lt;Mojo::Content::MultiPart&gt; object.

  $single-&gt;on(upgrade =&gt; sub {
    my ($single, $multi) = @_;
    return unless $multi-&gt;headers-&gt;content_type =~ /multipart\/([^;]+)/i;
    say "Multipart: $1";
  });

=head1 ATTRIBUTES

L&lt;Mojo::Content::Single&gt; inherits all attributes from L&lt;Mojo::Content&gt; and
implements the following new ones.

=head2 asset

  my $asset = $single-&gt;asset;
  $single   = $single-&gt;asset(Mojo::Asset::Memory-&gt;new);

The actual content, defaults to a L&lt;Mojo::Asset::Memory&gt; object with
C&lt;auto_upgrade&gt; enabled.

=head2 auto_upgrade

  my $upgrade = $single-&gt;auto_upgrade;
  $single     = $single-&gt;auto_upgrade(0);

Try to detect multipart content and automatically upgrade to a
L&lt;Mojo::Content::MultiPart&gt; object, defaults to C&lt;1&gt;.

=head1 METHODS

L&lt;Mojo::Content::Single&gt; inherits all methods from L&lt;Mojo::Content&gt; and
implements the following new ones.

=head2 new

  my $single = Mojo::Content::Single-&gt;new;

Construct a new L&lt;Mojo::Content::Single&gt; object and subscribe to L&lt;/"read"&gt;
event with default content parser.

=head2 body_contains

  my $bool = $single-&gt;body_contains('1234567');

Check if content contains a specific string.

=head2 body_size

  my $size = $single-&gt;body_size;

Content size in bytes.

=head2 clone

  my $clone = $single-&gt;clone;

Clone content if possible, otherwise return C&lt;undef&gt;.

=head2 get_body_chunk

  my $bytes = $single-&gt;get_body_chunk(0);

Get a chunk of content starting from a specific position.

=head2 parse

  $single = $single-&gt;parse("Content-Length: 12\x0d\x0a\x0d\x0aHello World!");
  my $multi
    = $single-&gt;parse("Content-Type: multipart/form-data\x0d\x0a\x0d\x0a");

Parse content chunk and upgrade to L&lt;Mojo::Content::MultiPart&gt; object if
necessary.

=head1 SEE ALSO

L&lt;Mojolicious&gt;, L&lt;Mojolicious::Guides&gt;, L&lt;http://mojolicio.us&gt;.

=cut
</pre></body></html>