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.
@@ -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
@@ -0,0 +1,2 @@
1
+ * Arto Bendiken <arto.bendiken@gmail.com>
2
+ * Gregg Kellogg <gregg@greggkellogg.net>
data/CREDITS ADDED
@@ -0,0 +1 @@
1
+ * Gregg Kellogg <gregg@greggkellogg.net>
@@ -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
+ [![Gem Version](https://badge.fury.io/rb/rack-rdf.png)](http://badge.fury.io/rb/rack-rdf)
13
+ [![Build Status](https://travis-ci.org/ruby-rdf/rack-rdf.png?branch=master)](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
@@ -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
@@ -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: []