App-MBUtiny

 view release on metacpan or  search on metacpan

lib/App/MBUtiny/Collector/Server.pm  view on Meta::CPAN

    > Host: localhost
    > User-Agent: curl/7.58.0
    > Accept: */*
    >
    < HTTP/1.1 204 No Content
    < Date: Fri, 21 Jun 2019 21:40:36 GMT
    < Server: Apache/2.4.29 (Ubuntu)
    < Connection: close
    < Content-Type: text/plain
    <

=cut

__PACKAGE__->register_method( # DELETE /mbutiny/NAME
    name    => "delete",
    method  => "DELETE",
    path    => $BASE_URL_PATH_PREFIX,
    deep    => 1,
    attrs   => {
        serialize => 1,
    },
    description => "Delete file",
    code    => sub {
### CODE:
    my $self = shift;
    my $q = shift;
    my $dbi = $self->dbi;
    my $name = _get_name_from_path($self->{request_uri} // "");
    unless ($name) {
        $self->error("Incorrect path! Check backup host name");
        $self->status(0);
        return HTTP_BAD_REQUEST;
    }
    my $file = $q->param("file");
    unless ($file) {
        $self->error("Incorrect file name for delete");
        $self->status(0);
        return HTTP_BAD_REQUEST;
    }
    my $type = $q->param("type") // 0;

    $dbi->del(
        type    => $type,
        name    => $name,
        file    => $file,
        addr    => $ENV{REMOTE_ADDR},
    ) or do {
        $self->error($dbi->error());
        $self->status(0);
        return HTTP_INTERNAL_SERVER_ERROR;
    };

    return HTTP_NO_CONTENT; # HTTP RC
});

    return 1;
}

sub again {
    my $self = shift;
    $self->SUPER::again;

    # Serializer
    my $sr = new CTK::Serializer(SERIALIZE_FORMAT, attrs => SR_ATTRS);
    unless ($sr->status) {
        $self->error(sprintf("Can't create json serializer: %s", $sr->error));
        $self->{status} = 0;
    }
    $self->{sr} = $sr;

    # DBI object
    my $dbi_conf = $self->config('dbi') || {};
    $dbi_conf = {} unless is_hash($dbi_conf);
    my $dbi = new App::MBUtiny::Collector::DBI(%$dbi_conf);
    $self->log_error($dbi->error) if $dbi->error;
    $self->{dbi} = $dbi;

    return $self;
}
sub serializer {
    my $self = shift;
    return $self->{sr};
}
sub dbi {
    my $self = shift;
    return $self->{dbi};
}
sub middleware {
    my $self = shift;
    my $q = shift;

    # Check DBI connect
    if ($self->dbi->error) { # DBI checking
        $self->error($self->dbi->error);
        $self->status(0);
    }
    $self->{_time} = sprintf("%.4f", $self->tms(1))*1;
    return HTTP_INTERNAL_SERVER_ERROR unless $self->status;

    # Prepare input data
    my $meth = $self->info->{method} || "GET";
    if ($meth =~ /POST|PUT|PATCH/) {
        my $data = $q->param($meth."DATA") // $q->param('XForms:Model');
        Encode::_utf8_on($data);
        if (value($self->info("attrs"), "deserialize")) {
            my $serializer = $self->serializer;
            $self->data($serializer->deserialize($data));
            unless ($serializer->status) {
                $self->error(sprintf("Can't deserialize document: %s", $serializer->error));
                $self->status(0);
                return HTTP_INTERNAL_SERVER_ERROR;
            }
        } else {
            $self->data($data);
        }
    }

    return HTTP_OK;
}
sub response {
    my $self = shift;
    my $q = shift;
    my $rc = $self->code; # RC HTTP code (from yuor methods)
    my $head = $self->head || {}; # HTTP Headers (hashref)
    my $data = $self->data; # The working data
    my $msg = $self->message || HTTP::Status::status_message($rc) || "Unknown code";
    $data = {status => 0, error => $self->error || "Unknown error"} if !$self->status && (is_void($data) || $data eq "");
    return $self->SUPER::response unless $data && ref($data);
    return $self->SUPER::response unless value($self->info("attrs"), "serialize");
    #binmode STDOUT, ":raw:utf8"; # Disabled, by encoding reasons. See SUPER::response (utf8::encode($content))

    # Set debug time
    $data->{'time'} = sprintf("%.4f", sprintf("%.4f", $self->tms(1))*1 - $self->{_time})*1;

    # Set status and response
    $data->{status} = $self->status;
    $data->{error} = $self->error;

    # Headers
    $head->{Server} = sprintf("%s/%s", __PACKAGE__, $VERSION);
    $head->{Connection} = "close";
    $head->{Date} = HTTP::Date::time2str(time());
    $head->{'Content-Type'} = CONTENT_TYPE;
    $self->head($head);

    my $serializer = $self->serializer;
    $self->data($serializer->serialize($data));

    unless ($serializer->status) {
        my $errmsg = sprintf("Can't serialize structure: %s", $serializer->error);
        $errmsg =~ s/\"/\\\"/g;
        $errmsg =~ s/\'/\\\'/g;
        $self->data(sprintf('{"status": 0, "error": "%s"}', $errmsg));
        $self->code(HTTP_INTERNAL_SERVER_ERROR);
    }

    #my @res = (sprintf("Status: %s %s", $rc, $msg));
    #push @res, sprintf("Content-Type: %s", "text/plain; charset=utf-8");
    #push @res, "", $data // "";
    #return join("\015\012", @res);

    return $self->SUPER::response;
}

sub _get_name_from_path {
    my $request_uri = shift // '';
    my $uri = new URI(sprintf("http://localhost%s", $request_uri));
    my $str = $uri->path() // "";
    return "" unless length($str);
    return "" if index($str, $BASE_URL_PATH_PREFIX, 0);
    my $sfx = substr($str, length($BASE_URL_PATH_PREFIX)) || "";
    $sfx =~ s/^\/+//;
    $sfx =~ s/\/+/\-/g;
    return $sfx;
}

=head1 INTERNAL METHODS

=head2 again

The CTK method for classes extension

See L<CTK/again>

=head2 dbi

Returns L<App::MBUtiny::Collector::DBI> object

=head2 middleware

The L<WWW::MLite> method for input data preparing

=head2 response

The L<WWW::MLite> method for output data preparing

=head2 serializer

Returns current serializer object

See L<CTK::Serializer>

=head1 HISTORY

See C<Changes> file

=head1 TO DO

See C<TODO> file

=head1 SEE ALSO

L<App::MBUtiny>, L<WWW::MLite>, L<App::MBUtiny::Collector::DBI>

=head1 AUTHOR

Serż Minus (Sergey Lepenkov) L<http://www.serzik.com> E<lt>abalama@cpan.orgE<gt>

=head1 COPYRIGHT

Copyright (C) 1998-2019 D&D Corporation. All Rights Reserved



( run in 0.766 second using v1.01-cache-2.11-cpan-8f98c5d2c55 )