Plack:...kedData(3pm)
π Plack::App::RDF::LinkedData π
okay so bestie, welcome to the Plack corner of the Perl user-contributed docs (that's the 3pm section, the one where all the modules live π«Ά). This page is literally called Plack::App::RDF::LinkedData and it's about to make your Linked Data era happen. No cap. β¨
πΈ NAME πΈ
Plack::App::RDF::LinkedData β it's a Plack application for running RDF::LinkedData. That's it, that's the whole vibe. π¦
β VERSION β
Version 1.940 π
π SYNOPSIS π
Here's the little ritual you do to summon it, copy-paste ready, character for character:
my $linkeddata = Plack::App::RDF::LinkedData->new();
$linkeddata->configure($config);
my $rdf_linkeddata = $linkeddata->to_app;
builder {
enable "Head";
enable "ContentLength";
enable "ConditionalGET";
$rdf_linkeddata;
};
not me building an app and enabling a whole lil stack of middleware in one breath π iconic behaviour honestly.
β¨ DESCRIPTION β¨
So this module sets up a basic Plack application that uses RDF::LinkedData to serve Linked Data β and it's out here making sure it follows the best practices for doing so, because serving Linked Data sloppily is not the move. π
Want the quick start? Go peek at the README π. Want the gory details? You're in exactly the right place, bestie. This is where they live. ππ
β¦and there's more where that came from, keep reading π
π οΈ MAKE IT RUN β¨
π Quick setup for a demo
π One-liner
bestie you can literally get this running with ONE command line, like:
PERLRDF_STORE="Memory;path/to/some/data.ttl" plackup -host localhost script/linked_data.psgi
this spins up a server with the default config on localhost on port 5000 π₯ so the URIs you're gonna serve from the file data.ttl have to have a base URI of "http://localhost:5000/". that's the vibe. no cap.
there's also a "LOG_ADAPTER" you can set to any of Log::Any::Adapter to send your logging straight to the console π
and if you use it with Log::Any::Adapter::Screen, there are several other environment variables you can use to control it even further. slay.
π¦ Using perlrdf command line tool
a slightly longer example needs App::perlrdf, but it sets you up a persistent SQLite-based triple store, parses a file, and gets the server running with the default config:
export PERLRDF_STORE="DBI;mymodel;DBI:SQLite:database=rdf.db"
perlrdf make_store
perlrdf store_load path/to/some/data.ttl
plackup -host localhost script/linked_data.psgi
look at her go ππ
π Configuration
okay so for production use, you make a config file called "rdf_linkeddata.json" that looks something like this:
{
"base_uri" : "http://localhost:3000/",
"store" : {
"storetype" : "Memory",
"sources" : [ {
"file" : "/path/to/your/data.ttl",
"syntax" : "turtle"
} ]
},
"endpoint": {
"html": {
"resource_links": true
}
},
"expires" : "A86400" ,
"cors": {
"origins": "*"
},
"void": {
"pagetitle": "VoID Description for my dataset"
},
"fragments" : { "fragments_path" : "/fragments" }
}
then in your shell you set
export RDF_LINKEDDATA_CONFIG=/to/where/you/put/rdf_linkeddata.json
then figure out where your install method dropped the <linked_data.psgi> script β locate is your friend here π β and if it landed in "/usr/local/bin", you go:
plackup /usr/local/bin/linked_data.psgi --host localhost --port 3000
the "endpoint" part of the config sets up a SPARQL Endpoint. this needs the RDF::Endpoint module, which is recommended by this module. to use it, it needs to have some config, but it'll use defaults. easy peasy πΈ
you can also set an "expires" time. this needs Plack::Middleware::Expires and it uses Apache mod_expires syntax β in the example above, it sets an expires header for all resources to expire after 1 day of access β°
the "cors" part of the config enables Cross-Origin Resource Sharing, which is a W3C Recommendation for relaxing security constraints so data can be shared across domains. in most cases this is literally what you want when you're serving open data, but in some cases β notably intranets β this should be turned off by removing this part. π«
the "void" part generates some statistics and a description of the dataset, using RDF::Generator::Void. it is strongly recommended to install and run that, but it can take some time to generate, so you may have to set the detail level. β³
finally, "fragments" adds support for Triple Pattern Fragments, a work-in-progress. it's a more lightweight but less powerful way to query RDF data than SPARQL. if you have this, it is recommended to have CORS enabled and required to have at least a minimal VoID setup. π§©
heads up bestie: in some environments β like if the Plack server is dynamically configured and/or sitting behind a proxy server β the server may fail to bind to the address you give it as hostname π in that case it's wise to let the server bind to any public IP address, i.e. set the host name to 0.0.0.0. π«Ά
β¨ Details of the implementation
this server is a minimal Plack-script that should be sufficient for most linked data usages, and it serves as an example for most others. iconic behaviour honestly π
a minimal example of the required config file is provided above. there are longer examples in the distribution, which is used to run tests. in the config file there's a "store" parameter, which must contain the RDF::Trine::Store config hashref. it may also have a "base_uri" URI and a "namespace" hashref which may contain prefix - URI mappings to be used in serializations. certain namespace β namely RDF, VoID, Hydra, DC Terms and XML Schema β are added by the module and do not need to be declared. π
note that this is a server that can only serve URIs of hosts you control. it is not a general purpose Linked Data manipulation tool, nor is it an implementation of Linked Data Platform or the Linked Data API. periodt. π«
the configuration is done using Config::ZOMG and all its features can be used. importantly, you can set the "RDF_LINKEDDATA_CONFIG" environment variable to point to the config file you want to use. see also Catalyst::Plugin::ConfigLoader for more info on how to use this config system. π
π Behaviour
the following documentation is adapted from RDF::LinkedData::Apache, which preceded this module.
will return an HTTP 303 redirect based on the value of the request's Accept header. if the Accept header contains a recognized RDF media type or there is no Accept header, the redirect will be to "http://host.name/rdf/example/data", otherwise to "http://host.name/rdf/example/page". if the URI has a foaf:homepage or foaf:page predicate, the redirect will in the latter case instead use the first encountered object URI. π
will return a bounded description of the "http://host.name/rdf/example" resource in an RDF serialization based on the Accept header. if the Accept header does not contain a recognized media type, RDF/XML will be returned. π¦
will return an HTML description of the "http://host.name/rdf/example" resource including RDFa markup, or β if the URI has a foaf:homepage or foaf:page predicate β a 301 redirect to that object. π
if the RDF resource for which data is requested is not the subject of any RDF triples in the underlying triplestore, the /page and /data redirects will not take place, and an HTTP 404 (Not Found) will be returned. π
the HTML description of resources will be enhanced by having metadata about the predicate of RDF triples loaded into the same triplestore. currently, only a "rdfs:label"-predicate will be used for a title, as in this version, generation of HTML is done by RDF::RDFa::Generator. β¨
π₯ Endpoint Usage
as stated earlier, this module can set up a SPARQL Endpoint for the data using RDF::Endpoint. often that's what you want, but if you don't want your users to have that kind of power, or you're worried it may overload your system, you may turn it off by simply having no "endpoint" section in your config. to use it, you just need to have an "endpoint" section with something in it β it doesn't really matter what, as it will use defaults for everything that isn't set. πͺ
RDF::Endpoint is recommended by this module, but since it's optional, you may have to install it separately. it has many configuration options, so please see its documentation for details. π
you may also need to set the "RDF_ENDPOINT_SHAREDIR" variable to wherever the endpoint shared files are installed. these are some CSS and Javascript files that enhance the user experience. they're not strictly necessary, but it sure makes it pretty! π
RDF::Endpoint should do the right thing though, so it shouldn't be necessary.
finally, note that while RDF::Endpoint can serve these files for you, this module doesn't help you do that. that's mostly because this author thinks you should serve them using some other parts of the deployment stack. for example, to use Apache, put this in your Apache config in the appropriate "VirtualHost" section:
Alias /js/ /path/to/share/www/js/
Alias /favicon.ico /path/to/share/www/favicon.ico
Alias /css/ /path/to/share/www/css/
π VoID Generator Usage
like a SPARQL Endpoint, this is something most users would want. in fact, it's an even stronger recommendation than an endpoint. to enable it, you must have RDF::Generator::Void installed, and just anything in the config file to enable it, like in the SYNOPSIS example. π
you can set several things in the config β the property attributes of RDF::Generator::Void can all be set there somehow. you can also set "pagetitle", which sets the title for the RDFa page that can be generated. moreover, you can set titles in several languages for the dataset using "titles" as the key, pointing to an arrayref with titles, where each title is a two element arrayref, where the first element is the title itself and the second is the language for that title. π
please refer to the RDF::Generator::Void for more details about what can be set, and the "rdf_linkeddata_void.json" test config in the distribution for example. π§
by adding an "add_void" config key, you can make pass a file to the generator so that arbitrary RDF can be added to the VoID description. it will check the last modification time of the file and only update the VoID description if it has been modified. this is useful since as much of the VoID description is expensive to compute. to use it, the configuration would in JSON look something like this:
"add_void": { "file": "/data/add.ttl", "syntax": "turtle" }
where "file" is the full path to RDF that should be added and "syntax" is needed by the parser to parse it. π
normally, the VoID description is cached in RAM and the store ETag is checked on every request to see if the description must be regenerated. if you use the "add_void" feature, you can force regeneration on the next request by touching the file. πβ¨
π Read-write support
some recent effort has gone into experimental write support, which for this module has the implications that a boolean option "writes_enabled" that configures the application for writes. this is also meant as security β unless set to true, writes will never be performed. π to support writes, a "class" option can be set with a class name, which can be instantiated to replace RDF::LinkedData. see RDF::LinkedData::RWHypermedia for more on this. π
π FEEDBACK WANTED
please contact the author if this documentation is unclear. it is really very simple to get it running, so if it appears difficult, this documentation is most likely to blame. ππ
π§ METHODS
Okay bestie, real talk first: you're most likely not gonna need to call any of these yourself. The vibe is to just use the linked_data.psgi script that comes with the distribution and let it do the heavy lifting for you. But here's the full rundown anyway, because you deserve to know what's going on under the hood π
configure
This is the one and only method you'd ever call manually. Its whole job is letting you pass in a hashref with configuration for the application. That's it, that's the method, periodt. β¨
prepare_app
Plack calls this one to set the application up. Not you. Plack. It's giving "let the framework handle it." π«Ά
check_read_operation ( $request )
Returns true if the current request is a pure read operation. Like, no writing happening, just reading. Very chill, very demure. π
call
Plack calls this to process the request. Again β not your job, bestie, just let it cook. π₯
auth_required ( $request )
Returns true if the current request is gonna require authorization. Basically the bouncer at the club door checking IDs before anyone gets in. π
Heads up: the original lists these in this order βconfigure,prepare_app,call,auth_required ( $request ),check_read_operation ( $request )β so if you're cross-referencing, that's where everything lives. π
π AUTHOR
Kjetil Kjernsmo, <kjetilk@cpan.org>
π COPYRIGHT & LICENSE
Copyright 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 Kjetil Kjernsmo
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
And that's a wrap, gorgeous! π This whole page came to you courtesy of perl v5.36.0, dated 2023-09-04, and it's filed under Plack:...kedData(3pm). Go forth and link your data, you absolute icon. ππ¦πΈ
π¦ where this page comes from
- debian trixie: librdf-linkeddata-perl 1.940-4 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu noble: librdf-linkeddata-perl 1.940-4 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu resolute: librdf-linkeddata-perl 1.940-4 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu stonking: librdf-linkeddata-perl 1.940-4 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms