Plack::App::SeeAlso - SeeAlso Server as PSGI application


version 0.14


    # create SeeAlso server with code reference
    use Plack::App::SeeAlso;
    my $app = Plack::App::SeeAlso->new(
        Query => sub {
            my $id = shift;
            return unless $id =~ /:/; # return undef for empty response

            # ... create and return response
            return [ $id, [ "label" ],
                          [ "hello" ],
                          [ "" ] ];

            # ... alternatively create with 'push_seealso'
            push_seealso [$id], "label", "hello", "";
        }, ShortName => 'My Server'

    # create SeeAlso server as subclass
    use parent 'Plack::App::SeeAlso';

    our $ShortName   = 'My Server';
    our $Contact     = '';
    our $Description = '...';

    sub query {
        my ($self, $id) = @_;
        my $response = ...; # your code
        return $response;

To implement a SeeAlso server with this module, just provide a query function:

    $ echo 'use Plack::App::SeeAlso;
    Plack::App::SeeAlso->new( Query => sub {
        my $id = shift;
        return unless $id =~ /:/;
        # ...
        return [ $id, [ "label" ], [ "hello" ], [ "" ] ];
    } );' > app.psgi

    $ plackup app.psgi &
    HTTP::Server::PSGI: Accepting connections at http://0:5000/

    $ curl 'http://0:5000/?format=seealso&id=foo:bar'

    $ curl 'http://0:5000/?format=seealso&id=foo&callback=bar'


This module implements a SeeAlso Linkserver Protocol server as PSGI application. SeeAlso is basically based on two HTTP protocols, unAPI and OpenSearch (in detail Open Search Suggestions for the response format and Open Search Description Documents for the service description).

You can simply implement a SeeAlso server by creating an instance of Plack::App::SeeAlso or by deriving from this class and implementing the query method. Errors in the query method (including invalid SeeAlso responses) are catched and printed to the error stream, so on failure an empty SeeAlso response is returned.

This module contains a SeeAlso client in form of three files (seealso.js, seealso.xsl, and seealso.css). The client is served if no format-parameter was given, so you automatically get a nice, human readable interface for your SeeAlso server, for instance for debugging.


new ( [ %properties ] )

Creates a new SeeAlso server. The following optional properties are supported, most of them to be used as OpenSearch description elements. Default values are taken from package variables of same name, so instead of passing properties to the constructor you can also set for instance $Plack::App::SeeAlso::Contact or say our $Contact = "..." in your subclass of Plack::App::SeeAlso.


A code reference to be used as query method.


Short name of the server (truncated to 16 characters).


Long name of the server (truncated to 48 characters).


Verbal description of the server (truncated to 1024 characters).


An email address at which the maintainer of the server can be reached.


Human-readable name or identifier of the creator or maintainer of the server.


A set of words that are used as keywords to identify and categorize the server. Tags must be a single word and are delimited by the space character (truncated to 256 characters).


A list of all sources or entities that should be credited for the content contained in the search feed (truncated to 256 characters).


Verbal description of the source of the server (Dublin Core element Source).


Timestamp of last modification of the server (qualified Dublin Core element Date.Modified).


A list of hash reference with id examples and optional response data, such as the following structure:

      { id => 'foo' },
      { id => 'bar',
        response => [ 'bar', ['label'],['description'],['uri'] ] }

By default, an client interface is returned at /seealso.xsl, /seealso.js, and /seealso.css. A link to the interface is added if no format parameter was given. You can disable this interface by setting the Stylesheet option to undef or you set it to some URL of another XSLT file.


A hash reference with additional formats, to be used with Plack::App::unAPI.


A base URL to be send in the seealso-query-base processing-instruction. Set to the HTTP query base by default. One may need to adjust this if the server runs behind a proxy.

The OpenSearch description element Url is set automatically. The elements SyndicationRight, AdultContent, Language, InputEncoding, and OutputEncoding are not supported yet.

query ( $identifier )

If you subclass this module, you are expected to implement a query method. The method receives a defined identifier (set to the empty string by default) as an argument and is expected to return either an Open Search Suggestions response or undef. An Open Search Suggestions response is an array reference with two to three elements:

  • The first element is the identifier, possibly normalized.

  • The second element is an array reference with labels as strings.

  • The third element is an array reference with descriptions as strings.

  • The fourth element is an arary reference with URIs as strings.


valid_seealso ( $response )

This utility function is exported on request. It can be used to validate a SeeAlso response, which must be an reference to an array of four elements (identifier, labels, descriptions, URIs), as described above. On success the function returns the response, otherwise undef.

push_seealso ( $response, $label, $description, $uri )

This utility function is exported by default. You can use it to append a single response item to a response array reference:

    $resp = [$id,[],[],[]];
    push_seealso $resp, $label, $descr, $uri;
    # $resp is now [$id,[$label],[$descr],[$uri]];


This module sets the default MIME type for .xsl files to text/xsl because browser will more likely complain otherwise. This setting is done with Plack::MIME and it may also affect other applications.


This module is basically a refactored clean-up of SeeAlso::Server. The unAPI handling is done by module Plack::App::unAPI. An introductionary article about unAPI can be found at


Jakob Voß


This software is copyright (c) 2014 by Jakob Voß.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.