rack-rdf 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []