rack-rdf 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/AUTHORS +2 -0
- data/CREDITS +1 -0
- data/README.md +161 -0
- data/UNLICENSE +24 -0
- data/VERSION +1 -0
- data/lib/rack/rdf.rb +34 -0
- data/lib/rack/rdf/conneg.rb +239 -0
- data/lib/rack/rdf/version.rb +20 -0
- metadata +121 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 13652453e2d12d1f8513353295d36488e73e9b60c4e7e163bbc47eb680ae1ad9
|
4
|
+
data.tar.gz: 5fe0fe7c64b5f4580cf17b483fa66ffce192e8f96959b93b921ac0fc2aae9f4a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: bb4db0ef155289c5685ea22c8c83efd7c41fb9936c93623792fe1156b2ec2b763e3af6428ecb2f4d21769bb0f8e17df894974327ef91036e6499e37553bf1af3
|
7
|
+
data.tar.gz: bc5baef7ae1c96331288f23ea6743d3a1dd3e1731855b72a6d53122566fbbf8e0e0ba126bfb4aff95104940f5407eb7e370732afc1d4b1d8c019e2e40926edc8
|
data/AUTHORS
ADDED
data/CREDITS
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
* Gregg Kellogg <gregg@greggkellogg.net>
|
data/README.md
ADDED
@@ -0,0 +1,161 @@
|
|
1
|
+
# Linked Data Content Negotiation for Rack Applications
|
2
|
+
|
3
|
+
This is [Rack][] middleware that provides [Linked Data][] content
|
4
|
+
negotiation for Rack applications. You can use `Rack::RDF` with any
|
5
|
+
Ruby web framework based on Rack, including with Ruby on Rails 3.0 and with
|
6
|
+
Sinatra.
|
7
|
+
|
8
|
+
This version is based on [rack-linkeddata][] without the hard dependency on the [linkeddata][] gem, to allow applications to better manage their dependencies
|
9
|
+
|
10
|
+
* <http://github.com/datagraph/rack-rdf>
|
11
|
+
|
12
|
+
[](http://badge.fury.io/rb/rack-rdf)
|
13
|
+
[](http://travis-ci.org/ruby-rdf/rack-rdf)
|
14
|
+
|
15
|
+
## Features
|
16
|
+
|
17
|
+
* Implements [HTTP content negotiation][conneg] for RDF content types.
|
18
|
+
* Supports all [RDF.rb][]-compatible serialization formats.
|
19
|
+
* Compatible with any Rack application and any Rack-based framework.
|
20
|
+
|
21
|
+
## Examples
|
22
|
+
|
23
|
+
### Adding RDF content negotiation to a Rails 3.x application
|
24
|
+
|
25
|
+
# config/application.rb
|
26
|
+
require 'rack/rdf'
|
27
|
+
|
28
|
+
class Application < Rails::Application
|
29
|
+
config.middleware.use Rack::RDF::ContentNegotiation
|
30
|
+
end
|
31
|
+
|
32
|
+
### Adding RDF content negotiation to a Sinatra application
|
33
|
+
|
34
|
+
#!/usr/bin/env ruby -rubygems
|
35
|
+
require 'sinatra'
|
36
|
+
require 'rack/linkeddata'
|
37
|
+
|
38
|
+
use Rack::LinkedData::ContentNegotiation
|
39
|
+
|
40
|
+
get '/hello' do
|
41
|
+
RDF::Graph.new do |graph|
|
42
|
+
graph << [RDF::Node.new, RDF::DC.title, "Hello, world!"]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
### Adding RDF content negotiation to a Rackup application
|
47
|
+
|
48
|
+
#!/usr/bin/env rackup
|
49
|
+
require 'rack/rdf'
|
50
|
+
|
51
|
+
rdf = RDF::Graph.new do |graph|
|
52
|
+
graph << [RDF::Node.new, RDF::DC.title, "Hello, world!"]
|
53
|
+
end
|
54
|
+
|
55
|
+
use Rack::RDF::ContentNegotiation
|
56
|
+
run lambda { |env| [200, {}, rdf] }
|
57
|
+
|
58
|
+
### Defining a default RDF content type
|
59
|
+
|
60
|
+
use Rack::RDF::ContentNegotiation, default: "text/turtle"
|
61
|
+
|
62
|
+
Options are also passed to the writer, which can allow options to be shared among the application
|
63
|
+
and different components.
|
64
|
+
|
65
|
+
shared_options = {:default => "text/turtle", :standard_prefixes => true, }
|
66
|
+
use Rack::RDF::ContentNegotiation, shared_options
|
67
|
+
run MyApplication, shared_options
|
68
|
+
|
69
|
+
### Testing RDF content negotiation using `rackup` and `curl`
|
70
|
+
|
71
|
+
$ rackup doc/examples/hello.ru
|
72
|
+
|
73
|
+
$ curl -iH "Accept: text/plain" http://localhost:9292/hello
|
74
|
+
$ curl -iH "Accept: text/turtle" http://localhost:9292/hello
|
75
|
+
$ curl -iH "Accept: */*" http://localhost:9292/hello
|
76
|
+
|
77
|
+
## Description
|
78
|
+
|
79
|
+
`Rack::RDF` implements content negotiation for any [Rack][] response
|
80
|
+
object that implements the `RDF::Enumerable` mixin. You would typically
|
81
|
+
return an instance of `RDF::Graph` or `RDF::Repository` from your Rack
|
82
|
+
application, and let the `Rack::RDF::ContentNegotiation` middleware
|
83
|
+
take care of serializing your response into whatever RDF format the HTTP
|
84
|
+
client requested and understands.
|
85
|
+
|
86
|
+
The middleware queries [RDF.rb][] for the MIME content types of known RDF
|
87
|
+
serialization formats, so it will work with whatever serialization extensions
|
88
|
+
that are currently available for RDF.rb. (At present, this includes support
|
89
|
+
for N-Triples, N-Quads, Turtle, RDF/XML, RDF/JSON, JSON-LD, RDFa, TriG and TriX.)
|
90
|
+
|
91
|
+
##Documentation
|
92
|
+
|
93
|
+
<http://http://rubydoc.info/github/ruby-rdf/rack-rdf/>
|
94
|
+
|
95
|
+
* {Rack::RDF}
|
96
|
+
* {Rack::RDF::ContentNegotiation}
|
97
|
+
|
98
|
+
## Dependencies
|
99
|
+
|
100
|
+
* [Rack](http://rubygems.org/gems/rack) (~> 2.0)
|
101
|
+
* [RDF](http://rubygems.org/gems/rdf) (~> 3.1)
|
102
|
+
|
103
|
+
## Installation
|
104
|
+
|
105
|
+
The recommended installation method is via [RubyGems](http://rubygems.org/).
|
106
|
+
To install the latest official release of the gem, do:
|
107
|
+
|
108
|
+
% [sudo] gem install rack-rdf
|
109
|
+
|
110
|
+
## Download
|
111
|
+
|
112
|
+
To get a local working copy of the development repository, do:
|
113
|
+
|
114
|
+
% git clone git://github.com/ruby-rdf/rack-rdf.git
|
115
|
+
|
116
|
+
Alternatively, download the latest development version as a tarball as
|
117
|
+
follows:
|
118
|
+
|
119
|
+
% wget http://github.com/ruby-rdf/rack-rdf/tarball/master
|
120
|
+
|
121
|
+
## Contributing
|
122
|
+
This repository uses [Git Flow](https://github.com/nvie/gitflow) to mange development and release activity. All submissions _must_ be on a feature branch based on the _develop_ branch to ease staging and integration.
|
123
|
+
|
124
|
+
* Do your best to adhere to the existing coding conventions and idioms.
|
125
|
+
* Don't use hard tabs, and don't leave trailing whitespace on any line.
|
126
|
+
* Do document every method you add using [YARD][] annotations. Read the
|
127
|
+
[tutorial][YARD-GS] or just look at the existing code for examples.
|
128
|
+
* Don't touch the `.gemspec`, `VERSION` or `AUTHORS` files. If you need to
|
129
|
+
change them, do so on your private branch only.
|
130
|
+
* Do feel free to add yourself to the `CREDITS` file and the corresponding
|
131
|
+
list in the the `README`. Alphabetical order applies.
|
132
|
+
* Do note that in order for us to merge any non-trivial changes (as a rule
|
133
|
+
of thumb, additions larger than about 15 lines of code), we need an
|
134
|
+
explicit [public domain dedication][PDD] on record from you.
|
135
|
+
|
136
|
+
## References
|
137
|
+
|
138
|
+
* <http://www.w3.org/DesignIssues/LinkedData.html>
|
139
|
+
* <http://linkeddata.org/docs/how-to-publish>
|
140
|
+
* <http://linkeddata.org/conneg-303-redirect-code-samples>
|
141
|
+
* <http://www.w3.org/TR/cooluris/>
|
142
|
+
* <http://www.w3.org/TR/swbp-vocab-pub/>
|
143
|
+
* <http://patterns.dataincubator.org/book/publishing-patterns.html>
|
144
|
+
|
145
|
+
## Authors
|
146
|
+
|
147
|
+
* [Arto Bendiken](http://github.com/bendiken) - <http://ar.to/>
|
148
|
+
* [Gregg Kellogg](http://github.com/gkellogg) - <http://greggkellogg.net/>
|
149
|
+
|
150
|
+
## License
|
151
|
+
|
152
|
+
This is free and unencumbered public domain software. For more information,
|
153
|
+
see <http://unlicense.org/> or the accompanying {file:UNLICENSE} file.
|
154
|
+
|
155
|
+
[Rack]: http://rack.github.com/
|
156
|
+
[RDF.rb]: http://ruby-rdf.github.com/rdf/
|
157
|
+
[Linked Data]: http://linkeddata.org/
|
158
|
+
[conneg]: http://en.wikipedia.org/wiki/Content_negotiation
|
159
|
+
[YARD]: http://yardoc.org/
|
160
|
+
[YARD-GS]: http://rubydoc.info/docs/yard/file/docs/GettingStarted.md
|
161
|
+
[PDD]: http://unlicense.org/#unlicensing-contributions
|
data/UNLICENSE
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
This is free and unencumbered software released into the public domain.
|
2
|
+
|
3
|
+
Anyone is free to copy, modify, publish, use, compile, sell, or
|
4
|
+
distribute this software, either in source code form or as a compiled
|
5
|
+
binary, for any purpose, commercial or non-commercial, and by any
|
6
|
+
means.
|
7
|
+
|
8
|
+
In jurisdictions that recognize copyright laws, the author or authors
|
9
|
+
of this software dedicate any and all copyright interest in the
|
10
|
+
software to the public domain. We make this dedication for the benefit
|
11
|
+
of the public at large and to the detriment of our heirs and
|
12
|
+
successors. We intend this dedication to be an overt act of
|
13
|
+
relinquishment in perpetuity of all present and future rights to this
|
14
|
+
software under copyright law.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
19
|
+
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
20
|
+
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
21
|
+
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
|
24
|
+
For more information, please refer to <http://unlicense.org/>
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
3.1.0
|
data/lib/rack/rdf.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'rack'
|
2
|
+
require 'rdf'
|
3
|
+
require 'rdf/ntriples'
|
4
|
+
require 'rdf/nquads'
|
5
|
+
|
6
|
+
module Rack
|
7
|
+
module RDF
|
8
|
+
autoload :ContentNegotiation, 'rack/rdf/conneg'
|
9
|
+
autoload :VERSION, 'rack/rdf/version'
|
10
|
+
|
11
|
+
##
|
12
|
+
# Registers all known RDF formats with Rack's MIME types registry.
|
13
|
+
#
|
14
|
+
# @param [Boolean] :overwrite (false)
|
15
|
+
# @param [Hash{Symbol => Object}] options
|
16
|
+
# @return [void]
|
17
|
+
def self.register_mime_types!(overwrite: false, **options)
|
18
|
+
if defined?(Rack::Mime::MIME_TYPES)
|
19
|
+
::RDF::Format.each do |format|
|
20
|
+
if !Rack::Mime::MIME_TYPES.has_key?(file_ext = ".#{format.to_sym}") || overwrite
|
21
|
+
Rack::Mime::MIME_TYPES.merge!(file_ext => format.content_type.first)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
::RDF::Format.file_extensions.each do |file_ext, formats|
|
25
|
+
if !Rack::Mime::MIME_TYPES.has_key?(file_ext = ".#{file_ext}") || overwrite
|
26
|
+
Rack::Mime::MIME_TYPES.merge!(file_ext => formats.first.content_type.first)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
Rack::RDF.register_mime_types!
|
@@ -0,0 +1,239 @@
|
|
1
|
+
module Rack; module RDF
|
2
|
+
##
|
3
|
+
# Rack middleware for Linked Data content negotiation.
|
4
|
+
#
|
5
|
+
# Uses HTTP Content Negotiation to find an appropriate RDF
|
6
|
+
# format to serialize any result with a body being `RDF::Enumerable`.
|
7
|
+
#
|
8
|
+
# Override content negotiation by setting the :format option to
|
9
|
+
# {#initialize}.
|
10
|
+
#
|
11
|
+
# Add a :default option to set a content type to use when nothing else
|
12
|
+
# is found.
|
13
|
+
#
|
14
|
+
# @example
|
15
|
+
# use Rack::RDF::ContentNegotation, :format => :ttl
|
16
|
+
# use Rack::RDF::ContentNegotiation, :format => RDF::NTriples::Format
|
17
|
+
# use Rack::RDF::ContentNegotiation, :default => 'application/rdf+xml'
|
18
|
+
#
|
19
|
+
# @see http://www4.wiwiss.fu-berlin.de/bizer/pub/LinkedDataTutorial/
|
20
|
+
# @see https://www.rubydoc.info/github/rack/rack/master/file/SPEC
|
21
|
+
class ContentNegotiation
|
22
|
+
DEFAULT_CONTENT_TYPE = "application/n-triples" # N-Triples
|
23
|
+
VARY = {'Vary' => 'Accept'}.freeze
|
24
|
+
|
25
|
+
# @return [#call]
|
26
|
+
attr_reader :app
|
27
|
+
|
28
|
+
# @return [Hash{Symbol => Object}]
|
29
|
+
attr_reader :options
|
30
|
+
|
31
|
+
##
|
32
|
+
# @param [#call] app
|
33
|
+
# @param [Hash{Symbol => Object}] options
|
34
|
+
# Other options passed to writer.
|
35
|
+
# @param [String] :default (DEFAULT_CONTENT_TYPE) Specific content type
|
36
|
+
# @option options [RDF::Format, #to_sym] :format Specific RDF writer format to use
|
37
|
+
def initialize(app, options)
|
38
|
+
@app, @options = app, options
|
39
|
+
@options[:default] = (@options[:default] || DEFAULT_CONTENT_TYPE).to_s
|
40
|
+
end
|
41
|
+
|
42
|
+
##
|
43
|
+
# Handles a Rack protocol request.
|
44
|
+
# Parses Accept header to find appropriate mime-type and sets content_type accordingly.
|
45
|
+
#
|
46
|
+
# Inserts ordered content types into the environment as `ORDERED_CONTENT_TYPES` if an Accept header is present
|
47
|
+
#
|
48
|
+
# @param [Hash{String => String}] env
|
49
|
+
# @return [Array(Integer, Hash, #each)] Status, Headers and Body
|
50
|
+
# @see http://rack.rubyforge.org/doc/SPEC.html
|
51
|
+
def call(env)
|
52
|
+
env['ORDERED_CONTENT_TYPES'] = parse_accept_header(env['HTTP_ACCEPT']) if env.has_key?('HTTP_ACCEPT')
|
53
|
+
response = app.call(env)
|
54
|
+
body = response[2].respond_to?(:body) ? response[2].body : response[2]
|
55
|
+
case body
|
56
|
+
when ::RDF::Enumerable
|
57
|
+
response[2] = body # Put it back in the response, it might have been a proxy
|
58
|
+
serialize(env, *response)
|
59
|
+
else response
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
##
|
64
|
+
# Serializes an `RDF::Enumerable` response into a Rack protocol
|
65
|
+
# response using HTTP content negotiation rules or a specified Content-Type.
|
66
|
+
#
|
67
|
+
# Passes parameters from Accept header, and Link header to writer.
|
68
|
+
#
|
69
|
+
# @param [Hash{String => String}] env
|
70
|
+
# @param [Integer] status
|
71
|
+
# @param [Hash{String => Object}] headers
|
72
|
+
# @param [RDF::Enumerable] body
|
73
|
+
# @return [Array(Integer, Hash, #each)] Status, Headers and Body
|
74
|
+
def serialize(env, status, headers, body)
|
75
|
+
result, content_type = nil, nil
|
76
|
+
find_writer(env, headers) do |writer, ct, accept_params = {}|
|
77
|
+
begin
|
78
|
+
# Passes content_type as writer option to allow parameters to be extracted.
|
79
|
+
writer_options = @options.merge(
|
80
|
+
accept_params: accept_params,
|
81
|
+
link: env['HTTP_LINK']
|
82
|
+
)
|
83
|
+
result, content_type = writer.dump(body, nil, **writer_options), ct.split(';').first
|
84
|
+
break
|
85
|
+
rescue ::RDF::WriterError
|
86
|
+
# Continue to next writer
|
87
|
+
ct
|
88
|
+
rescue
|
89
|
+
ct
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
if result
|
94
|
+
headers = headers.merge(VARY).merge('Content-Type' => content_type)
|
95
|
+
[status, headers, [result]]
|
96
|
+
else
|
97
|
+
not_acceptable
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
protected
|
102
|
+
##
|
103
|
+
# Yields an `RDF::Writer` class for the given `env`.
|
104
|
+
#
|
105
|
+
# If options contain a `:format` key, it identifies the specific format to use;
|
106
|
+
# otherwise, if the environment has an HTTP_ACCEPT header, use it to find a writer;
|
107
|
+
# otherwise, use the default content type
|
108
|
+
#
|
109
|
+
# @param [Hash{String => String}] env
|
110
|
+
# @param [Hash{String => Object}] headers
|
111
|
+
# @yield |writer, content_type|
|
112
|
+
# @yield_param [RDF::Writer] writer
|
113
|
+
# @yield_param [String] content_type from accept media-range without parameters
|
114
|
+
# @yield_param [Hash{Symbol => String}] accept_params from accept media-range
|
115
|
+
# @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
|
116
|
+
def find_writer(env, headers)
|
117
|
+
if @options[:format]
|
118
|
+
format = @options[:format]
|
119
|
+
writer = ::RDF::Writer.for(format.to_sym)
|
120
|
+
yield(writer, writer.format.content_type.first) if writer
|
121
|
+
elsif env.has_key?('HTTP_ACCEPT')
|
122
|
+
content_types = parse_accept_header(env['HTTP_ACCEPT'])
|
123
|
+
content_types.each do |content_type|
|
124
|
+
find_writer_for_content_type(content_type) do |writer, ct, accept_params|
|
125
|
+
# Yields content type with parameters
|
126
|
+
yield(writer, ct, accept_params)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
else
|
130
|
+
# HTTP/1.1 §14.1: "If no Accept header field is present, then it is
|
131
|
+
# assumed that the client accepts all media types"
|
132
|
+
find_writer_for_content_type(options[:default]) do |writer, ct|
|
133
|
+
# Yields content type with parameters
|
134
|
+
yield(writer, ct)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
##
|
140
|
+
# Yields an `RDF::Writer` class for the given `content_type`.
|
141
|
+
#
|
142
|
+
# Calls `Writer#accept?(content_type)` for matched content type to allow writers to further discriminate on how if to accept content-type with specified parameters.
|
143
|
+
#
|
144
|
+
# @param [String, #to_s] content_type
|
145
|
+
# @yield |writer, content_type|
|
146
|
+
# @yield_param [RDF::Writer] writer
|
147
|
+
# @yield_param [String] content_type (including media-type parameters)
|
148
|
+
def find_writer_for_content_type(content_type)
|
149
|
+
ct, *params = content_type.split(';').map(&:strip)
|
150
|
+
accept_params = params.inject({}) do |memo, pv|
|
151
|
+
p, v = pv.split('=').map(&:strip)
|
152
|
+
memo.merge(p.downcase.to_sym => v.sub(/^["']?([^"']*)["']?$/, '\1'))
|
153
|
+
end
|
154
|
+
formats = ::RDF::Format.each(content_type: ct, has_writer: true).to_a.reverse
|
155
|
+
formats.each do |format|
|
156
|
+
yield format.writer, (ct || format.content_type.first), accept_params if
|
157
|
+
format.writer.accept?(accept_params)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
##
|
162
|
+
# Parses an HTTP `Accept` header, returning an array of MIME content
|
163
|
+
# types ordered by the precedence rules defined in HTTP/1.1 §14.1.
|
164
|
+
#
|
165
|
+
# @param [String, #to_s] header
|
166
|
+
# @return [Array<String>]
|
167
|
+
# @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1
|
168
|
+
def parse_accept_header(header)
|
169
|
+
entries = header.to_s.split(',')
|
170
|
+
entries = entries.map { |e| accept_entry(e) }.sort_by(&:last).map(&:first)
|
171
|
+
entries.map { |e| find_content_type_for_media_range(e) }.flatten.compact
|
172
|
+
end
|
173
|
+
|
174
|
+
# Returns pair of content_type (including non-'q' parameters)
|
175
|
+
# and array of quality, number of '*' in content-type, and number of non-'q' parameters
|
176
|
+
def accept_entry(entry)
|
177
|
+
type, *options = entry.split(';').map(&:strip)
|
178
|
+
quality = 0 # we sort smallest first
|
179
|
+
options.delete_if { |e| quality = 1 - e[2..-1].to_f if e.start_with? 'q=' }
|
180
|
+
[options.unshift(type).join(';'), [quality, type.count('*'), 1 - options.size]]
|
181
|
+
end
|
182
|
+
|
183
|
+
##
|
184
|
+
# Returns a content type appropriate for the given `media_range`,
|
185
|
+
# returns `nil` if `media_range` contains a wildcard subtype
|
186
|
+
# that is not mapped.
|
187
|
+
#
|
188
|
+
# @param [String, #to_s] media_range
|
189
|
+
# @return [String, nil]
|
190
|
+
def find_content_type_for_media_range(media_range)
|
191
|
+
case media_range.to_s
|
192
|
+
when '*/*'
|
193
|
+
options[:default]
|
194
|
+
when 'text/*'
|
195
|
+
'text/turtle'
|
196
|
+
when 'application/*'
|
197
|
+
'application/ld+json'
|
198
|
+
when 'application/json'
|
199
|
+
'application/ld+json'
|
200
|
+
when 'application/xml'
|
201
|
+
'application/rdf+xml'
|
202
|
+
when /^([^\/]+)\/\*$/
|
203
|
+
nil
|
204
|
+
else
|
205
|
+
media_range.to_s
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
##
|
210
|
+
# Outputs an HTTP `406 Not Acceptable` response.
|
211
|
+
#
|
212
|
+
# @param [String, #to_s] message
|
213
|
+
# @return [Array(Integer, Hash, #each)]
|
214
|
+
def not_acceptable(message = nil)
|
215
|
+
http_error(406, message, VARY)
|
216
|
+
end
|
217
|
+
|
218
|
+
##
|
219
|
+
# Outputs an HTTP `4xx` or `5xx` response.
|
220
|
+
#
|
221
|
+
# @param [Integer, #to_i] code
|
222
|
+
# @param [String, #to_s] message
|
223
|
+
# @param [Hash{String => String}] headers
|
224
|
+
# @return [Array(Integer, Hash, #each)]
|
225
|
+
def http_error(code, message = nil, headers = {})
|
226
|
+
message = http_status(code) + (message.nil? ? "\n" : " (#{message})\n")
|
227
|
+
[code, {'Content-Type' => "text/plain"}.merge(headers), [message]]
|
228
|
+
end
|
229
|
+
|
230
|
+
##
|
231
|
+
# Returns the standard HTTP status message for the given status `code`.
|
232
|
+
#
|
233
|
+
# @param [Integer, #to_i] code
|
234
|
+
# @return [String]
|
235
|
+
def http_status(code)
|
236
|
+
[code, Rack::Utils::HTTP_STATUS_CODES[code]].join(' ')
|
237
|
+
end
|
238
|
+
end # class ContentNegotiation
|
239
|
+
end; end # module Rack::RDF
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Rack; module RDF
|
2
|
+
module VERSION
|
3
|
+
VERSION_FILE = ::File.expand_path("../../../../VERSION", __FILE__)
|
4
|
+
MAJOR, MINOR, TINY, EXTRA = ::File.read(VERSION_FILE).chomp.split(".")
|
5
|
+
|
6
|
+
STRING = [MAJOR, MINOR, TINY, EXTRA].compact.join('.')
|
7
|
+
|
8
|
+
##
|
9
|
+
# @return [String]
|
10
|
+
def self.to_s() STRING end
|
11
|
+
|
12
|
+
##
|
13
|
+
# @return [String]
|
14
|
+
def self.to_str() STRING end
|
15
|
+
|
16
|
+
##
|
17
|
+
# @return [Array(Integer, Integer, Integer)]
|
18
|
+
def self.to_a() [MAJOR, MINOR, TINY] end
|
19
|
+
end
|
20
|
+
end; end
|
metadata
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rack-rdf
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 3.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Arto Bendiken
|
8
|
+
- Gregg Kellogg
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2020-02-13 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rdf
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - "~>"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '3.1'
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - "~>"
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '3.1'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: rack
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - "~>"
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '2.1'
|
35
|
+
type: :runtime
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - "~>"
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '2.1'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: yard
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - "~>"
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0.9'
|
49
|
+
type: :development
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - "~>"
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0.9'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: rspec
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - "~>"
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '3.9'
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '3.9'
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: rack-test
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - "~>"
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '1.1'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - "~>"
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '1.1'
|
84
|
+
description: Rack middleware for Linked Data content negotiation.
|
85
|
+
email: public-rdf-ruby@w3.org
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- AUTHORS
|
91
|
+
- CREDITS
|
92
|
+
- README.md
|
93
|
+
- UNLICENSE
|
94
|
+
- VERSION
|
95
|
+
- lib/rack/rdf.rb
|
96
|
+
- lib/rack/rdf/conneg.rb
|
97
|
+
- lib/rack/rdf/version.rb
|
98
|
+
homepage: http://ruby-rdf.github.com/rack-rdf
|
99
|
+
licenses:
|
100
|
+
- Unlicense
|
101
|
+
metadata: {}
|
102
|
+
post_install_message:
|
103
|
+
rdoc_options: []
|
104
|
+
require_paths:
|
105
|
+
- lib
|
106
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '2.4'
|
111
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
112
|
+
requirements:
|
113
|
+
- - ">="
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
version: '0'
|
116
|
+
requirements: []
|
117
|
+
rubygems_version: 3.1.2
|
118
|
+
signing_key:
|
119
|
+
specification_version: 4
|
120
|
+
summary: Linked Data content negotiation for Rack applications.
|
121
|
+
test_files: []
|