Home > Net >  "Can't call method 'isBinary' on an undefined value", when value actually i
"Can't call method 'isBinary' on an undefined value", when value actually i

Time:12-16

I am trying to make a tinier, more optimized CGI module for Perl.

When working on the init subroutine to get, or set default file data, I run into an issue primarily caused with the MIME::Types module.

In reality, my init subroutine is supposed to get the blessed variables from the new constructor, initialize MIME::Types, use MIME::Types to return the MIME::Type of $type via mimeTypeOf(), determine if the MIME::Type is binary, and print out the Content-Type and Content-Disposition.

However, when trying to do something of that nature, I get the title as the error.

This is my current code, which in theory should work.

sub new {
    my ($class, %args) = @_; 
    my $self = {};
    my $type = $args{type} // 'text/html'; # If type isn't defined, default to HTML content.
    my $attachment = ($args{attachment} // 'false') eq 'true' ? 'attachment' : 'inline'; # Same, but with disposition instead.
    $self->{type} = $type;
    $self->{attachment} = $attachment;
    bless $self, $class;
    return $self;
}

sub init {
    my $self = shift;
    CORE::state $type = shift // $self->{type}; # If there are no overrides, just use $self->type;
    # print $self->type; prints text/html when not specified.
    CORE::state $attachment = shift // $self->{attachment}; # Same as above, but with $self->attachment;
    # print $self->attachment; prints inline when not specified.
    my $types = MIME::Types->new;
    my $mime = $types->mimeTypeOf($type);
    if ($mime->isBinary) {
        $self->{attachment} = 'attachment';
    } else {
        $self->{attachment} = ('inline' or $attachment);
    }
    die "Warning: Binary content types should not be sent inline!\r\n" if ($mime->isBinary && $attachment eq 'inline');
    print "Content-Type: $mime\r\nContent-Disposition: $self->{attachment}\r\n\r\n";
    return;
}

Even printing the types return a non undefined value, in fact, it prints out what it's supposed to when there's nothing inside of the new method. This is the code which is in my main CGI file.

#!C:\Strawberry\perl\bin\perl.exe
use strict;
use warnings;
use TinyCGI::Core;

# Create a new TinyCGI::Core object
my $cgi = TinyCGI::Core->new();

# Initialize the TinyCGI::Core object
$cgi->init();

print 'Hello, World!';

This worked perfectly fine without MIME::Types, and even works just fine with stuff actually defined within the object.

I've also tried not using CORE::state.

CodePudding user response:

You are using MIME::Types incorrectly. It looks like you want to take the value from an HTTP header (or maybe multi-part body header) and figure out what it is. You are using mimeTypeOf, which expects a file extension or filename, when you should be using type, which expects a type string.

Either way, there's a chance that you could get back an undef value because MIME::Types might not be able to map the string to a type. You should guard against that:

my $type = $mime->type( $self->{type} );
if( defined $type ) { ... }

Unrelated to that, you are using CORE::state for some reason. That makes it look like you are defining some method or subroutine named state and expecting it to conflict with the Perl built-in.

But I don't think you want state here. You have an instance method init that is for some reason persisting a value based on an earlier created, unrelated instance. I think you want my, since you are merely giving a local name to something that's already inside the invoking instance. You don't want to persist that to the next instance that calls this.

  • Related