Module: Sinatra::REST::Helpers
- Defined in:
- lib/sinatra/rest/helpers.rb
Overview
Constant Summary collapse
- INFINITY =
1/0.0
Instance Method Summary collapse
- #compute_etag(*args) ⇒ Object
-
#decode(proc, config = {}) ⇒ Object
Automatically decode the input data (coming from a POST or PUT request) based on the request’s content-type.
-
#provides(*formats) ⇒ Object
e.g.
Instance Method Details
#compute_etag(*args) ⇒ Object
13 14 15 16 |
# File 'lib/sinatra/rest/helpers.rb', line 13 def compute_etag(*args) raise ArgumentError, "You must provide at least one parameter for the ETag computation" if args.empty? Digest::SHA1.hexdigest(args.join(".")) end |
#decode(proc, config = {}) ⇒ Object
Automatically decode the input data (coming from a POST or PUT request) based on the request’s content-type. You must pass a Proc that will return the parser object to use to decode the payload. The parser object must respond to a parse
method. You may also pass a hash of options:
-
:size_range
: byte range specifying the minimum and maximum length (in bytes) of the payload [default=(1..1024**3)]
e.g.
post '/resource' do
data = decode lambda{|content_type| if content_type =~ /^application\/.*json$/i then JSON}, :size_range => (1..2*1024**3)
end
The processing of the request will be halted in the following cases:
-
400 if the payload is not within the specified size range.
-
400 if the payload cannot be correctly parsed.
-
415 if the payload’s content type is not supported (i.e. the given Proc returns nil)
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/sinatra/rest/helpers.rb', line 81 def decode(proc, config = {}) raise ArgumentError, "You must pass an object that responds to #call" unless proc.respond_to?(:call) size_range = config.delete(:size_range) || (1..(1024**3)) case (mime_type = request.env['CONTENT_TYPE']) when /^application\/x-www-form-urlencoded/i request.env['sinatra.decoded_input'] = request.env['rack.request.form_hash'] else content = "" request.env['rack.input'].each do |block| content.concat(block) break if content.length > size_range.end end if not size_range.include?(content.length) halt 400, "Input data size must be between #{size_range.begin} and #{size_range.end} bytes." elsif parser = proc.call(mime_type) begin parser.parse(content) rescue StandardError => e halt 400, "#{e.class.name}: #{e.}" end else halt 415, "Format #{mime_type} not supported" end end end |
#provides(*formats) ⇒ Object
e.g.
get '/' do
provides :xml, "text/html;level=5"
"Hello"
end
will accept requests having an Accept header containing at least one of the following value:
-
application/xml
-
application/*
-
text/html
-
text/html;level=5
-
text/html;level=6
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/sinatra/rest/helpers.rb', line 29 def provides(*formats) generate_type_hash = Proc.new{ |header| type, *params = header.split(/;\s*/) Hash[*params.map{|p| p.split(/\s*=\s*/)}.flatten].merge("type" => type) } supported_formats = formats.map do |f| # selects the correct mime type if a symbol is given f.is_a?(Symbol) ? ::Rack::Mime::MIME_TYPES[".#{f.to_s}"] : f end.compact.map do |f| generate_type_hash.call(f) end # request.accept is an Array accepted_formats = request.accept.map do |f| generate_type_hash.call(f) end selected_format = nil accepted_formats.each{ |accepted_format| selected_format = supported_formats.detect{ |supported_format| Regexp.new(Regexp.escape(accepted_format["type"]).gsub("\\*", ".*?"), Regexp::IGNORECASE) =~ supported_format["type"] && (accepted_format["level"] || INFINITY).to_f >= (supported_format["level"] || 0).to_f } break unless selected_format.nil? } if selected_format.nil? content_type :txt halt 406, supported_formats.map{|f| output = f["type"] output.concat(";level=#{f["level"]}") if f.has_key?("level") output }.join(",") else response.headers['Content-Type'] = "#{selected_format["type"]}#{selected_format["level"].nil? ? "" : ";level=#{selected_format["level"]}"}" end end |