.\" Automatically generated by Pod::Man 4.09 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .if !\nF .nr F 0 .if \nF>0 \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} .\} .\" ======================================================================== .\" .IX Title "Plack::App::RDF::LinkedData 3pm" .TH Plack::App::RDF::LinkedData 3pm "2017-08-25" "perl v5.26.0" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Plack::App::RDF::LinkedData \- A Plack application for running RDF::LinkedData .SH "VERSION" .IX Header "VERSION" Version 1.00 .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 3 \& 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; \& }; .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" This module sets up a basic Plack application to use RDF::LinkedData to serve Linked Data, while making sure it does follow best practices for doing so. See the \s-1README\s0 for quick start, the gory details are here. .SH "MAKE IT RUN" .IX Header "MAKE IT RUN" .SS "Quick setup for a demo" .IX Subsection "Quick setup for a demo" \fIOne-liner\fR .IX Subsection "One-liner" .PP It is possible to make it run with a single command line, e.g.: .PP .Vb 1 \& PERLRDF_STORE="Memory;path/to/some/data.ttl" plackup \-host localhost script/linked_data.psgi .Ve .PP This will start a server with the default config on localhost on port 5000, so the URIs you're going serve from the file data.ttl will have to have a base \s-1URI\s0 \f(CW\*(C`http://localhost:5000/\*(C'\fR. .PP \fIUsing perlrdf command line tool\fR .IX Subsection "Using perlrdf command line tool" .PP A slightly longer example requires App::perlrdf, but sets up a persistent SQLite-based triple store, parses a file and gets the server with the default config running: .PP .Vb 4 \& 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 .Ve .SS "Configuration" .IX Subsection "Configuration" To configure the system for production use, create a configuration file \f(CW\*(C`rdf_linkeddata.json\*(C'\fR that looks something like: .PP .Vb 8 \& { \& "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" } \& } .Ve .PP In your shell set .PP .Vb 1 \& export RDF_LINKEDDATA_CONFIG=/to/where/you/put/rdf_linkeddata.json .Ve .PP Then, figure out where your install method installed the , script, e.g. by using locate. If it was installed in \f(CW\*(C`/usr/local/bin\*(C'\fR, go: .PP .Vb 1 \& plackup /usr/local/bin/linked_data.psgi \-\-host localhost \-\-port 3000 .Ve .PP The \f(CW\*(C`endpoint\*(C'\fR\-part of the config sets up a \s-1SPARQL\s0 Endpoint. This requires the RDF::Endpoint module, which is recommended by this module. To use it, it needs to have some config, but will use defaults. .PP It is also possible to set an \f(CW\*(C`expires\*(C'\fR time. This needs Plack::Middleware::Expires and uses Apache \f(CW\*(C`mod_expires\*(C'\fR syntax, in the example above, it will set an expires header for all resources to expire after 1 day of access. .PP The \f(CW\*(C`cors\*(C'\fR\-part of the config enables Cross-Origin Resource Sharing, which is a W3C Recommendation for relaxing security constraints to allow data to be shared across domains. In most cases, this is what you want when you are serving open data, but in some cases, notably intranets, this should be turned off by removing this part. .PP The \f(CW\*(C`void\*(C'\fR\-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. .PP Finally, \f(CW\*(C`fragments\*(C'\fR add support for Triple Pattern Fragments, a work-in-progress, It is a more lightweight but less powerful way to query \s-1RDF\s0 data than \s-1SPARQL.\s0 If you have this, it is recommended to have \s-1CORS\s0 enabled and required to have at least a minimal VoID setup. .PP Note that in some environments, for example if the Plack server that is dynamically configured, and/or behind a proxy server, the server may fail to bind to the address you give it as hostname. In this case, it is wise to allow the server to bind to any public \s-1IP\s0 address, i.e. set the host name to 0.0.0.0. .SS "Details of the implementation" .IX Subsection "Details of the implementation" This server is a minimal Plack-script that should be sufficient for most linked data usages, and serve as a an example for most others. .PP A minimal example of the required config file is provided above. There is are longer examples in the distribution, which is used to run tests. In the config file, there is a \f(CW\*(C`store\*(C'\fR parameter, which must contain the RDF::Trine::Store config hashref. It may also have a \&\f(CW\*(C`base_uri\*(C'\fR \s-1URI\s0 and a \f(CW\*(C`namespace\*(C'\fR hashref which may contain prefix \- \&\s-1URI\s0 mappings to be used in serializations. Certain namespace, namely \&\s-1RDF,\s0 VoID, Hydra, \s-1DC\s0 Terms and \s-1XML\s0 Schema are added by the module and do not need to be declared. .PP 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 \&\s-1API.\s0 .PP The configuration is done using Config::ZOMG and all its features can be used. Importantly, you can set the \f(CW\*(C`RDF_LINKEDDATA_CONFIG\*(C'\fR environment variable to point to the config file you want to use. See also Catalyst::Plugin::ConfigLoader for more information on how to use this config system. .SS "Behaviour" .IX Subsection "Behaviour" The following documentation is adapted from RDF::LinkedData::Apache, which preceded this module. .IP "\(bu" 4 \&\f(CW\*(C`http://host.name/rdf/example\*(C'\fR .Sp Will return an \s-1HTTP 303\s0 redirect based on the value of the request's Accept header. If the Accept header contains a recognized \s-1RDF\s0 media type or there is no Accept header, the redirect will be to \&\f(CW\*(C`http://host.name/rdf/example/data\*(C'\fR, otherwise to \&\f(CW\*(C`http://host.name/rdf/example/page\*(C'\fR. If the \s-1URI\s0 has a foaf:homepage or foaf:page predicate, the redirect will in the latter case instead use the first encountered object \s-1URI.\s0 .IP "\(bu" 4 \&\f(CW\*(C`http://host.name/rdf/example/data\*(C'\fR .Sp Will return a bounded description of the \f(CW\*(C`http://host.name/rdf/example\*(C'\fR resource in an \s-1RDF\s0 serialization based on the Accept header. If the Accept header does not contain a recognized media type, \s-1RDF/XML\s0 will be returned. .IP "\(bu" 4 \&\f(CW\*(C`http://host.name/rdf/example/page\*(C'\fR .Sp Will return an \s-1HTML\s0 description of the \f(CW\*(C`http://host.name/rdf/example\*(C'\fR resource including RDFa markup, or, if the \s-1URI\s0 has a foaf:homepage or foaf:page predicate, a 301 redirect to that object. .PP If the \s-1RDF\s0 resource for which data is requested is not the subject of any \s-1RDF\s0 triples in the underlying triplestore, the /page and /data redirects will not take place, and a \s-1HTTP 404\s0 (Not Found) will be returned. .PP The \s-1HTML\s0 description of resources will be enhanced by having metadata about the predicate of \s-1RDF\s0 triples loaded into the same triplestore. Currently, only a \f(CW\*(C`rdfs:label\*(C'\fR\-predicate will be used for a title, as in this version, generation of \s-1HTML\s0 is done by RDF::RDFa::Generator. .SS "Endpoint Usage" .IX Subsection "Endpoint Usage" As stated earlier, this module can set up a \s-1SPARQL\s0 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 \&\f(CW\*(C`endpoint\*(C'\fR section in your config. To use it, you just need to have an \f(CW\*(C`endpoint\*(C'\fR section with something in it, it doesn't really matter what, as it will use defaults for everything that isn't set. .PP RDF::Endpoint is recommended by this module, but as it is optional, you may have to install it separately. It has many configuration options, please see its documentation for details. .PP You may also need to set the \f(CW\*(C`RDF_ENDPOINT_SHAREDIR\*(C'\fR variable to wherever the endpoint shared files are installed to. These are some \&\s-1CSS\s0 and Javascript files that enhance the user experience. They are not strictly necessary, but it sure makes it pretty! RDF::Endpoint should do the right thing, though, so it shouldn't be necessary. .PP 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 \f(CW\*(C`VirtualHost\*(C'\fR section: .PP .Vb 3 \& Alias /js/ /path/to/share/www/js/ \& Alias /favicon.ico /path/to/share/www/favicon.ico \& Alias /css/ /path/to/share/www/css/ .Ve .SS "VoID Generator Usage" .IX Subsection "VoID Generator Usage" Like a \s-1SPARQL\s0 Endpoint, this is something most users would want. In fact, it is 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 \s-1SYNOPSIS\s0 example. .PP 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 \&\f(CW\*(C`pagetitle\*(C'\fR, which sets the title for the RDFa page that can be generated. Moreover, you can set titles in several languages for the dataset using \f(CW\*(C`titles\*(C'\fR 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. .PP Please refer to the RDF::Generator::Void for more details about what can be set, and the \f(CW\*(C`rdf_linkeddata_void.json\*(C'\fR test config in the distribution for example. .PP By adding an \f(CW\*(C`add_void\*(C'\fR config key, you can make pass a file to the generator so that arbitrary \s-1RDF\s0 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 \s-1JSON\s0 look something like this: .PP .Vb 1 \& "add_void": { "file": "/data/add.ttl", "syntax": "turtle" } .Ve .PP where \f(CW\*(C`file\*(C'\fR is the full path to \s-1RDF\s0 that should be added and \&\f(CW\*(C`syntax\*(C'\fR is needed by the parser to parse it. .PP Normally, the VoID description is cached in \s-1RAM\s0 and the store ETag is checked on every request to see if the description must be regenerated. If you use the \f(CW\*(C`add_void\*(C'\fR feature, you can force regeneration on the next request by touching the file. .SH "FEEDBACK WANTED" .IX Header "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. .SH "METHODS" .IX Header "METHODS" You would most likely not need to call these yourself, but rather use the \f(CW\*(C`linked_data.psgi\*(C'\fR script supplied with the distribution. .ie n .IP """configure""" 4 .el .IP "\f(CWconfigure\fR" 4 .IX Item "configure" This is the only method you would call manually, as it can be used to pass a hashref with configuration to the application. .ie n .IP """prepare_app""" 4 .el .IP "\f(CWprepare_app\fR" 4 .IX Item "prepare_app" Will be called by Plack to set the application up. .ie n .IP """call""" 4 .el .IP "\f(CWcall\fR" 4 .IX Item "call" Will be called by Plack to process the request. .SH "AUTHOR" .IX Header "AUTHOR" Kjetil Kjernsmo, \f(CW\*(C`\*(C'\fR .SH "COPYRIGHT & LICENSE" .IX Header "COPYRIGHT & LICENSE" Copyright 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 Kjetil Kjernsmo .PP This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.