Skip to content

Instantly share code, notes, and snippets.

@mdom

mdom/tazxslt

Last active Dec 18, 2018
Embed
What would you like to do?
#!/usr/bin/env perl
use Mojolicious::Lite;
use Mojo::IOLoop;
use XML::LibXSLT;
use XML::LibXML;
get '/*path' => sub {
my $c = shift;
my $headers = $c->req->headers;
my $host = $headers->header('X-Taz-Proxy-To') || $headers->header('Host');
my $xml_url =
Mojo::URL->new->host($host)->path( $c->stash('path') )->scheme('http');
my $stylesheet_url = $headers->header('X-TazXSLT-Stylesheet');
$c->ua->max_redirects(5);
my $p1 = $c->ua->get_p( $xml_url => $headers->to_hash );
my $p2 = $c->ua->get_p($stylesheet_url);
Mojo::Promise->all( $p1, $p2 )->then(
sub {
my ( $p1, $p2 ) = map { $_->[0]->result } @_;
if ( !$c->is_transformable($p1) ) {
$c->tx->res($p1);
return $c->rendered;
}
my $res = {};
my $req = {};
$req->{headers} = $c->req->headers->to_hash;
$req->{params} = $c->req->query_params->to_hash;
my $xml_body = $p1->body;
my $xslt_body = $p2->body;
Mojo::IOLoop->subprocess(
sub {
my $subprocess = shift;
my $xslt = XML::LibXSLT->new;
my $p = XML::LibXML->new;
$p->load_catalog('catalog.xml');
my $xml_dom = $p->load_xml( string => $xml_body );
my $xslt_dom = $p->load_xml(
string => $xslt_body,
URI => $stylesheet_url
);
my $stylesheet = $xslt->parse_stylesheet($xslt_dom);
register_elements( $stylesheet, $res, $req );
return $stylesheet->transform( $xml_dom, xslt_variables() );
},
sub {
my ( $subprocess, $err, $xml ) = @_;
$c->reply->exception($err) and return if $err;
return $c->render( text => $xml );
}
);
}
)->catch(
sub {
my $error = shift;
return $c->reply->exception($error);
}
);
};
helper is_transformable => sub {
my ( $c, $res ) = @_;
return 0
if $res->is_redirect
|| !$res->is_success
|| $c->req->method eq 'HEAD'
|| ( defined $res->headers->content_length
&& $res->headers->content_length == 0 );
return 1;
};
sub register_elements {
my ( $xslt_dom, $req, $res ) = @_;
$xslt_dom->register_element( 'http://www.mod-xslt2.com/ns/1.0',
'header-set', sub { return; } );
$xslt_dom->register_function(
'http://taz.de/xmlns/tazxslt/http_response',
'header',
sub {
$res->{headers}->{ $_[0] } = $_[1];
}
);
$xslt_dom->register_function(
'http://taz.de/xmlns/tazxslt/http_response',
'code',
sub {
$res->{code} = $_[0];
}
);
$xslt_dom->register_element(
'http://www.mod-xslt2.com/ns/1.0',
'value-of',
sub {
my $string = $_[2]->getAttribute("select");
return XML::LibXML::Text->new( replace_header( $req, $string ) );
}
);
return;
}
sub xslt_variables {
return XML::LibXSLT::xpath_to_string(
'modxslt-name' => 'tazxslt',
'modxslt-version' => '2.0',
);
}
sub replace_header {
my ( $req, $string ) = @_;
$string =~ s/ \$HEADER\[(.*?)\] / $req->{headers}->{$1} || '' /xge;
$string =~ s/ \$GET\[(.*?)\] / $req->{params}->{$1} || '' /xge;
return $string;
}
app->start;
__END__
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment