Plack-App-Catmandu-SRU
view release on metacpan or search on metacpan
lib/Plack/App/Catmandu/SRU.pm view on Meta::CPAN
package Plack::App::Catmandu::SRU;
our $VERSION = '0.02';
use Catmandu::Sane;
use Catmandu;
use Catmandu::Fix;
use Catmandu::Exporter::Template;
use URI;
use SRU::Request;
use SRU::Response;
use Types::Standard qw(Str ArrayRef HashRef ConsumerOf);
use Types::Common::String qw(NonEmptyStr);
use Types::Common::Numeric qw(PositiveInt);
use Moo;
use Plack::Request;
use namespace::clean;
use feature qw(signatures);
no warnings qw(experimental::signatures);
has store_name => (
is => 'ro',
isa => Str,
init_arg => 'store',
);
has bag_name => (
is => 'ro',
isa => Str,
init_arg => 'bag',
);
has content_type => (
is => 'ro',
isa => Str,
default => sub { 'text/xml'; },
);
has cql_filter => (
is => 'ro',
isa => NonEmptyStr,
);
has default_record_schema => (
is => 'ro',
isa => NonEmptyStr,
required => 1,
);
has record_schemas => (
is => 'ro',
isa => ArrayRef[HashRef],
default => sub { []; },
);
has title => (
is => 'ro',
isa => NonEmptyStr,
);
has description => (
is => 'ro',
isa => NonEmptyStr,
);
has template_options => (
is => 'ro',
isa => HashRef,
lib/Plack/App/Catmandu/SRU.pm view on Meta::CPAN
<database>$database</database>
</serverInfo>
$database_info
$index_info
$schema_info
$config_info
</explain>
XML
));
return $self->render_sru_response($response);
}
elsif ($operation eq 'searchRetrieve') {
my $request = SRU::Request::SearchRetrieve->new($params->flatten);
my $response = SRU::Response->newFromRequest($request);
if (@{$response->diagnostics}) {
return $self->render_sru_response($response);
}
my $schema = $record_schema_map->{$request->recordSchema || $self->default_record_schema};
unless ($schema) {
$response->addDiagnostic(SRU::Response::Diagnostic->newFromCode(66));
return $self->render_sru_response($response);
}
my $identifier = $schema->{identifier};
my $fix = $schema->{fix};
my $template = $schema->{template};
my $layout = $schema->{layout};
my $cql = $params->get('query');
if ($self->cql_filter) {
# space before the filter is to circumvent a bug in the Solr
# 3.6 edismax parser
$cql = "( ".$self->cql_filter.") and ( $cql)";
}
my $first = $request->startRecord // 1;
my $limit = $request->maximumRecords // $default_limit;
if ($limit > $maximum_limit) {
$limit = $maximum_limit;
}
my $hits = eval {
$bag->search(
%{$self->default_search_params},
cql_query => $cql,
sru_sortkeys => $request->sortKeys,
limit => $limit,
start => $first - 1,
);
} or do {
my $e = $@;
if (index($e, 'cql error') == 0) {
$response->addDiagnostic(SRU::Response::Diagnostic->newFromCode(10));
return $self->render_sru_response($response);
}
Catmandu::Error->throw($e);
};
$hits->each(sub {
my $data = $_[0];
my $metadata = "";
my $exporter = Catmandu::Exporter::Template->new(
%$template_options,
template => $template,
file => \$metadata
);
$exporter->add($fix ? $fix->fix($data) : $data);
$exporter->commit;
$response->addRecord(SRU::Response::Record->new(
recordSchema => $identifier,
recordData => $metadata,
));
});
$response->numberOfRecords($hits->total);
return $self->render_sru_response($response);
}
else {
my $request = SRU::Request::Explain->new($params->flatten);
my $response = SRU::Response->newFromRequest($request);
$response->addDiagnostic(SRU::Response::Diagnostic->newFromCode(6));
return $self->render_sru_response($response);
}
};
}
sub render_sru_response ($self, $response) {
my $body = $response->asXML;
utf8::encode($body);
[200, ['Content-Type' => $self->content_type], [$body]];
}
sub not_found ($self) {
[404, ['Content-Type' => 'text/plain'], ['not found']];
}
1;
=head1 NAME
Plack::App::Catmandu::SRU - drop in replacement for Dancer::Plugin::Catmandu::SRU
=head1 SYNOPSIS
use Plack::Builder;
Plack::App::Catmandu::SRU;
builder {
enable 'ReverseProxy';
enable '+Dancer::Middleware::Rebase', base => Catmandu->config->{uri_base}, strip => 1;
mount "/sru" => Plack::App::Catmandu::SRU->new(
store => 'search',
bag => 'publication',
cql_filter => 'type = dataset',
limit => 100,
maximum_limit => 500,
record_schemas => [
{
identifier => "info:srw/schema/1/mods-v3.6",
title => "MODS",
name => "mods_36",
template => "views/export/mods_36.tt",
fix => 'fixes/pub.fix'
},
],
)->to_app;
};
=head1 CONSTRUCTOR ARGUMENTS
=over
=item store
Name of Catmandu store in your catmandu store configuration
Default: C<default>
=item bag
Name of Catmandu bag in your catmandu store configuration
Default: C<data>
This must be a bag that implements L<Catmandu::CQLSearchable>, and that configures a C<cql_mapping>
=item cql_filter
A CQL query to find all records in the database that should be made available to SRU
=item default_record_schema
default metadata schema all records are shown in, when SRU parameter C<recordSchema> is not gi en . Should be one listed in C<record_schemas>
=item limit
The default number of records to be returned in each SRU request, when SRU parameter C<maximumRecords> is not given during a searchRetrieve request.
When not provided in the constructor, it is derived from the default limit of your catmandu bag (see L<Catmandu::Searchable#default_limit>)
=item maximum_limit
The maximum value allowed for request parameter C<maximumRecords>.
When not provided in the constructor, it is derived from the maximum limit of your catmandu bag (see L<Catmandu::Searchable#maximum_limit>)
=item record_schemas
An array of all supported record schemas. Each item in the array is an object with attributes:
* identifier - The SRU identifier for the schema (see L<http://www.loc.gov/standards/sru/recordSchemas/>)
* name - A short descriptive name for the schema
* fix - Optionally an array of fixes to apply to the records before they are transformed into XML
* template - The path to a Template Toolkit file to transform your records into this format
=item template_options
An optional hash of configuration options that will be passed to L<Catmandu::Exporter::Template> or L<Template>
=item content_type
Set a custom content type header, the default is C<text/xml>.
=item title
Title shown in databaseInfo
=item description
Description shown in databaseInfo
=item default_search_params
Extra search parameters added during search in your catmandu bag:
$bag->search(
%{$self->default_search_params},
cql_query => $cql,
sru_sortkeys => $request->sortKeys,
limit => $limit,
start => $first - 1,
);
Must be a hash reference
Note that search parameter C<cql_query>, C<sru_sortkeys>, C<limit> and C<start> are overwritten
=back
As this is meant as a drop in replacement for L<Dancer::Plugin::Catmandu::SRU> all arguments should be the same.
So all arguments can be taken from your previous dancer plugin configuration, if necessary:
use Dancer;
use Catmandu;
use Plack::Builder;
use Plack::App::Catmandu::SRU;
my $dancer_app = sub {
Dancer->dance(Dancer::Request->new(env => $_[0]));
};
builder {
enable 'ReverseProxy';
enable '+Dancer::Middleware::Rebase', base => Catmandu->config->{uri_base}, strip => 1;
mount "/sru" => Plack::App::Catmandu::SRU->new(
%{config->{plugins}->{'Catmandu::SRU'}}
)->to_app;
mount "/" => builder {
# only create session cookies for dancer application
enable "Session";
mount '/' => $dancer_app;
};
};
=head1 METHODS
( run in 1.536 second using v1.01-cache-2.11-cpan-b301d465b3d )