Terse
view release on metacpan or search on metacpan
lib/Terse.pm view on Meta::CPAN
package Terse;
our $VERSION = '0.123456789';
use 5.006;
use strict;
use warnings;
no warnings 'redefine';
use Plack::Request;
use Plack::Response;
use Cpanel::JSON::XS;
use Scalar::Util qw/reftype/;
use Time::HiRes qw(gettimeofday);
use Terse::WebSocket;
use Want qw/want/;
use Digest::SHA;
use Struct::WOP qw/all/ => { type => ['UTF-8'], destruct => 1 };
our ($JSON, %PRIVATE);
BEGIN {
$JSON = Cpanel::JSON::XS->new->utf8->canonical(1)->allow_blessed->convert_blessed;
%PRIVATE = (
map { $_ => 1 }
qw/new run logger logInfo logError websocket delayed_response build_terse content_type raiseError graft pretty serialize DESTROY TO_JSON AUTOLOAD to_app/
);
}
sub new {
my ($pkg, %args) = @_;
$pkg = ref $pkg if ref $pkg;
if (delete $args{private}) {
for my $key (keys %args) {
if ($key !~ m/^_/) {
$args{"_$key"} = delete $args{$key};
}
}
}
return bless \%args, $pkg;
}
sub run {
my ($pkg, %args) = @_;
my $j = $pkg->new(
private => 1,
login => 'login',
logout => 'logout',
auth => 'auth',
insecure_session => 0,
content_type => 'application/json',
request_class => 'Plack::Request',
websocket_class => 'Terse::WebSocket',
sock => 'psgix.io',
stream_check => 'psgi.streaming',
favicon => 'favicon.ico',
%args
);
$j->_build_terse();
$j->request = $j->{_request_class}->new($args{plack_env});
$j->response = $pkg->new(
authenticated => \0,
error => \0,
errors => [],
);
if ($j->request->env->{PATH_INFO} =~ m/favicon.ico$/) {
return [500, [], []] unless -f $j->_favicon;
open my $fh, '<', $j->_favicon;
my $favicon = do { local $/; <$fh> };
close $fh;
return [200, ['Content-Type', 'image/vnd.microsoft.icon'], [$favicon] ];
}
my $content_type = $j->request->content_type;
if ($content_type && $content_type =~ m/application\/json/) {
$j->graft('params', $j->request->raw_body || "{}");
} else {
$j->params = {%{$j->request->parameters || {}}};
}
unless ((reftype($j->params) || "") eq 'HASH') {
$j->response->raiseError('Invalid parameters', 400);
return $j->_response($j->response);
}
$j->sid = $j->request->cookies->{sid};
unless ($j->sid) {
my $h = Digest::SHA->new(256);
my @us = gettimeofday;
push @us, map { $j->request->env->{$_} } grep {
$_ =~ /^HTTP(?:_|$)/;
} keys %{ $j->request->env };
$h->add(@us);
$j->sid = $h->hexdigest;
}
$j->sid = {
value => $j->is_logout ? "" : $j->sid,
path => $j->request->uri,
secure => !$j->{_insecure_session},
};
my $auth = $j->{_auth};
my ($session) = $j->_dispatch($auth, $pkg->new());
my $req = $j->params->req;
$req =~ /^([a-z][0-9a-zA-Z_]{1,31})$/ && do { $req = $1 // '' } if $req;
$req = $j->{_application}->preprocess_req($req, $j) if $j->{_application}->can('preprocess_req');
if (!$req || !$session || $PRIVATE{$req}) {
$j->response->raiseError('Invalid request', 400);
lib/Terse.pm view on Meta::CPAN
=head2 logger
Set or Retrieve the logger for the application.
$terse->logger($logger);
$terse->logger->info();
$terse->logger->err();
=cut
=head2 logError
Log and raise an error message.
$terse->logError('this is an error message', 404);
=cut
=head2 logInfo
Log an info message.
$terse->logInfo('this an info message');
=cut
=head2 raiseError
Raise an error message.
$terse->raiseError('this is an error message', 404);
=cut
=head2 graft
Decode a JSON string.
$terse->response->graft('config', "{...}");
=cut
=head2 pretty
Set JSON to pretty print mode.
$terse->pretty(1);
=cut
=head2 serialize
Encode a perl struct as a JSON string.
$terse->serialize({ ... });
=cut
=head2 delayed_response
Delay the response for non-blocking I/O based server streaming or long-poll Comet push technology.
$terse->delayed_response(sub {
$terse->response->test = 'okay';
return $terse->response;
});
=cut
=head1 AUTHOR
LNATION, C<< <email at lnation.org> >>
=head1 BUGS
Please report any bugs or feature requests to C<bug-terse at rt.cpan.org>, or through
the web interface at L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Terse>. I will be notified, and then you'll
automatically be notified of progress on your bug as I make changes.
=head1 SUPPORT
You can find documentation for this module with the perldoc command.
perldoc Terse
You can also look for information at:
=over 4
=item * RT: CPAN's request tracker (report bugs here)
L<https://rt.cpan.org/NoAuth/Bugs.html?Dist=Terse>
=item * CPAN Ratings
L<https://cpanratings.perl.org/d/Terse>
=item * Search CPAN
L<https://metacpan.org/release/Terse>
=back
=head1 ACKNOWLEDGEMENTS
=head1 LICENSE AND COPYRIGHT
This software is Copyright (c) 2022 by LNATION.
This is free software, licensed under:
The Artistic License 2.0 (GPL Compatible)
=cut
1; # End of Terse
( run in 0.457 second using v1.01-cache-2.11-cpan-0bb4e1dffa6 )