safrano 0.4.1 → 0.4.6
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 +4 -4
- data/lib/core_ext/Dir/iter.rb +18 -0
- data/lib/core_ext/Hash/transform.rb +21 -0
- data/lib/core_ext/Integer/edm.rb +13 -0
- data/lib/core_ext/REXML/Document/output.rb +16 -0
- data/lib/core_ext/String/convert.rb +25 -0
- data/lib/core_ext/String/edm.rb +13 -0
- data/lib/core_ext/dir.rb +3 -0
- data/lib/core_ext/hash.rb +3 -0
- data/lib/core_ext/integer.rb +3 -0
- data/lib/core_ext/rexml.rb +3 -0
- data/lib/core_ext/string.rb +5 -0
- data/lib/odata/attribute.rb +15 -10
- data/lib/odata/batch.rb +15 -13
- data/lib/odata/collection.rb +144 -535
- data/lib/odata/collection_filter.rb +47 -40
- data/lib/odata/collection_media.rb +155 -99
- data/lib/odata/collection_order.rb +50 -37
- data/lib/odata/common_logger.rb +36 -34
- data/lib/odata/complex_type.rb +152 -0
- data/lib/odata/edm/primitive_types.rb +184 -0
- data/lib/odata/entity.rb +183 -216
- data/lib/odata/error.rb +195 -31
- data/lib/odata/expand.rb +126 -0
- data/lib/odata/filter/base.rb +74 -0
- data/lib/odata/filter/error.rb +49 -6
- data/lib/odata/filter/parse.rb +44 -36
- data/lib/odata/filter/sequel.rb +136 -67
- data/lib/odata/filter/sequel_function_adapter.rb +148 -0
- data/lib/odata/filter/token.rb +26 -19
- data/lib/odata/filter/tree.rb +113 -63
- data/lib/odata/function_import.rb +168 -0
- data/lib/odata/model_ext.rb +639 -0
- data/lib/odata/navigation_attribute.rb +44 -61
- data/lib/odata/relations.rb +5 -5
- data/lib/odata/select.rb +54 -0
- data/lib/odata/transition.rb +71 -0
- data/lib/odata/url_parameters.rb +128 -37
- data/lib/odata/walker.rb +20 -10
- data/lib/safrano.rb +17 -37
- data/lib/safrano/contract.rb +143 -0
- data/lib/safrano/core.rb +29 -104
- data/lib/safrano/core_ext.rb +13 -0
- data/lib/safrano/deprecation.rb +73 -0
- data/lib/safrano/multipart.rb +39 -43
- data/lib/safrano/rack_app.rb +68 -67
- data/lib/safrano/{odata_rack_builder.rb → rack_builder.rb} +18 -2
- data/lib/safrano/request.rb +102 -51
- data/lib/safrano/response.rb +5 -3
- data/lib/safrano/sequel_join_by_paths.rb +2 -2
- data/lib/safrano/service.rb +274 -219
- data/lib/safrano/version.rb +3 -1
- data/lib/sequel/plugins/join_by_paths.rb +17 -29
- metadata +34 -11
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
# shamelessly copied from Sequel...
|
4
|
+
|
5
|
+
module Safrano
|
6
|
+
# This module makes it easy to print deprecation warnings with optional backtraces to a given stream.
|
7
|
+
# There are a two accessors you can use to change how/where the deprecation methods are printed
|
8
|
+
# and whether/how backtraces should be included:
|
9
|
+
#
|
10
|
+
# Safrano::Deprecation.output = $stderr # print deprecation messages to standard error (default)
|
11
|
+
# Safrano::Deprecation.output = File.open('deprecated_calls.txt', 'wb') # use a file instead
|
12
|
+
# Safrano::Deprecation.output = false # do not output deprecation messages
|
13
|
+
#
|
14
|
+
# Safrano::Deprecation.prefix = "SAFRANO DEPRECATION WARNING: " # prefix deprecation messages with a given string (default)
|
15
|
+
# Safrano::Deprecation.prefix = false # do not prefix deprecation messages
|
16
|
+
#
|
17
|
+
# Safrano::Deprecation.backtrace_filter = false # don't include backtraces
|
18
|
+
# Safrano::Deprecation.backtrace_filter = true # include full backtraces
|
19
|
+
# Safrano::Deprecation.backtrace_filter = 2 # include 2 backtrace lines (default)
|
20
|
+
# Safrano::Deprecation.backtrace_filter = 1 # include 1 backtrace line
|
21
|
+
# Safrano::Deprecation.backtrace_filter = lambda{|line, line_no| line_no < 3 || line =~ /my_app/} # select backtrace lines to output
|
22
|
+
module Deprecation
|
23
|
+
@backtrace_filter = false
|
24
|
+
@output = $stderr
|
25
|
+
@prefix = 'SAFRANO DEPRECATION WARNING: '
|
26
|
+
|
27
|
+
class << self
|
28
|
+
# How to filter backtraces. +false+ does not include backtraces, +true+ includes
|
29
|
+
# full backtraces, an Integer includes that number of backtrace lines, and
|
30
|
+
# a proc is called with the backtrace line and line number to select the backtrace
|
31
|
+
# lines to include. The default is no backtrace .
|
32
|
+
attr_accessor :backtrace_filter
|
33
|
+
|
34
|
+
# Where deprecation messages should be output, must respond to puts. $stderr by default.
|
35
|
+
attr_accessor :output
|
36
|
+
|
37
|
+
# Where deprecation messages should be prefixed with ("SEQUEL DEPRECATION WARNING: " by default).
|
38
|
+
attr_accessor :prefix
|
39
|
+
end
|
40
|
+
|
41
|
+
# Print the message and possibly backtrace to the output.
|
42
|
+
def self.deprecate(method, instead = nil)
|
43
|
+
return unless output
|
44
|
+
|
45
|
+
message = instead ? "#{method} is deprecated and will be removed in Safrano 0.6. #{instead}." : method
|
46
|
+
message = "#{prefix}#{message}" if prefix
|
47
|
+
output.puts(message)
|
48
|
+
case b = backtrace_filter
|
49
|
+
when Integer
|
50
|
+
caller.each do |c|
|
51
|
+
b -= 1
|
52
|
+
output.puts(c)
|
53
|
+
break if b <= 0
|
54
|
+
end
|
55
|
+
when true
|
56
|
+
caller.each { |c| output.puts(c) }
|
57
|
+
when Proc
|
58
|
+
caller.each_with_index { |line, line_no| output.puts(line) if b.call(line, line_no) }
|
59
|
+
end
|
60
|
+
nil
|
61
|
+
end
|
62
|
+
|
63
|
+
# If using ruby 2.3+, use Module#deprecate_constant to deprecate the constant,
|
64
|
+
# otherwise do nothing as the ruby implementation does not support constant deprecation.
|
65
|
+
def self.deprecate_constant(mod, constant)
|
66
|
+
# :nocov:
|
67
|
+
return unless RUBY_VERSION > '2.3'
|
68
|
+
|
69
|
+
# :nocov:
|
70
|
+
mod.deprecate_constant(constant)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/lib/safrano/multipart.rb
CHANGED
@@ -1,21 +1,25 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
CRLF = "\r\n"
|
4
|
+
LF = "\n"
|
3
5
|
|
4
6
|
require 'securerandom'
|
5
7
|
require 'webrick/httpstatus'
|
6
8
|
|
7
9
|
# Simple multipart support for OData $batch purpose
|
8
10
|
module MIME
|
11
|
+
CTT_TYPE_LC = 'content-type'
|
12
|
+
TEXT_PLAIN = 'text/plain'
|
13
|
+
|
9
14
|
# a mime object has a header(with content-type etc) and a content(aka body)
|
10
15
|
class Media
|
11
16
|
# Parser for MIME::Media
|
12
17
|
class Parser
|
13
18
|
HMD_RGX = /^([\w-]+)\s*:\s*(.*)/.freeze
|
14
19
|
|
15
|
-
CRLF_LINE_RGX = /^#{CRLF}$/.freeze
|
16
|
-
|
17
20
|
attr_accessor :lines
|
18
21
|
attr_accessor :target
|
22
|
+
|
19
23
|
def initialize
|
20
24
|
@state = :h
|
21
25
|
@lines = []
|
@@ -54,9 +58,8 @@ module MIME
|
|
54
58
|
if (hmd = HMD_RGX.match(line))
|
55
59
|
@target_hd[hmd[1].downcase] = hmd[2].strip
|
56
60
|
|
57
|
-
# elsif CRLF_LINE_RGX =~ line
|
58
61
|
elsif CRLF == line
|
59
|
-
@target_ct = @target_hd[
|
62
|
+
@target_ct = @target_hd[CTT_TYPE_LC] || TEXT_PLAIN
|
60
63
|
@state = new_content
|
61
64
|
|
62
65
|
end
|
@@ -100,24 +103,22 @@ module MIME
|
|
100
103
|
end
|
101
104
|
|
102
105
|
def hook_multipart(content_type, boundary)
|
103
|
-
@target_hd[
|
104
|
-
@target_ct = @target_hd[
|
106
|
+
@target_hd[CTT_TYPE_LC] = content_type
|
107
|
+
@target_ct = @target_hd[CTT_TYPE_LC]
|
105
108
|
@target = multipart_content(boundary)
|
106
109
|
@target.hd = @target_hd
|
107
110
|
@target.ct = @target_ct
|
108
111
|
@state = :bmp
|
109
112
|
end
|
110
|
-
MPS = 'multipart/'
|
111
|
-
MP_RGX1 = %r{^(digest|mixed);\s*boundary
|
113
|
+
MPS = 'multipart/'
|
114
|
+
MP_RGX1 = %r{^(digest|mixed);\s*boundary="(.*)"}.freeze
|
112
115
|
MP_RGX2 = %r{^(digest|mixed);\s*boundary=(.*)}.freeze
|
113
116
|
# APP_HTTP_RGX = %r{^application/http}.freeze
|
114
|
-
APP_HTTP = 'application/http'
|
117
|
+
APP_HTTP = 'application/http'
|
115
118
|
def new_content
|
116
119
|
@target =
|
117
|
-
if @target_ct.start_with?(MPS)
|
118
|
-
(md = (
|
119
|
-
(MP_RGX2.match(@target_ct[10..-1])))
|
120
|
-
)
|
120
|
+
if @target_ct.start_with?(MPS) &&
|
121
|
+
(md = (MP_RGX1.match(@target_ct[10..-1]) || MP_RGX2.match(@target_ct[10..-1])))
|
121
122
|
multipart_content(md[2].strip)
|
122
123
|
elsif @target_ct.start_with?(APP_HTTP)
|
123
124
|
MIME::Content::Application::Http.new
|
@@ -198,7 +199,6 @@ module MIME
|
|
198
199
|
# Parser for Text::Plain
|
199
200
|
class Parser
|
200
201
|
HMD_RGX = /^([\w-]+)\s*:\s*(.*)/.freeze
|
201
|
-
CRLF_LINE_RGX = /^#{CRLF}$/.freeze
|
202
202
|
def initialize(target)
|
203
203
|
@state = :h
|
204
204
|
@lines = []
|
@@ -212,7 +212,6 @@ module MIME
|
|
212
212
|
def parse_head(line)
|
213
213
|
if (hmd = HMD_RGX.match(line))
|
214
214
|
@target.hd[hmd[1].downcase] = hmd[2].strip
|
215
|
-
# elsif CRLF_LINE_RGX =~ line
|
216
215
|
elsif CRLF == line
|
217
216
|
@state = :b
|
218
217
|
else
|
@@ -241,10 +240,11 @@ module MIME
|
|
241
240
|
|
242
241
|
def initialize
|
243
242
|
@hd = {}
|
244
|
-
|
243
|
+
# we need it unfrozen --> +
|
244
|
+
@content = +''
|
245
245
|
# set default values. Can be overwritten by parser
|
246
|
-
@hd[
|
247
|
-
@ct =
|
246
|
+
@hd[CTT_TYPE_LC] = TEXT_PLAIN
|
247
|
+
@ct = TEXT_PLAIN
|
248
248
|
@parser = Parser.new(self)
|
249
249
|
end
|
250
250
|
|
@@ -309,8 +309,10 @@ module MIME
|
|
309
309
|
# to remove it from the end of the last body line
|
310
310
|
return unless @body_lines
|
311
311
|
|
312
|
-
#
|
313
|
-
@body_lines.last.chomp!(CRLF)
|
312
|
+
# the last line ends up frozen --> chomp! fails
|
313
|
+
# @body_lines.last.chomp!(CRLF)
|
314
|
+
last_line = @body_lines.pop.chomp(CRLF)
|
315
|
+
@body_lines.push last_line
|
314
316
|
@parts << @body_lines
|
315
317
|
end
|
316
318
|
|
@@ -364,7 +366,7 @@ module MIME
|
|
364
366
|
end
|
365
367
|
|
366
368
|
def set_multipart_header
|
367
|
-
@hd[
|
369
|
+
@hd[CTT_TYPE_LC] = "#{Safrano::MP_MIXED}; boundary=#{@boundary}"
|
368
370
|
end
|
369
371
|
|
370
372
|
def get_http_resp(batcha)
|
@@ -382,9 +384,7 @@ module MIME
|
|
382
384
|
# of the changes
|
383
385
|
batcha.db.transaction do
|
384
386
|
begin
|
385
|
-
@response.content = @content.map { |part|
|
386
|
-
part.get_response(batcha)
|
387
|
-
}
|
387
|
+
@response.content = @content.map { |part| part.get_response(batcha) }
|
388
388
|
rescue Sequel::Rollback => e
|
389
389
|
# one of the changes of the changeset has failed
|
390
390
|
# --> provide a dummy empty response for the change-parts
|
@@ -405,18 +405,18 @@ module MIME
|
|
405
405
|
@response.content = [{ 'odata.error' =>
|
406
406
|
{ 'message' =>
|
407
407
|
'Bad Request: Failed changeset ' } }.to_json]
|
408
|
-
@response.hd =
|
408
|
+
@response.hd = Safrano::CT_JSON
|
409
409
|
@response
|
410
410
|
end
|
411
411
|
|
412
412
|
def unparse(bodyonly = false)
|
413
|
-
b =
|
413
|
+
b = +String.new
|
414
414
|
unless bodyonly
|
415
|
-
|
416
|
-
b << "#{OData::CONTENT_TYPE}: #{@hd[OData::CTT_TYPE_LC]}#{CRLF}"
|
415
|
+
b << "#{Safrano::CONTENT_TYPE}: #{@hd[CTT_TYPE_LC]}#{CRLF}"
|
417
416
|
end
|
418
|
-
|
419
|
-
b <<
|
417
|
+
|
418
|
+
b << crbdcr = "#{CRLF}--#{@boundary}#{CRLF}"
|
419
|
+
b << @content.map(&:unparse).join(crbdcr)
|
420
420
|
b << "#{CRLF}--#{@boundary}--#{CRLF}"
|
421
421
|
b
|
422
422
|
end
|
@@ -436,15 +436,14 @@ module MIME
|
|
436
436
|
|
437
437
|
def initialize
|
438
438
|
@hd = {}
|
439
|
-
@content =
|
439
|
+
@content = +String.new
|
440
440
|
end
|
441
441
|
|
442
442
|
def unparse
|
443
|
-
b = "#{@http_method} #{@uri} HTTP/1.1#{CRLF}"
|
443
|
+
b = +"#{@http_method} #{@uri} HTTP/1.1#{CRLF}"
|
444
444
|
@hd.each { |k, v| b << "#{k}: #{v}#{CRLF}" }
|
445
|
-
# @hd.each { |k, v| b << k.to_s << ': ' << v.to_s << CRLF }
|
446
445
|
b << CRLF
|
447
|
-
b << @content
|
446
|
+
b << @content unless content.empty?
|
448
447
|
b
|
449
448
|
end
|
450
449
|
end
|
@@ -470,10 +469,9 @@ module MIME
|
|
470
469
|
end
|
471
470
|
|
472
471
|
def unparse
|
473
|
-
b = String.new(APPLICATION_HTTP_11)
|
472
|
+
b = +String.new(APPLICATION_HTTP_11)
|
474
473
|
b << "#{@status} #{StatusMessage[@status]} #{CRLF}"
|
475
474
|
@hd.each { |k, v| b << "#{k}: #{v}#{CRLF}" }
|
476
|
-
# @hd.each { |k, v| b << k.to_s << ': ' << v.to_s << CRLF }
|
477
475
|
b << CRLF
|
478
476
|
b << @content.join if @content
|
479
477
|
b
|
@@ -482,15 +480,14 @@ module MIME
|
|
482
480
|
|
483
481
|
# For application/http . Content is either a Request or a Response
|
484
482
|
class Http < Media
|
485
|
-
HTTP_MTHS_RGX = 'POST|GET|PUT|MERGE|PATCH|DELETE'
|
483
|
+
HTTP_MTHS_RGX = 'POST|GET|PUT|MERGE|PATCH|DELETE'
|
486
484
|
HTTP_R_RGX = %r{^(#{HTTP_MTHS_RGX})\s+(\S*)\s?(HTTP/1\.1)\s*$}.freeze
|
487
|
-
HEADER_RGX = %r{^([a-zA-Z\-]+):\s*([0-9a-zA-Z
|
485
|
+
HEADER_RGX = %r{^([a-zA-Z\-]+):\s*([0-9a-zA-Z\-/,\s]+;?\S*)\s*$}.freeze
|
488
486
|
HTTP_RESP_RGX = %r{^HTTP/1\.1\s(\d+)\s}.freeze
|
489
487
|
|
490
488
|
# Parser for Http Media
|
491
489
|
class Parser
|
492
490
|
HMD_RGX = /^([\w-]+)\s*:\s*(.*)/.freeze
|
493
|
-
CRLF_LINE_RGX = /^#{CRLF}$/.freeze
|
494
491
|
|
495
492
|
def initialize(target)
|
496
493
|
@state = :http
|
@@ -523,7 +520,6 @@ module MIME
|
|
523
520
|
if (hmd = HMD_RGX.match(line))
|
524
521
|
@target.content.hd[hmd[1].downcase] = hmd[2].strip
|
525
522
|
elsif CRLF == line
|
526
|
-
# elsif CRLF_LINE_RGX =~ line
|
527
523
|
@state = :b
|
528
524
|
else
|
529
525
|
@body_lines << line
|
@@ -575,7 +571,7 @@ module MIME
|
|
575
571
|
end
|
576
572
|
|
577
573
|
def unparse
|
578
|
-
b = "Content-Type: #{@ct}#{CRLF}"
|
574
|
+
b = +"Content-Type: #{@ct}#{CRLF}"
|
579
575
|
b << "Content-Transfer-Encoding: binary#{CRLF}#{CRLF}"
|
580
576
|
b << @content.unparse
|
581
577
|
b
|
data/lib/safrano/rack_app.rb
CHANGED
@@ -1,98 +1,72 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'rack'
|
4
|
-
require_relative '../odata/walker
|
5
|
-
require_relative 'request
|
6
|
-
require_relative 'response
|
4
|
+
require_relative '../odata/walker'
|
5
|
+
require_relative 'request'
|
6
|
+
require_relative 'response'
|
7
7
|
|
8
|
-
module
|
8
|
+
module Safrano
|
9
9
|
# handle GET PUT etc
|
10
10
|
module MethodHandlers
|
11
11
|
def odata_options
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
end
|
21
|
-
@response.headers['Content-Type'] = ''
|
22
|
-
x
|
23
|
-
end
|
24
|
-
|
25
|
-
def odata_error
|
26
|
-
return @walker.error.odata_get(@request) unless @walker.error.nil?
|
27
|
-
|
28
|
-
# this is too critical; raise a real Exception
|
29
|
-
raise 'Walker construction failed with a unknown Error '
|
12
|
+
@walker.finalize.tap_error { |err| return err.odata_get(@request) }
|
13
|
+
.if_valid do |context|
|
14
|
+
# cf. stackoverflow.com/questions/22924678/sinatra-delete-response-headers
|
15
|
+
headers.delete('Content-Type')
|
16
|
+
@response.headers.delete('Content-Type')
|
17
|
+
@response.headers['Content-Type'] = ''
|
18
|
+
[200, EMPTY_HASH, '']
|
19
|
+
end
|
30
20
|
end
|
31
21
|
|
32
22
|
def odata_delete
|
33
|
-
|
34
|
-
|
35
|
-
else
|
36
|
-
odata_error
|
37
|
-
end
|
23
|
+
@walker.finalize.tap_error { |err| return err.odata_get(@request) }
|
24
|
+
.if_valid { |context| context.odata_delete(@request) }
|
38
25
|
end
|
39
26
|
|
40
27
|
def odata_put
|
41
|
-
|
42
|
-
|
43
|
-
else
|
44
|
-
odata_error
|
45
|
-
end
|
28
|
+
@walker.finalize.tap_error { |err| return err.odata_get(@request) }
|
29
|
+
.if_valid { |context| context.odata_put(@request) }
|
46
30
|
end
|
47
31
|
|
48
32
|
def odata_patch
|
49
|
-
|
50
|
-
|
51
|
-
else
|
52
|
-
odata_error
|
53
|
-
end
|
33
|
+
@walker.finalize.tap_error { |err| return err.odata_get(@request) }
|
34
|
+
.if_valid { |context| context.odata_patch(@request) }
|
54
35
|
end
|
55
36
|
|
56
37
|
def odata_get
|
57
|
-
|
58
|
-
|
59
|
-
else
|
60
|
-
odata_error
|
61
|
-
end
|
38
|
+
@walker.finalize.tap_error { |err| return err.odata_get(@request) }
|
39
|
+
.if_valid { |context| context.odata_get(@request) }
|
62
40
|
end
|
63
41
|
|
64
42
|
def odata_post
|
65
|
-
|
66
|
-
|
67
|
-
else
|
68
|
-
odata_error
|
69
|
-
end
|
43
|
+
@walker.finalize.tap_error { |err| return err.odata_get(@request) }
|
44
|
+
.if_valid { |context| context.odata_post(@request) }
|
70
45
|
end
|
71
46
|
|
72
47
|
def odata_head
|
73
|
-
[200,
|
48
|
+
[200, EMPTY_HASH, [EMPTY_STRING]]
|
74
49
|
end
|
75
50
|
end
|
76
51
|
|
77
52
|
# the main Rack server app. Source: the Rack docu/examples and partly
|
78
53
|
# inspired from Sinatra
|
79
54
|
class ServerApp
|
80
|
-
METHODS_REGEXP = Regexp.new('HEAD|OPTIONS|GET|POST|PATCH|MERGE|PUT|DELETE')
|
55
|
+
METHODS_REGEXP = Regexp.new('HEAD|OPTIONS|GET|POST|PATCH|MERGE|PUT|DELETE').freeze
|
56
|
+
NOCACHE_HDRS = { 'Cache-Control' => 'no-cache',
|
57
|
+
'Expires' => '-1',
|
58
|
+
'Pragma' => 'no-cache' }.freeze
|
59
|
+
DATASERVICEVERSION = 'DataServiceVersion'
|
81
60
|
include MethodHandlers
|
82
|
-
def before
|
83
|
-
headers 'Cache-Control' => 'no-cache'
|
84
|
-
headers 'Expires' => '-1'
|
85
|
-
headers 'Pragma' => 'no-cache'
|
86
61
|
|
62
|
+
def before
|
87
63
|
@request.service_base = self.class.get_service_base
|
88
64
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
headers 'DataServiceVersion' => @request.service.data_service_version
|
65
|
+
@request.negotiate_service_version.tap_valid do
|
66
|
+
myhdrs = NOCACHE_HDRS.dup
|
67
|
+
myhdrs[DATASERVICEVERSION] = @request.service.data_service_version
|
68
|
+
headers myhdrs
|
69
|
+
end
|
96
70
|
end
|
97
71
|
|
98
72
|
# dispatch for all methods requiring parsing of the path
|
@@ -117,9 +91,14 @@ module OData
|
|
117
91
|
end
|
118
92
|
end
|
119
93
|
|
94
|
+
def dispatch_error(err)
|
95
|
+
@response.status, rsph, @response.body = err.odata_get(@request)
|
96
|
+
headers rsph
|
97
|
+
end
|
98
|
+
|
120
99
|
def dispatch
|
121
100
|
req_ret = if @request.request_method !~ METHODS_REGEXP
|
122
|
-
[404,
|
101
|
+
[404, EMPTY_HASH, ['Did you get lost?']]
|
123
102
|
elsif @request.request_method == 'HEAD'
|
124
103
|
odata_head
|
125
104
|
else
|
@@ -130,13 +109,23 @@ module OData
|
|
130
109
|
end
|
131
110
|
|
132
111
|
def call(env)
|
133
|
-
|
134
|
-
|
112
|
+
# for thread safety
|
113
|
+
dup._call(env)
|
114
|
+
end
|
135
115
|
|
136
|
-
|
116
|
+
def _call(env)
|
117
|
+
begin
|
118
|
+
@request = Safrano::Request.new(env)
|
119
|
+
@response = Safrano::Response.new
|
137
120
|
|
138
|
-
|
121
|
+
before.tap_error { |err| dispatch_error(err) }
|
122
|
+
.tap_valid { |res| dispatch }
|
139
123
|
|
124
|
+
# handle remaining Sequel errors that we couldnt prevent with our
|
125
|
+
# own pre-checks
|
126
|
+
rescue Sequel::Error => e
|
127
|
+
dispatch_error(SequelExceptionError.new(e))
|
128
|
+
end
|
140
129
|
@response.finish
|
141
130
|
end
|
142
131
|
|
@@ -165,10 +154,22 @@ module OData
|
|
165
154
|
end
|
166
155
|
|
167
156
|
def self.publish_service(&block)
|
168
|
-
sbase =
|
157
|
+
sbase = Safrano::ServiceBase.new
|
169
158
|
sbase.instance_eval(&block) if block_given?
|
170
159
|
sbase.finalize_publishing
|
171
160
|
set_servicebase(sbase)
|
172
161
|
end
|
173
162
|
end
|
174
163
|
end
|
164
|
+
|
165
|
+
# deprecated
|
166
|
+
# REMOVE 0.6
|
167
|
+
module OData
|
168
|
+
class ServerApp < Safrano::ServerApp
|
169
|
+
def self.publish_service(&block)
|
170
|
+
::Safrano::Deprecation.deprecate('OData::ServerApp',
|
171
|
+
'Use Safrano::ServerApp instead')
|
172
|
+
super
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|