Skip to content

Instantly share code, notes, and snippets.

@vti
Created August 30, 2011 15:37
Show Gist options
  • Save vti/1181195 to your computer and use it in GitHub Desktop.
Save vti/1181195 to your computer and use it in GitHub Desktop.
jsonp for metacpan
$app = Plack::Middleware::ReverseProxy->wrap($app);
$app = Plack::Middleware::RestrictedJSONP->wrap($app, path => qr{^/(?:author|release|pod)(?:$|/)});
package Plack::Middleware::RestrictedJSONP;
use strict;
use parent qw(Plack::Middleware::JSONP);
use Plack::Util;
use URI::Escape ();
use Plack::Util::Accessor qw(path);
sub call {
my ($self, $env) = @_;
my $path_match = $self->path;
my $path = $env->{PATH_INFO};
for ($path) {
my $matched = 'CODE' eq ref $path_match ? $path_match->($_) : $_ =~ $path_match;
return $self->app->($env) unless $matched;
}
my $callback_key = $self->callback_key;
# We cut off jsonp callback parameter because we don't want
# it to get to ElasticSearch (otherwise we get already wrapped
# JSONP response that metacpan tries to parse as JSON)
my $callback;
if ($env->{QUERY_STRING} =~ s/(?:^|&)$callback_key=([^&]+)//) {
my $cb = $1;
if ($cb =~ /^[\w\.\[\]\_\%]+$/) {
$callback = URI::Escape::uri_unescape($cb);
}
}
my $res = $self->app->($env);
return $res unless $callback;
$self->response_cb(
$res,
sub {
my $res = shift;
if (defined $res->[2]) {
my $h = Plack::Util::headers($res->[1]);
if ($h->get('Content-Type') =~ m!/(?:json|javascript)!) {
my $body;
Plack::Util::foreach($res->[2], sub { $body .= $_[0] });
my $jsonp = "$callback($body)";
$res->[2] = [$jsonp];
$h->set('Content-Length', length $jsonp);
$h->set('Content-Type', 'text/javascript');
}
}
}
);
}
1;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment