The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Mojolicious::Plugin::WebFinger - Serve and Retrieve WebFinger Documents

SYNOPSIS

  # Mojolicious
  $app->plugin('WebFinger');

  # Mojolicious::Lite
  plugin 'WebFinger';

  # Serves XRD or JRD from /.well-known/webfinger

  # Discover WebFinger resources the blocking ...
  print $c->webfinger('acct:bob@example.com')
          ->link('describedby')
          ->attrs('href');

  # ... or non-blocking way
  $c->webfinger('acct:bob@example.com' => sub {
    my ($xrd, $header) = @_;
    # ...
  });

DESCRIPTION

Mojolicious::Plugin::WebFinger provides several functions for the WebFinger Protocol. It supports .well-known/webfinger discovery as well as Host-Meta and works with both XRD and JRD.

This module is an early release! There may be significant changes in the future.

METHODS

register

  # Mojolicious
  $app->plugin(WebFinger => {
    expires => 100,
    secure  => 1
  });

  # Mojolicious::Lite
  plugin 'WebFinger';

Called when registering the plugin. Accepts the optional parameters secure, which is a boolean value which indicates that only secure transactions are allowed, and expires, which is the number of seconds the served WebFinger document should be cached by the fetching client (defaults to 10 days). These parameters can be either set on registration or as part of the configuration file with the key WebFinger.

HELPERS

webfinger

  # In Controllers:
  my $xrd = $self->webfinger('acct:me@sojolicio.us');

  # Only secure discovery
  my $xrd = $self->webfinger('acct:me@sojolicio.us', -secure);

  # Use lrdd with host and resource description
  my $xrd = $self->webfinger(
    'sojolicio.us' => 'http://sojolicio.us/me.html', -secure
  );

  # Use rel parameters
  my $xrd = $self->webfinger(
    'acct:me@sojolicio.us' => ['describedBy'], -secure
  );

  # Use non-blocking
  $self->webfinger(
    'acct:me@sojolicio.us' => [qw/describedBy author/] => sub {
      my $xrd = shift;
      # ...
    } => -modern);

  # Serve local WebFinger documents
  my $xrd = $self->webfinger('me');

Returns the WebFinger resource as an XRD object. Accepts the WebFinger resource, an optional array reference of relations, and an optional callback for non-blocking requests. The appended flag indicates, how the discovery should be done. -secure indicates, that discovery is allowed only over https. -modern indicates, that only /.well-known/webfinger is discovered over https. -old indicates, that only Host-Meta and lrdd discovery is used.

CALLBACKS

fetch_webfinger

  # Establish a callback
  $mojo->callback(
    fetch_webfinger=> sub {
      my ($c, $host, $res, $header) = @_;

      # Get cached document
      my $doc = $c->chi->get("webfinger-$host-$res");
      return unless $doc;

      # Get cached headers
      my $headers = $c->chi->get("webfinger-$host-$res-headers");

      # Return document
      return ($c->new_xrd($doc), Mojo::Headers->new->parse($headers));
    }
  );

This callback is released before a WebFinger document is retrieved from a foreign server. The parameters passed to the callback include the current controller object, the host's name and the resource name.

If an XRD object associated with the requested host name is returned (and optionally a Mojo::Headers object), the retrieval will stop.

This can be used for caching.

The callback can be established with the callback helper or on registration. Callbacks may be changed for non-blocking requests.

prepare_webfinger

  if ($c->callback(prepare_webfinger => sub {
    my ($c, $res) = @_;
    if ($res eq 'acct:akron@sojolicio.us') {
      $c->stash('profile' => 'http://sojolicio.us/user/akron');
      return 1;
    };
  })) {
    print 'The requested resource exists!';
  };

This callback is triggered before a WebFinger document is served. The current controller object and the requested resource is passed. A boolean value indicating the validity of the resource is expected. A rendered response in the callback will be respected and further serving won't be processed.

Data retrieved for the resource can be passed to the stash and rendered using the before_serving_webfinger hook.

The callback can be either set using the callback helper or on registration. Callbacks may be changed for non-blocking requests.

HOOKS

before_serving_webfinger

  $mojo->hook(
    before_serving_webfinger => sub {
      my ($c, $res, $xrd) = @_;
      if ($c->stash('profile')) {
        $xrd->link(profile => { href => $c->stash('profile') } );
      };
    });

This hook is run before the requested WebFinger document is served. The hook passes the current controller object, the resource name and the XRD object.

after_fetching_webfinger

  $mojo->hook(
    after_fetching_webfinger => sub {
      my ($c, $host, $res, $xrd, $headers) = @_;

      # Store document in cache
      $c->chi->set("webfinger-$host-$res" => $xrd->to_pretty_xml);

      # Store headers in cache
      $c->chi->set("webfinger-$host-$res-headers" => $headers->to_string);
    }
  );

This hook is run after a foreign WebFinger document is newly fetched. The parameters passed to the hook are the current controller object, the host name, the resource name, the XRD object and the headers object of the response.

This can be used for caching.

ROUTES

The route /.well-known/webfinger is established as the lrdd endpoint webfinger. This plugin depends on this route, and the resource and rel attributes. Although other routes are possible for WebFinger/lrdd in older drafts of the specification and different forms for the resource definition, this is assumed to be a future-proof best practice.

EXAMPLE

The examples/ folder contains a full working example application with serving and discovery. The example has an additional dependency of CHI. It can be started using the daemon, morbo or hypnotoad.

  $ perl examples/webfingerapp daemon

This example may be a good starting point for your own implementation.

A less advanced application using non-blocking requests without caching is also available in the examples/ folder. It can be started using the daemon, morbo or hypnotoad as well.

  $ perl examples/webfingerapp-async daemon

DEPENDENCIES

Mojolicious (best with SSL support), Mojolicious::Plugin::HostMeta.

AVAILABILITY

  https://github.com/Akron/Mojolicious-Plugin-WebFinger

This plugin is part of the Sojolicious project.

COPYRIGHT AND LICENSE

Copyright (C) 2011-2013, Nils Diewald.

This program is free software, you can redistribute it and/or modify it under the same terms as Perl.