CONTRIBUTING000644001750001750 531712266567055 15072 0ustar00taitai000000000000HTTP-Link-Parser-0.200NAME CONTRIBUTING DESCRIPTION If you're reading this document, that means you might be thinking about helping me out with this project. Thanks! Here's some ways you could help out: * Bug reports Found a bug? Great! (Well, not so great I suppose.) The place to report them is . Don't e-mail me about it, as your e-mail is more than likely to get lost amongst the spam. An example script clearly demonstrating the bug (preferably written using Test::More) would be greatly appreciated. * Patches If you've found a bug and written a fix for it, even better! Generally speaking you should check out the latest copy of the code from the source repository rather than using the CPAN distribution. The file META.yml should contain a link to the source repository. If not, then try or submit a bug report. (As far as I'm concerned the lack of a link is a bug.) Many of my distributions are also mirrored at . To submit the patch, do a pull request on GitHub or Bitbucket, or attach a diff file to a bug report. Unless otherwise stated, I'll assume that your contributions are licensed under the same terms as the rest of the project. (If using git, feel free to work in a branch. For Mercurial, I'd prefer bookmarks within the default branch.) * Documentation If there's anything unclear in the documentation, please submit this as a bug report or patch as above. Non-toy example scripts that I can bundle would also be appreciated. * Translation Translations of documentation would be welcome. For translations of error messages and other strings embedded in the code, check with me first. Sometimes the English strings may not in a stable state, so it would be a waste of time translating them. Coding Style I tend to write using something approximating the Allman style, using tabs for indentation and Unix-style line breaks. * * I nominally encode all source files as UTF-8, though in practice most of them use a 7-bit-safe ASCII-compatible subset of UTF-8. AUTHOR Toby Inkster . COPYRIGHT AND LICENCE Copyright (c) 2012-2013 by Toby Inkster. CONTRIBUTING.pod is licensed under the Creative Commons Attribution-ShareAlike 2.0 UK: England & Wales License. To view a copy of this license, visit . COPYRIGHT000644001750001750 235412266567055 14531 0ustar00taitai000000000000HTTP-Link-Parser-0.200Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: HTTP-Link-Parser Upstream-Contact: Toby Inkster Source: https://metacpan.org/release/HTTP-Link-Parser Files: Changes META.json META.yml dist.ini doap.ttl Copyright: Copyright 2014 Toby Inkster. License: Expat Files: README lib/HTTP/Link/Parser.pm t/02rdf.t Copyright: Copyright (C) 2009-2011, 2014 by Toby Inkster. License: Expat Files: COPYRIGHT CREDITS SIGNATURE Copyright: None License: public-domain Files: CONTRIBUTING INSTALL LICENSE Copyright: Unknown License: Unknown Files: t/01basic.t Copyright: Copyright (C) 2014 by Toby Inkster. License: Expat Files: Makefile.PL Copyright: Copyright 2013 Toby Inkster. License: GPL-1.0+ or Artistic-1.0 License: Expat This software is Copyright (c) 2014 by Toby Inkster. This is free software, licensed under: The MIT (X11) License License: Artistic-1.0 This software is Copyright (c) 2014 by the copyright holder(s). This is free software, licensed under: The Artistic License 1.0 License: GPL-1.0 This software is Copyright (c) 2014 by the copyright holder(s). This is free software, licensed under: The GNU General Public License, Version 1, February 1989 CREDITS000644001750001750 5712266567053 14212 0ustar00taitai000000000000HTTP-Link-Parser-0.200Maintainer: - Toby Inkster Changes000644001750001750 216612266567053 14530 0ustar00taitai000000000000HTTP-Link-Parser-0.200HTTP-Link-Parser ================ Created: 2009-10-09 Home page: Bug tracker: Maintainer: Toby Inkster 0.200 2014-01-18 [ Documentation ] - Copyright 2014. [ Packaging ] - use Dist::Inkt. [ Other ] - Make RDF::Trine dependency optional. 0.103 2011-12-04 [ Bug Fixes ] - Newer version of Module::Package::RDF. 0.102 2011-11-27 [ Packaging ] - Module::Package::RDF [ Other ] - Minor tidy - Updated: use 5.010 0.101 2011-02-19 - Minor cleanups. - Updated: Copyright 2011. 0.100 2010-06-26 - Updated: Let the Content-Language header provide a default language for the 'title' property. 0.05 2010-02-07 - Clean up @EXPORT and @EXPORT_OK. - General documentation improvements. - Rename parse_header to parse_single_link, and document this. - Updated: Copyright 2010. - Updated: Use my new build system. 0.04 2009-12-15 - Added: Support the 'title*' parameter. 0.03 2009-11-28 - Added: Provide an RDF::Trine::Model 0.02 2009-11-24 0.01 2009-10-09 First release INSTALL000644001750001750 172112266567052 14261 0ustar00taitai000000000000HTTP-Link-Parser-0.200 Installing HTTP-Link-Parser should be straightforward. INSTALLATION WITH CPANMINUS If you have cpanm, you only need one line: % cpanm HTTP::Link::Parser If you are installing into a system-wide directory, you may need to pass the "-S" flag to cpanm, which uses sudo to install the module: % cpanm -S HTTP::Link::Parser INSTALLATION WITH THE CPAN SHELL Alternatively, if your CPAN shell is set up, you should just be able to do: % cpan HTTP::Link::Parser MANUAL INSTALLATION As a last resort, you can manually install it. Download the tarball and unpack it. Consult the file META.json for a list of pre-requisites. Install these first. To build HTTP-Link-Parser: % perl Makefile.PL % make && make test Then install it: % make install If you are installing into a system-wide directory, you may need to run: % sudo make install LICENSE000644001750001750 220712266567052 14235 0ustar00taitai000000000000HTTP-Link-Parser-0.200This software is Copyright (c) 2014 by Toby Inkster. This is free software, licensed under: The MIT (X11) License The MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. MANIFEST000644001750001750 26012266567055 14341 0ustar00taitai000000000000HTTP-Link-Parser-0.200CONTRIBUTING COPYRIGHT CREDITS Changes INSTALL LICENSE MANIFEST META.json META.yml Makefile.PL README SIGNATURE dist.ini doap.ttl lib/HTTP/Link/Parser.pm t/01basic.t t/02rdf.t META.json000644001750001750 402212266567055 14651 0ustar00taitai000000000000HTTP-Link-Parser-0.200{ "abstract" : "parse HTTP Link headers", "author" : [ "Toby Inkster " ], "dynamic_config" : 0, "generated_by" : "Dist::Inkt::Profile::TOBYINK version 0.013, CPAN::Meta::Converter version 2.120921", "keywords" : [ "HTTP", "Link", "RDF", "RFC5988", "Relationships", "Semantics", "rel" ], "license" : [ "mit" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : "2" }, "name" : "HTTP-Link-Parser", "no_index" : { "directory" : [ "eg", "examples", "inc", "t", "xt" ] }, "optional_features" : {}, "prereqs" : { "configure" : { "requires" : { "ExtUtils::MakeMaker" : "6.17" } }, "runtime" : { "requires" : { "HTTP::Message" : "0", "URI" : "0", "URI::Escape" : "0", "perl" : "5.010" }, "suggests" : { "RDF::Trine" : "0.135" } }, "test" : { "recommends" : { "RDF::Trine" : "0.135" }, "requires" : { "Test::More" : "0.96" } } }, "provides" : { "HTTP::Link::Parser" : { "file" : "lib/HTTP/Link/Parser.pm", "version" : "0.200" }, "HTTP::Link::Parser::PlainLiteral" : { "file" : "lib/HTTP/Link/Parser.pm" } }, "release_status" : "stable", "resources" : { "X_identifier" : "http://purl.org/NET/cpan-uri/dist/HTTP-Link-Parser/project", "bugtracker" : { "web" : "http://rt.cpan.org/Dist/Display.html?Queue=HTTP-Link-Parser" }, "homepage" : "https://metacpan.org/release/HTTP-Link-Parser", "license" : [ "http://www.opensource.org/licenses/mit-license.php" ], "repository" : { "type" : "git", "web" : "https://github.com/tobyink/p5-http-link-parser" } }, "version" : "0.200" } META.yml000644001750001750 224612266567054 14506 0ustar00taitai000000000000HTTP-Link-Parser-0.200--- abstract: 'parse HTTP Link headers' author: - 'Toby Inkster ' build_requires: Test::More: 0.96 configure_requires: ExtUtils::MakeMaker: 6.17 dynamic_config: 0 generated_by: 'Dist::Inkt::Profile::TOBYINK version 0.013, CPAN::Meta::Converter version 2.120921' keywords: - HTTP - Link - RDF - RFC5988 - Relationships - Semantics - rel license: mit meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: 1.4 name: HTTP-Link-Parser no_index: directory: - eg - examples - inc - t - xt optional_features: {} provides: HTTP::Link::Parser: file: lib/HTTP/Link/Parser.pm version: 0.200 HTTP::Link::Parser::PlainLiteral: file: lib/HTTP/Link/Parser.pm version: 0 requires: HTTP::Message: 0 URI: 0 URI::Escape: 0 perl: 5.010 resources: X_identifier: http://purl.org/NET/cpan-uri/dist/HTTP-Link-Parser/project bugtracker: http://rt.cpan.org/Dist/Display.html?Queue=HTTP-Link-Parser homepage: https://metacpan.org/release/HTTP-Link-Parser license: http://www.opensource.org/licenses/mit-license.php repository: https://github.com/tobyink/p5-http-link-parser version: 0.200 Makefile.PL000644001750001750 1230012266567055 15220 0ustar00taitai000000000000HTTP-Link-Parser-0.200use strict; use ExtUtils::MakeMaker 6.17; my $EUMM = eval( $ExtUtils::MakeMaker::VERSION ); my $meta = { "abstract" => "parse HTTP Link headers", "author" => ["Toby Inkster "], "dynamic_config" => 0, "generated_by" => "Dist::Inkt::Profile::TOBYINK version 0.013, CPAN::Meta::Converter version 2.120921", "keywords" => [ "HTTP", "Link", "RDF", "RFC5988", "Relationships", "Semantics", "rel", ], "license" => ["mit"], "meta-spec" => { url => "http://search.cpan.org/perldoc?CPAN::Meta::Spec", version => 2, }, "name" => "HTTP-Link-Parser", "no_index" => { directory => ["eg", "examples", "inc", "t", "xt"] }, "prereqs" => { configure => { requires => { "ExtUtils::MakeMaker" => 6.17 } }, runtime => { requires => { "HTTP::Message" => 0, "perl" => "5.010", "URI" => 0, "URI::Escape" => 0 }, suggests => { "RDF::Trine" => 0.135 }, }, test => { recommends => { "RDF::Trine" => 0.135 }, requires => { "Test::More" => 0.96 }, }, }, "provides" => { "HTTP::Link::Parser" => { file => "lib/HTTP/Link/Parser.pm", version => "0.200" }, "HTTP::Link::Parser::PlainLiteral" => { file => "lib/HTTP/Link/Parser.pm", version => 0 }, }, "release_status" => "stable", "resources" => { bugtracker => { web => "http://rt.cpan.org/Dist/Display.html?Queue=HTTP-Link-Parser", }, homepage => "https://metacpan.org/release/HTTP-Link-Parser", license => ["http://www.opensource.org/licenses/mit-license.php"], repository => { type => "git", web => "https://github.com/tobyink/p5-http-link-parser", }, X_identifier => "http://purl.org/NET/cpan-uri/dist/HTTP-Link-Parser/project", }, "version" => "0.200", }; my %dynamic_config; my %WriteMakefileArgs = ( ABSTRACT => $meta->{abstract}, AUTHOR => ($EUMM >= 6.5702 ? $meta->{author} : $meta->{author}[0]), DISTNAME => $meta->{name}, VERSION => $meta->{version}, EXE_FILES => [ map $_->{file}, values %{ $meta->{x_provides_scripts} || {} } ], NAME => do { my $n = $meta->{name}; $n =~ s/-/::/g; $n }, %dynamic_config, ); $WriteMakefileArgs{LICENSE} = $meta->{license}[0] if $EUMM >= 6.3001; sub deps { my %r; for my $stage (@_) { for my $dep (keys %{$meta->{prereqs}{$stage}{requires}}) { next if $dep eq 'perl'; my $ver = $meta->{prereqs}{$stage}{requires}{$dep}; $r{$dep} = $ver if !exists($r{$dep}) || $ver >= $r{$dep}; } } \%r; } my ($build_requires, $configure_requires, $runtime_requires, $test_requires); if ($EUMM >= 6.6303) { $WriteMakefileArgs{BUILD_REQUIRES} ||= deps('build'); $WriteMakefileArgs{CONFIGURE_REQUIRES} ||= deps('configure'); $WriteMakefileArgs{TEST_REQUIRES} ||= deps('test'); $WriteMakefileArgs{PREREQ_PM} ||= deps('runtime'); } elsif ($EUMM >= 6.5503) { $WriteMakefileArgs{BUILD_REQUIRES} ||= deps('build', 'test'); $WriteMakefileArgs{CONFIGURE_REQUIRES} ||= deps('configure'); $WriteMakefileArgs{PREREQ_PM} ||= deps('runtime'); } elsif ($EUMM >= 6.52) { $WriteMakefileArgs{CONFIGURE_REQUIRES} ||= deps('configure'); $WriteMakefileArgs{PREREQ_PM} ||= deps('runtime', 'build', 'test'); } else { $WriteMakefileArgs{PREREQ_PM} ||= deps('configure', 'build', 'test', 'runtime'); } { my ($minperl) = reverse sort( grep defined && /^[0-9]+(\.[0-9]+)?$/, map $meta->{prereqs}{$_}{requires}{perl}, qw( configure build runtime ) ); if (defined($minperl)) { die "Installing $meta->{name} requires Perl >= $minperl" unless $] >= $minperl; $WriteMakefileArgs{MIN_PERL_VERSION} ||= $minperl if $EUMM >= 6.48; } } sub FixMakefile { return unless -d 'inc'; my $file = shift; local *MAKEFILE; open MAKEFILE, "< $file" or die "FixMakefile: Couldn't open $file: $!; bailing out"; my $makefile = do { local $/; }; close MAKEFILE or die $!; $makefile =~ s/\b(test_harness\(\$\(TEST_VERBOSE\), )/$1'inc', /; $makefile =~ s/( -I\$\(INST_ARCHLIB\))/ -Iinc$1/g; $makefile =~ s/( "-I\$\(INST_LIB\)")/ "-Iinc"$1/g; $makefile =~ s/^(FULLPERL = .*)/$1 "-Iinc"/m; $makefile =~ s/^(PERL = .*)/$1 "-Iinc"/m; open MAKEFILE, "> $file" or die "FixMakefile: Couldn't open $file: $!; bailing out"; print MAKEFILE $makefile or die $!; close MAKEFILE or die $!; } my $mm = WriteMakefile(%WriteMakefileArgs); FixMakefile($mm->{FIRST_MAKEFILE} || 'Makefile'); exit(0); README000644001750001750 1155612266567052 14137 0ustar00taitai000000000000HTTP-Link-Parser-0.200NAME HTTP::Link::Parser - parse HTTP Link headers SYNOPSIS use HTTP::Link::Parser ':standard'; use LWP::UserAgent; my $ua = LWP::UserAgent->new; my $response = $ua->get("http://example.com/foo"); # Parse link headers into an RDF::Trine::Model. my $model = parse_links_into_model($response); # Find data about . my $iterator = $model->get_statements( RDF::Trine::Node::Resource->new('http://example.com/foo'), undef, undef); while ($statement = $iterator->next) { # Skip data where the value is not a resource (i.e. link) next unless $statement->object->is_resource; printf("Link to <%s> with rel=\"%s\".\n", $statement->object->uri, $statement->predicate->uri); } DESCRIPTION HTTP::Link::Parser parses HTTP "Link" headers found in an HTTP::Response object. Headers should conform to the format described in RFC 5988. Functions To export all functions: use HTTP::Link::Parser ':all'; `parse_links_into_model($response, [$existing_model])` Takes an HTTP::Response object (or in fact, any HTTP::Message object) and returns an RDF::Trine::Model containing link data extracted from the response. Dublin Core is used to encode 'hreflang', 'title' and 'type' link parameters. $existing_model is an RDF::Trine::Model to add data to. If omitted, a new, empty model is created. `parse_links_to_rdfjson($response)` Returns a hashref with a structure inspired by the RDF/JSON specification. This can be thought of as a shortcut for: parse_links_into_model($response)->as_hashref But it's faster as no intermediate model is built. `relationship_uri($short)` This function is not exported by default. It may be used to convert short strings identifying relationships, such as "next" and "prev", into longer URIs identifying the same relationships, such as "http://www.iana.org/assignments/relation/next" and "http://www.iana.org/assignments/relation/prev". If passed a string which is a URI already, simply returns it as-is. Internal Functions These are really just internal implementations, but you can use them if you like. `parse_links_to_list($response)` This function is not exported by default. Returns an arrayref of hashrefs. Each hashref contains keys corresponding to the link parameters of the link, and a key called 'URI' corresponding to the target of the link. The 'rel' and 'rev' keys are arrayrefs containing lists of relationships. If the Link used the short form of a registered relationship, then the short form is present on this list. Short forms can be converted to long forms (URIs) using the `relationship_uri` function. The structure returned by this function should not be considered stable. `parse_single_link($link, $base, [$default_lang])` This function is not exported by default. This parses a single Link header (minus the "Link:" bit itself) into a hashref structure. A base URI must be included in case the link contains relative URIs. A default language can be provided for the 'title' parameter. The structure returned by this function should not be considered stable. BUGS Please report any bugs to . SEE ALSO . RDF::Trine, HTTP::Response, XRD::Parser, HTTP::LRDD. . . AUTHOR Toby Inkster . COPYRIGHT AND LICENCE Copyright (C) 2009-2011, 2014 by Toby Inkster Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. SIGNATURE000644001750001750 314212266567055 14516 0ustar00taitai000000000000HTTP-Link-Parser-0.200This file contains message digests of all files listed in MANIFEST, signed via the Module::Signature module, version 0.70. To verify the content in this distribution, first make sure you have Module::Signature installed, then type: % cpansign -v It will check each file's integrity, as well as the signature's validity. If "==> Signature verified OK! <==" is not displayed, the distribution may already have been compromised, and you should not run its Makefile.PL or Build.PL. -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 SHA1 294505f858f11dd062e9916e3f50d88210a9ef54 CONTRIBUTING SHA1 1ba79b96d4d2098c7dba3943b7ac4ebe102fc17f COPYRIGHT SHA1 4a475a6a4c60c03a6352ec84ae84ca3d03280f81 CREDITS SHA1 32a2982f394da15b0d7fc916d48d05653b3d716c Changes SHA1 d4ccb5eb6234586d8787ef894964d21588f2b771 INSTALL SHA1 533f33316733b851649aa6b7043c286b29e4463b LICENSE SHA1 80a3479b5e88f8ce70e47837682aa677d8035138 MANIFEST SHA1 1bda83fc1fbc3267e43b1b3491e896a86da8e1de META.json SHA1 713ab55a47f0a59fd578ad918c755fa063fc35b6 META.yml SHA1 f3e04eec1abab59edb61772f536d91f020b388b9 Makefile.PL SHA1 ff78a45e6c0cb41ed3299a693d7e1fcd3564526d README SHA1 0f5f3eb7ab409e6a320cad7a58cae0fc2a59ba73 dist.ini SHA1 ac6b83c2a0c6e9b5e4b9185c0ed6e122faecbc32 doap.ttl SHA1 9b2be57c9ef912223bb1850bb71c6942485195b1 lib/HTTP/Link/Parser.pm SHA1 1b6cada68c2580a0c938f803c54c185681db3b18 t/01basic.t SHA1 3d67c77ff8e99b4f52cfc32419cbab1dc36cc3d8 t/02rdf.t -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.14 (GNU/Linux) iEYEARECAAYFAlLa7i0ACgkQzr+BKGoqfTkLEACeOZh6G/AAvxrNtwe41pengKZb PC0AoKt6t/8hKBC1mss0Y93lQiOhqN1Q =MKPc -----END PGP SIGNATURE----- dist.ini000644001750001750 10212266567052 14644 0ustar00taitai000000000000HTTP-Link-Parser-0.200;;class='Dist::Inkt::Profile::TOBYINK' ;;name='HTTP-Link-Parser' doap.ttl000644001750001750 2026712266567054 14730 0ustar00taitai000000000000HTTP-Link-Parser-0.200@prefix dc: . @prefix doap: . @prefix doap-changeset: . @prefix doap-deps: . @prefix foaf: . @prefix owl: . @prefix rdfs: . @prefix xsd: . a doap:Project; doap-deps:runtime-requirement [ doap-deps:on "perl 5.010"^^doap-deps:CpanId ], [ doap-deps:on "HTTP::Message"^^doap-deps:CpanId ], [ doap-deps:on "URI"^^doap-deps:CpanId ], [ doap-deps:on "URI::Escape"^^doap-deps:CpanId ]; doap-deps:runtime-suggestion [ doap-deps:on "RDF::Trine 0.135"^^doap-deps:CpanId ]; doap-deps:test-recommendation [ doap-deps:on "RDF::Trine 0.135"^^doap-deps:CpanId ]; doap-deps:test-requirement [ doap-deps:on "Test::More 0.96"^^doap-deps:CpanId ]; doap:bug-database ; doap:category [ rdfs:label "Link" ], [ rdfs:label "RDF" ], [ rdfs:label "Semantics" ], [ rdfs:label "Relationships" ], [ rdfs:label "rel" ], [ rdfs:label "RFC5988" ], [ rdfs:label "HTTP" ]; doap:created "2009-10-09"^^xsd:date; doap:developer ; doap:documenter ; doap:download-page ; doap:homepage ; doap:license ; doap:maintainer ; doap:name "HTTP-Link-Parser"; doap:programming-language "Perl"; doap:release , , , , , , , , , ; doap:repository [ a doap:GitRepository; doap:browse ; ]; doap:shortdesc "parse HTTP Link headers"@en; doap:tester . a doap:Version; rdfs:label "First release"@en; dc:issued "2009-10-09"^^xsd:date; doap:file-release ; doap:revision "0.01"^^xsd:string. a doap:Version; dc:issued "2009-11-24"^^xsd:date; doap:file-release ; doap:revision "0.02"^^xsd:string. a doap:Version; dc:issued "2009-11-28"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Addition; rdfs:label "Provide an RDF::Trine::Model"@en; ]; doap-changeset:versus ; ]; doap:file-release ; doap:revision "0.03"^^xsd:string. a doap:Version; dc:issued "2009-12-15"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Addition; rdfs:label "Support the 'title*' parameter."@en; ]; doap-changeset:versus ; ]; doap:file-release ; doap:revision "0.04"^^xsd:string. a doap:Version; dc:issued "2010-02-07"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ rdfs:label "Rename parse_header to parse_single_link, and document this."@en; ], [ rdfs:label "Clean up @EXPORT and @EXPORT_OK."@en ], [ a doap-changeset:Update; rdfs:label "Copyright 2010."@en; ], [ a doap-changeset:Update; rdfs:label "Use my new build system."@en; ], [ rdfs:label "General documentation improvements."@en; ]; doap-changeset:versus ; ]; doap:file-release ; doap:revision "0.05"^^xsd:string. a doap:Version; dc:issued "2010-06-26"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Update; rdfs:label "Let the Content-Language header provide a default language for the 'title' property."@en; ]; doap-changeset:versus ; ]; doap:file-release ; doap:revision "0.100"^^xsd:string. a doap:Version; dc:issued "2011-02-19"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ rdfs:label "Minor cleanups."@en ], [ a doap-changeset:Update; rdfs:label "Copyright 2011."@en; ]; doap-changeset:versus ; ]; doap:file-release ; doap:revision "0.101"^^xsd:string. a doap:Version; dc:issued "2011-11-27"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Update; rdfs:label "use 5.010"@en; ], [ rdfs:label "Minor tidy"@en ], [ a doap-changeset:Packaging; rdfs:label "Module::Package::RDF"@en; ]; doap-changeset:versus ; ]; doap:file-release ; doap:revision "0.102"^^xsd:string. a doap:Version; dc:issued "2011-12-04"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Bugfix, doap-changeset:Packaging; rdfs:label "Newer version of Module::Package::RDF."@en; ]; doap-changeset:versus ; ]; doap:file-release ; doap:revision "0.103"^^xsd:string. a doap:Version; dc:issued "2014-01-18"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Packaging, doap-changeset:Update; rdfs:label "use Dist::Inkt."@en; ], [ a doap-changeset:Change; rdfs:label "Make RDF::Trine dependency optional."@en; ], [ a doap-changeset:Documentation, doap-changeset:Update; rdfs:label "Copyright 2014."@en; ]; doap-changeset:versus ; ]; doap:file-release ; doap:revision "0.200"^^xsd:string. a foaf:Person; foaf:homepage ; foaf:mbox ; foaf:name "Toby Inkster"; foaf:page ; owl:sameAs . 01basic.t000644001750001750 665412266567052 15114 0ustar00taitai000000000000HTTP-Link-Parser-0.200/t=pod =encoding utf-8 =head1 PURPOSE Check HTTP Link headers can be parsed. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE Copyright (C) 2014 by Toby Inkster Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. =cut use strict; use warnings; use Test::More tests => 1; use HTTP::Link::Parser (); # Create a test response to parse. use HTTP::Response; my $response = HTTP::Response->new( 200 ); $response->push_header("Base" => "http://example.org/subject"); $response->push_header("Link" => "; rel=\"http://example.net/rel/one http://example.net/rel/two\"; title=\"absolute\""); $response->push_header("Link" => "; rel=\"three\"; title=\"relative\""); $response->push_header("Link" => "; rel=\"next\"; title=\"relative\"; type=\"TEXT/HTML\"; hreflang=en"); $response->push_header("Link" => "; rel=\"prev\"; title=\"subject\"; anchor=\"nextdoc\""); $response->push_header("Link" => "; rev=\"made\"; title=\"author\";"); $response->push_header("Link" => "; rev=\"test\"; title=\"nachstes Kapitel\"; title*=UTF-8'de'n%c3%a4chstes%20Kapitel"); my @data = sort { $a->{URI} cmp $b->{URI} } @{ HTTP::Link::Parser::parse_links_to_list($response) }; is_deeply( \@data, [ { 'URI' => bless( do{\(my $o = 'http://example.net/absolute')}, 'URI::http' ), 'rel' => [ 'http://example.net/rel/one', 'http://example.net/rel/two' ], 'title' => 'absolute' }, { 'URI' => bless( do{\(my $o = 'http://example.org/author')}, 'URI::http' ), 'rev' => [ 'made' ], 'title' => 'author' }, { 'URI' => bless( do{\(my $o = 'http://example.org/german-page')}, 'URI::http' ), 'rev' => [ 'test' ], 'title' => 'nachstes Kapitel', 'title*' => [ bless( [ "n\x{e4}chstes Kapitel", undef, 'de' ], 'HTTP::Link::Parser::PlainLiteral' ) ] }, { 'URI' => bless( do{\(my $o = 'http://example.org/nextdoc')}, 'URI::http' ), 'hreflang' => [ 'en' ], 'rel' => [ 'next' ], 'title' => 'relative', 'type' => 'TEXT/HTML' }, { 'URI' => bless( do{\(my $o = 'http://example.org/relative')}, 'URI::http' ), 'rel' => [ 'three' ], 'title' => 'relative' }, { 'URI' => bless( do{\(my $o = 'http://example.org/subject')}, 'URI::http' ), 'anchor' => bless( do{\(my $o = 'http://example.org/nextdoc')}, 'URI::http' ), 'rel' => [ 'prev' ], 'title' => 'subject' }, ], ) or diag explain(\@data); 02rdf.t000644001750001750 1223012266567052 14612 0ustar00taitai000000000000HTTP-Link-Parser-0.200/t=pod =encoding utf-8 =head1 PURPOSE Check HTTP Link headers can be parsed to an RDF model. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE Copyright (C) 2009-2011, 2014 by Toby Inkster Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. =cut use strict; use warnings; use Test::More; BEGIN { eval { require RDF::Trine } ? plan(tests => 11) : plan(skip_all => "requires RDF::Trine") }; use HTTP::Link::Parser (); # Create a test response to parse. use HTTP::Response; my $response = HTTP::Response->new( 200 ); $response->push_header("Base" => "http://example.org/subject"); $response->push_header("Link" => "; rel=\"http://example.net/rel/one http://example.net/rel/two\"; title=\"absolute\""); $response->push_header("Link" => "; rel=\"three\"; title=\"relative\""); $response->push_header("Link" => "; rel=\"next\"; title=\"relative\"; type=\"TEXT/HTML\"; hreflang=en"); $response->push_header("Link" => "; rel=\"prev\"; title=\"subject\"; anchor=\"nextdoc\""); $response->push_header("Link" => "; rev=\"made\"; title=\"author\";"); $response->push_header("Link" => "; rev=\"test\"; title=\"nachstes Kapitel\"; title*=UTF-8'de'n%c3%a4chstes%20Kapitel"); my $M = HTTP::Link::Parser::parse_links_into_model($response); ok( $M->count_statements( RDF::Trine::Node::Resource->new('http://example.org/subject'), RDF::Trine::Node::Resource->new('http://example.net/rel/one'), RDF::Trine::Node::Resource->new('http://example.net/absolute'), ), "absolute relationships", ); ok( $M->count_statements( RDF::Trine::Node::Resource->new('http://example.org/subject'), RDF::Trine::Node::Resource->new('http://www.iana.org/assignments/relation/three'), RDF::Trine::Node::Resource->new('http://example.org/relative'), ), "relative relationships", ); ok( $M->count_statements( RDF::Trine::Node::Resource->new('http://example.org/subject'), RDF::Trine::Node::Resource->new('http://example.net/rel/two'), RDF::Trine::Node::Resource->new('http://example.net/absolute'), ), "space-separated relationships", ); ok( $M->count_statements( RDF::Trine::Node::Resource->new('http://example.org/nextdoc'), RDF::Trine::Node::Resource->new('http://www.iana.org/assignments/relation/prev'), RDF::Trine::Node::Resource->new('http://example.org/subject'), ), "the 'anchor' link parameter", ); ok( $M->count_statements( RDF::Trine::Node::Resource->new('http://example.org/author'), RDF::Trine::Node::Resource->new('http://www.iana.org/assignments/relation/made'), RDF::Trine::Node::Resource->new('http://example.org/subject'), ), "the 'rev' link parameter", ); ok( $M->count_statements( RDF::Trine::Node::Resource->new('http://example.org/author'), RDF::Trine::Node::Resource->new('http://purl.org/dc/terms/title'), RDF::Trine::Node::Literal->new('author'), ), "the 'title' link parameter", ); ok( $M->count_statements( RDF::Trine::Node::Resource->new('http://example.org/subject'), RDF::Trine::Node::Resource->new('http://purl.org/dc/terms/title'), RDF::Trine::Node::Literal->new('subject'), ), "the 'title' link parameter, with 'anchor'", ); ok( $M->count_statements( RDF::Trine::Node::Resource->new('http://example.org/german-page'), RDF::Trine::Node::Resource->new('http://purl.org/dc/terms/title'), RDF::Trine::Node::Literal->new('nächstes Kapitel', 'de'), ), "the 'title*' link parameter", ); ok( $M->count_statements( RDF::Trine::Node::Resource->new('http://example.org/german-page'), RDF::Trine::Node::Resource->new('http://purl.org/dc/terms/title'), RDF::Trine::Node::Literal->new('nachstes Kapitel'), ), "'title*' fallback", ); ok( $M->count_statements( RDF::Trine::Node::Resource->new('http://example.org/nextdoc'), RDF::Trine::Node::Resource->new('http://purl.org/dc/terms/language'), RDF::Trine::Node::Resource->new('http://www.lingvoj.org/lingvo/en'), ), "the 'hreflang' link parameter", ); ok( $M->count_statements( RDF::Trine::Node::Resource->new('http://example.org/nextdoc'), RDF::Trine::Node::Resource->new('http://purl.org/dc/terms/format'), RDF::Trine::Node::Resource->new('http://www.iana.org/assignments/media-types/text/html'), ), "the 'type' link parameter", ); Parser.pm000644001750001750 2520012266567052 17262 0ustar00taitai000000000000HTTP-Link-Parser-0.200/lib/HTTP/Linkpackage HTTP::Link::Parser; use 5.010; use strict; no warnings; BEGIN { $HTTP::Link::Parser::AUTHORITY = 'cpan:TOBYINK'; $HTTP::Link::Parser::VERSION = '0.200'; require Exporter; our @ISA = qw(Exporter); our %EXPORT_TAGS = ( 'all' => [qw/parse_links_into_model parse_links_to_rdfjson parse_links_to_list parse_single_link relationship_uri/], 'standard' => [qw/parse_links_into_model parse_links_to_rdfjson/], ); our @EXPORT_OK = @{ $EXPORT_TAGS{'all'} }; our @EXPORT = @{ $EXPORT_TAGS{'standard'} }; } use Carp qw(croak carp); use Encode qw(decode encode_utf8); use Scalar::Util qw(blessed); use URI; use URI::Escape; use constant ( LINK_NAMESPACE => 'http://www.iana.org/assignments/relation/', ); sub parse_links_into_model { my ($response, $model) = @_; croak "Parameter to parse_links_into_model should be an HTTP::Message" unless blessed($response) && $response->isa('HTTP::Message'); require RDF::Trine; my $model ||= RDF::Trine::Model->temporary_model; $model->add_hashref(parse_links_to_rdfjson($response)); return $model; } sub parse_links_to_rdfjson { my ($response) = @_; croak "Parameter to parse_links_to_rdfjson should be an HTTP::Message." unless blessed($response) && $response->isa('HTTP::Message'); my $base = URI->new($response->base); my $links = parse_links_to_list($response); my $rv = {}; foreach my $link (@$links) { my $subject = $base; $subject = $link->{'anchor'} if defined $link->{'anchor'}; my $object = $link->{'URI'}; foreach my $r (@{ $link->{'rel'} }) { my $r1 = relationship_uri($r); push @{ $rv->{ $subject }->{ $r1 } }, { 'value' => "$object", 'type' => 'uri', }; } foreach my $r (@{ $link->{'rev'} }) { my $r1 = relationship_uri($r); push @{ $rv->{ $object }->{ $r1 } }, { 'value' => "$subject", 'type' => 'uri', }; } if (defined $link->{'title'}) { if (blessed($link->{'title'}) && $link->{'title'}->isa('HTTP::Link::Parser::PlainLiteral')) { push @{ $rv->{ $object }->{ 'http://purl.org/dc/terms/title' } }, { 'value' => encode_utf8($link->{'title'}.''), 'type' => 'literal', 'lang' => $link->{'title'}->lang, }; } else { push @{ $rv->{ $object }->{ 'http://purl.org/dc/terms/title' } }, { 'value' => $link->{'title'}, 'type' => 'literal', }; } } if (defined $link->{'title*'}) { foreach my $t (@{ $link->{'title*'} }) { push @{ $rv->{ $object }->{ 'http://purl.org/dc/terms/title' } }, { 'value' => encode_utf8("$t"), 'type' => 'literal', 'lang' => $t->lang, }; } } if (defined $link->{'hreflang'}) { foreach my $lang (@{ $link->{'hreflang'} }) { push @{ $rv->{ $object }->{ 'http://purl.org/dc/terms/language' } }, { 'value' => 'http://www.lingvoj.org/lingvo/' . uri_escape(lc $lang), 'type' => 'uri', }; } } if (defined $link->{'type'} && $link->{'type'} =~ m?([A-Z0-9\!\#\$\&\.\+\-\^\_]{1,127})/([A-Z0-9\!\#\$\&\.\+\-\^\_]{1,127})?i) { my $type = lc $1; my $subtype = lc $2; push @{ $rv->{ $object }->{ 'http://purl.org/dc/terms/format' } }, { 'value' => 'http://www.iana.org/assignments/media-types/'.uri_escape($type).'/'.uri_escape($subtype), 'type' => 'uri', }; } } return $rv; } sub relationship_uri { my ($str) = @_; if ($str =~ /^([a-z][a-z0-9\+\.\-]{0,126})\:/i) { # seems to be an absolute URI, so can safely return "as is". return $str; } return LINK_NAMESPACE . lc $str; } sub parse_links_to_list { my ($response) = @_; croak "Parameter to parse_links_to_list should be an HTTP::Message." unless blessed($response) && $response->isa('HTTP::Message'); my $rv = []; my $base = URI->new($response->base); my $clang; if ($response->header('Content-Language') =~ /^\s*([^,\s]+)/) { $clang = $1; } foreach my $header ($response->header('Link')) { push @$rv, parse_single_link($header, $base, $clang); } return $rv; } sub parse_single_link { my ($hdrv, $base, $default_lang) = @_; my $rv = {}; my $uri = undef; if ($hdrv =~ /^(\s*<([^>]*)>\s*)/) { $uri = $2; $hdrv = substr($hdrv, length($1)); } else { return $rv; } $rv->{'URI'} = URI->new_abs($uri, $base); while ($hdrv =~ /^(\s*\;\s*(\/|[a-z0-9-]+\*?)\s*\=\s*("[^"]*"|[^\s\"\;\,]+)\s*)/i) { $hdrv = substr($hdrv, length($1)); my $key = lc $2; my $val = $3; $val =~ s/(^"|"$)//g if ($val =~ /^".*"$/); if ($key eq 'rel') { $val =~ s/(^\s+)|(\s+$)//g; $val =~ s/\s+/ /g; my @rels = split / /, $val; foreach my $rel (@rels) { push @{ $rv->{'rel'} }, $rel; } } elsif ($key eq 'rev') { $val =~ s/(^\s+)|(\s+$)//g; $val =~ s/\s+/ /g; my @rels = split / /, $val; foreach my $rel (@rels) { push @{ $rv->{'rev'} }, $rel; } } elsif ($key eq 'anchor') { $rv->{'anchor'} = URI->new_abs($val, $base) unless defined $rv->{'anchor'}; } elsif ($key eq 'title') { if (defined $default_lang) { my $lit = bless [$val, undef, lc $default_lang], 'HTTP::Link::Parser::PlainLiteral'; push @{ $rv->{'title'} }, $lit; } else { $rv->{'title'} = $val unless defined $rv->{'title'}; } } elsif ($key eq 'title*') { my ($charset, $lang, $string) = split /\'/, $val; $string = uri_unescape($string); $string = decode($charset, $string); my $lit = bless [$string, undef, lc $lang], 'HTTP::Link::Parser::PlainLiteral'; push @{ $rv->{'title*'} }, $lit; } elsif ($key eq 'type') { $rv->{'type'} = $val unless defined $rv->{'type'}; } else # hreflang, plus any extended types. { push @{ $rv->{ $key } }, $val; } } return $rv; } { package HTTP::Link::Parser::PlainLiteral; use overload '""' => sub { $_[0]->[0] }, 'eq' => sub { $_[0]->[0] eq $_[1]->[0] and lc $_[0]->[2] eq lc $_[1]->[2] }; sub value { $_[0]->[0]; } sub lang { length $_[0]->[2] ? $_[0]->[2] : undef; } } 1; __END__ =pod =encoding utf-8 =for stopwords hreflang prev rel =head1 NAME HTTP::Link::Parser - parse HTTP Link headers =head1 SYNOPSIS use HTTP::Link::Parser ':standard'; use LWP::UserAgent; my $ua = LWP::UserAgent->new; my $response = $ua->get("http://example.com/foo"); # Parse link headers into an RDF::Trine::Model. my $model = parse_links_into_model($response); # Find data about . my $iterator = $model->get_statements( RDF::Trine::Node::Resource->new('http://example.com/foo'), undef, undef); while ($statement = $iterator->next) { # Skip data where the value is not a resource (i.e. link) next unless $statement->object->is_resource; printf("Link to <%s> with rel=\"%s\".\n", $statement->object->uri, $statement->predicate->uri); } =head1 DESCRIPTION HTTP::Link::Parser parses HTTP "Link" headers found in an HTTP::Response object. Headers should conform to the format described in RFC 5988. =head2 Functions To export all functions: use HTTP::Link::Parser ':all'; =over 4 =item C<< parse_links_into_model($response, [$existing_model]) >> Takes an L object (or in fact, any L object) and returns an L containing link data extracted from the response. Dublin Core is used to encode 'hreflang', 'title' and 'type' link parameters. C<$existing_model> is an RDF::Trine::Model to add data to. If omitted, a new, empty model is created. =item C<< parse_links_to_rdfjson($response) >> Returns a hashref with a structure inspired by the RDF/JSON specification. This can be thought of as a shortcut for: parse_links_into_model($response)->as_hashref But it's faster as no intermediate model is built. =item C<< relationship_uri($short) >> This function is not exported by default. It may be used to convert short strings identifying relationships, such as "next" and "prev", into longer URIs identifying the same relationships, such as "http://www.iana.org/assignments/relation/next" and "http://www.iana.org/assignments/relation/prev". If passed a string which is a URI already, simply returns it as-is. =back =head2 Internal Functions These are really just internal implementations, but you can use them if you like. =over =item C<< parse_links_to_list($response) >> This function is not exported by default. Returns an arrayref of hashrefs. Each hashref contains keys corresponding to the link parameters of the link, and a key called 'URI' corresponding to the target of the link. The 'rel' and 'rev' keys are arrayrefs containing lists of relationships. If the Link used the short form of a registered relationship, then the short form is present on this list. Short forms can be converted to long forms (URIs) using the C function. The structure returned by this function should not be considered stable. =item C<< parse_single_link($link, $base, [$default_lang]) >> This function is not exported by default. This parses a single Link header (minus the "Link:" bit itself) into a hashref structure. A base URI must be included in case the link contains relative URIs. A default language can be provided for the 'title' parameter. The structure returned by this function should not be considered stable. =back =head1 BUGS Please report any bugs to L. =head1 SEE ALSO L. L, L, L, L. L. L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE Copyright (C) 2009-2011, 2014 by Toby Inkster Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. =cut