safrano 0.6.7 → 0.7.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 +4 -4
- data/lib/core_ext/DateTime/format.rb +1 -1
- data/lib/core_ext/Time/format.rb +2 -2
- data/lib/odata/batch.rb +39 -33
- data/lib/odata/collection.rb +2 -3
- data/lib/odata/collection_media.rb +92 -81
- data/lib/odata/common_logger.rb +19 -2
- data/lib/odata/complex_type.rb +5 -9
- data/lib/odata/edm/primitive_types.rb +53 -64
- data/lib/odata/entity.rb +1 -2
- data/lib/odata/error.rb +3 -3
- data/lib/odata/expand.rb +0 -3
- data/lib/odata/function_import.rb +5 -3
- data/lib/odata/model_ext.rb +21 -26
- data/lib/odata/walker.rb +8 -15
- data/lib/safrano/multipart.rb +39 -28
- data/lib/safrano/rack_app.rb +14 -123
- data/lib/safrano/request.rb +127 -8
- data/lib/safrano/service.rb +3 -3
- data/lib/safrano/version.rb +1 -1
- data/lib/sequel/plugins/join_by_paths.rb +48 -7
- metadata +18 -6
@@ -38,6 +38,28 @@ module Safrano
|
|
38
38
|
|
39
39
|
# type mappings are hard, especially between "Standards" like SQL and OData V2 (might be a bit better in V4 ?)
|
40
40
|
# this is all best effort/try to make it work logic
|
41
|
+
|
42
|
+
RUBY_TY_EDM_TY_MAP = { integer: 'Edm.Int32',
|
43
|
+
string: 'Edm.String',
|
44
|
+
date: 'Edm.DateTime',
|
45
|
+
datetime: 'Edm.DateTime',
|
46
|
+
time: 'Edm.Time',
|
47
|
+
boolean: 'Edm.Boolean',
|
48
|
+
float: 'Edm.Double',
|
49
|
+
decimal: 'Edm.Decimal',
|
50
|
+
blob: 'Edm.Binary' }.freeze
|
51
|
+
DB_TY_EDM_TY_MAP = { 'smallint' => 'Edm.Int16',
|
52
|
+
'int2' => 'Edm.Int16',
|
53
|
+
'smallserial' => 'Edm.Int16',
|
54
|
+
'int' => 'Edm.Int32',
|
55
|
+
'integer' => 'Edm.Int32',
|
56
|
+
'serial' => 'Edm.Int32',
|
57
|
+
'mediumint' => 'Edm.Int32',
|
58
|
+
'int4' => 'Edm.Int32',
|
59
|
+
'bigint' => 'Edm.Int64',
|
60
|
+
'bigserial' => 'Edm.Int64',
|
61
|
+
'int8' => 'Edm.Int64',
|
62
|
+
'tinyint' => 'Edm.Byte' }.freeze
|
41
63
|
def self.add_edm_types(metadata, props)
|
42
64
|
# try num/dec with db_type:
|
43
65
|
metadata[:edm_type] = if (md = DB_TYPE_NUMDEC_RGX.match(props[:db_type]))
|
@@ -80,51 +102,24 @@ module Safrano
|
|
80
102
|
|
81
103
|
# try int-like with db_type:
|
82
104
|
# smallint|int|integer|bigint|serial|bigserial
|
83
|
-
metadata[:edm_type] = if (md = DB_TYPE_INTLIKE_RGX.match(props[:db_type]))
|
84
105
|
|
106
|
+
metadata[:edm_type] = if (md = DB_TYPE_INTLIKE_RGX.match(props[:db_type]))
|
85
107
|
if (itype = md[1])
|
86
|
-
|
87
|
-
when 'smallint', 'int2', 'smallserial'
|
88
|
-
'Edm.Int16'
|
89
|
-
when 'int', 'integer', 'serial', 'mediumint', 'int4'
|
90
|
-
'Edm.Int32'
|
91
|
-
when 'bigint', 'bigserial', 'int8'
|
92
|
-
'Edm.Int64'
|
93
|
-
when 'tinyint'
|
94
|
-
'Edm.Byte'
|
95
|
-
end
|
108
|
+
DB_TY_EDM_TY_MAP[itype.downcase]
|
96
109
|
end
|
97
110
|
end
|
98
111
|
return if metadata[:edm_type]
|
99
112
|
|
100
113
|
# try Guid with db_type:
|
101
114
|
|
102
|
-
metadata[:edm_type] = if
|
115
|
+
metadata[:edm_type] = if DB_TYPE_GUID_RGX.match(props[:db_type])
|
103
116
|
'Edm.Guid'
|
104
117
|
end
|
118
|
+
|
105
119
|
return if metadata[:edm_type]
|
106
120
|
|
107
121
|
# try with Sequel(ruby) type
|
108
|
-
metadata[:edm_type] =
|
109
|
-
when :integer
|
110
|
-
'Edm.Int32'
|
111
|
-
when :string
|
112
|
-
'Edm.String'
|
113
|
-
when :date
|
114
|
-
'Edm.DateTime'
|
115
|
-
when :datetime
|
116
|
-
'Edm.DateTime'
|
117
|
-
when :time
|
118
|
-
'Edm.Time'
|
119
|
-
when :boolean
|
120
|
-
'Edm.Boolean'
|
121
|
-
when :float
|
122
|
-
'Edm.Double'
|
123
|
-
when :decimal
|
124
|
-
'Edm.Decimal'
|
125
|
-
when :blob
|
126
|
-
'Edm.Binary'
|
127
|
-
end
|
122
|
+
metadata[:edm_type] = RUBY_TY_EDM_TY_MAP[props[:type]]
|
128
123
|
end
|
129
124
|
|
130
125
|
# use Edm twice so that we can do include Safrano::Edm and then
|
@@ -153,8 +148,8 @@ module Safrano
|
|
153
148
|
nil
|
154
149
|
end
|
155
150
|
|
156
|
-
def self.convert_from_urlparam(
|
157
|
-
return Contract::NOK unless
|
151
|
+
def self.convert_from_urlparam(val)
|
152
|
+
return Contract::NOK unless val == 'null'
|
158
153
|
|
159
154
|
Contract.valid(nil)
|
160
155
|
end
|
@@ -164,9 +159,9 @@ module Safrano
|
|
164
159
|
class Binary < String
|
165
160
|
extend OutputClassMethods
|
166
161
|
|
167
|
-
def self.convert_from_urlparam(
|
168
|
-
# TODO this should use base64
|
169
|
-
Contract.valid(
|
162
|
+
def self.convert_from_urlparam(val)
|
163
|
+
# TODO: this should use base64
|
164
|
+
Contract.valid(val.dup.force_encoding('BINARY'))
|
170
165
|
end
|
171
166
|
end
|
172
167
|
|
@@ -180,13 +175,13 @@ module Safrano
|
|
180
175
|
end
|
181
176
|
|
182
177
|
def self.odata_collection(array)
|
183
|
-
array.map { |
|
178
|
+
array.map { |val| odata_value(val) }
|
184
179
|
end
|
185
180
|
|
186
|
-
def self.convert_from_urlparam(
|
187
|
-
return Contract::NOK unless %w[true false].include?(
|
181
|
+
def self.convert_from_urlparam(val)
|
182
|
+
return Contract::NOK unless %w[true false].include?(val)
|
188
183
|
|
189
|
-
Contract.valid(
|
184
|
+
Contract.valid(val == 'true')
|
190
185
|
end
|
191
186
|
end
|
192
187
|
|
@@ -195,8 +190,8 @@ module Safrano
|
|
195
190
|
class Byte < Integer
|
196
191
|
extend OutputClassMethods
|
197
192
|
|
198
|
-
def self.convert_from_urlparam(
|
199
|
-
return Contract::NOK unless (bytev =
|
193
|
+
def self.convert_from_urlparam(val)
|
194
|
+
return Contract::NOK unless (bytev = val.to_i) < 256
|
200
195
|
|
201
196
|
Contract.valid(bytev)
|
202
197
|
end
|
@@ -209,29 +204,29 @@ module Safrano
|
|
209
204
|
end
|
210
205
|
|
211
206
|
def self.odata_collection(array)
|
212
|
-
array.map { |
|
207
|
+
array.map { |val| odata_value(val) }
|
213
208
|
end
|
214
209
|
|
215
|
-
def self.convert_from_urlparam(
|
216
|
-
Contract.valid(DateTime.parse(
|
210
|
+
def self.convert_from_urlparam(val)
|
211
|
+
Contract.valid(DateTime.parse(val))
|
217
212
|
rescue StandardError
|
218
|
-
convertion_error(
|
213
|
+
convertion_error(val)
|
219
214
|
end
|
220
215
|
end
|
221
216
|
|
222
217
|
class String < ::String
|
223
218
|
extend OutputClassMethods
|
224
219
|
|
225
|
-
def self.convert_from_urlparam(
|
226
|
-
Contract.valid(
|
220
|
+
def self.convert_from_urlparam(val)
|
221
|
+
Contract.valid(val)
|
227
222
|
end
|
228
223
|
end
|
229
224
|
|
230
225
|
class Int32 < Integer
|
231
226
|
extend OutputClassMethods
|
232
227
|
|
233
|
-
def self.convert_from_urlparam(
|
234
|
-
return Contract::NOK unless (ret = number_or_nil(
|
228
|
+
def self.convert_from_urlparam(val)
|
229
|
+
return Contract::NOK unless (ret = number_or_nil(val))
|
235
230
|
|
236
231
|
Contract.valid(ret)
|
237
232
|
end
|
@@ -240,8 +235,8 @@ module Safrano
|
|
240
235
|
class Int64 < Integer
|
241
236
|
extend OutputClassMethods
|
242
237
|
|
243
|
-
def self.convert_from_urlparam(
|
244
|
-
return Contract::NOK unless (ret = number_or_nil(
|
238
|
+
def self.convert_from_urlparam(val)
|
239
|
+
return Contract::NOK unless (ret = number_or_nil(val))
|
245
240
|
|
246
241
|
Contract.valid(ret)
|
247
242
|
end
|
@@ -250,8 +245,8 @@ module Safrano
|
|
250
245
|
class Double < Float
|
251
246
|
extend OutputClassMethods
|
252
247
|
|
253
|
-
def self.convert_from_urlparam(
|
254
|
-
Contract.valid(
|
248
|
+
def self.convert_from_urlparam(val)
|
249
|
+
Contract.valid(val.to_f)
|
255
250
|
rescue StandardError
|
256
251
|
Contract::NOK
|
257
252
|
end
|
@@ -260,10 +255,10 @@ module Safrano
|
|
260
255
|
class Guid < UUIDTools::UUID
|
261
256
|
extend OutputClassMethods
|
262
257
|
|
263
|
-
def self.convert_from_urlparam(
|
264
|
-
Contract::NOK unless m = Filter::Parser::Token::GUIDRGX.match(
|
258
|
+
def self.convert_from_urlparam(val)
|
259
|
+
Contract::NOK unless (m = Filter::Parser::Token::GUIDRGX.match(val))
|
265
260
|
|
266
|
-
Contract.valid(UUIDTools::UUID.parse
|
261
|
+
Contract.valid(UUIDTools::UUID.parse(m[1]))
|
267
262
|
rescue StandardError
|
268
263
|
Contract::NOK
|
269
264
|
end
|
@@ -271,9 +266,3 @@ module Safrano
|
|
271
266
|
end
|
272
267
|
end
|
273
268
|
end
|
274
|
-
|
275
|
-
# include Safrano
|
276
|
-
|
277
|
-
# x = Edm::String.new('xxx')
|
278
|
-
|
279
|
-
# pp x
|
data/lib/odata/entity.rb
CHANGED
data/lib/odata/error.rb
CHANGED
@@ -50,9 +50,9 @@ module Safrano
|
|
50
50
|
|
51
51
|
# used in function import error handling. cf. func import / do_execute_func
|
52
52
|
def self.with_error(result)
|
53
|
-
|
54
|
-
|
55
|
-
|
53
|
+
return unless result.respond_to?(:error) && (err = result.error)
|
54
|
+
|
55
|
+
yield err
|
56
56
|
end
|
57
57
|
|
58
58
|
# base module for HTTP errors, when used as a Error Class
|
data/lib/odata/expand.rb
CHANGED
@@ -196,7 +196,7 @@ module Safrano
|
|
196
196
|
unless (@error = check_url_func_params)
|
197
197
|
begin
|
198
198
|
return yield
|
199
|
-
rescue LocalJumpError
|
199
|
+
rescue LocalJumpError
|
200
200
|
@error = Safrano::ServiceOperationReturnError.new
|
201
201
|
end
|
202
202
|
end
|
@@ -212,13 +212,15 @@ module Safrano
|
|
212
212
|
|
213
213
|
# Note: Sequel::Error exceptions are already
|
214
214
|
# handled on rack app level (cf. the call methode )
|
215
|
-
Safrano
|
215
|
+
Safrano.with_error(result) do |error|
|
216
216
|
@error = error
|
217
217
|
return [nil, :error, @error] # this is return from do_execute_func !
|
218
218
|
end
|
219
219
|
|
220
220
|
# non error case
|
221
|
-
[@returning.do_execute_func_result(result, req,
|
221
|
+
[@returning.do_execute_func_result(result, req,
|
222
|
+
apply_query_params: @auto_query_params),
|
223
|
+
:run]
|
222
224
|
end
|
223
225
|
end
|
224
226
|
|
data/lib/odata/model_ext.rb
CHANGED
@@ -142,11 +142,11 @@ module Safrano
|
|
142
142
|
@attribute_path_list = attribute_path_list
|
143
143
|
end
|
144
144
|
|
145
|
-
MAX_DEPTH =
|
145
|
+
MAX_DEPTH = 4
|
146
146
|
def attribute_path_list(depth = 0)
|
147
147
|
ret = @columns_str.dup
|
148
148
|
# break circles
|
149
|
-
return ret if depth
|
149
|
+
return ret if depth >= MAX_DEPTH
|
150
150
|
|
151
151
|
depth += 1
|
152
152
|
|
@@ -166,7 +166,7 @@ module Safrano
|
|
166
166
|
ret.concat(@nav_collection_attribs_keys) if @nav_collection_attribs
|
167
167
|
|
168
168
|
# break circles
|
169
|
-
return ret if depth
|
169
|
+
return ret if depth >= MAX_DEPTH
|
170
170
|
|
171
171
|
depth += 1
|
172
172
|
|
@@ -387,7 +387,7 @@ module Safrano
|
|
387
387
|
end
|
388
388
|
|
389
389
|
# attribute specific type mapping
|
390
|
-
if colmap = @type_mappings[col]
|
390
|
+
if (colmap = @type_mappings[col])
|
391
391
|
metadata[:edm_type] = colmap.edm_type
|
392
392
|
if colmap.castfunc
|
393
393
|
@casted_cols[col] = colmap.castfunc
|
@@ -430,7 +430,7 @@ module Safrano
|
|
430
430
|
if metadata[:edm_type] == 'Edm.Guid'
|
431
431
|
|
432
432
|
if props[:type] == :blob # Edm.Guid but as 16 byte binary Blob on DB level, eg in Sqlite
|
433
|
-
@casted_cols[col] =
|
433
|
+
@casted_cols[col] = lambda { |x|
|
434
434
|
UUIDTools::UUID.parse_raw(x).to_s unless x.nil?
|
435
435
|
} # Base64
|
436
436
|
next
|
@@ -445,9 +445,9 @@ module Safrano
|
|
445
445
|
end # db_schema.each do |col, props|
|
446
446
|
|
447
447
|
# check if key needs casting. Important for later entity-uri generation !
|
448
|
-
|
449
|
-
|
450
|
-
|
448
|
+
return unless primary_key.is_a? Symbol # single key field
|
449
|
+
|
450
|
+
@pk_castfunc = @casted_cols[primary_key]
|
451
451
|
end # build_casted_cols(service)
|
452
452
|
|
453
453
|
def finalize_publishing(service)
|
@@ -516,14 +516,13 @@ module Safrano
|
|
516
516
|
|
517
517
|
@iuk_rgx_parts.transform_values! { |v| /\A#{v}\z/ }
|
518
518
|
|
519
|
-
@entity_id_url_regexp = KEYPRED_URL_REGEXP
|
520
519
|
else
|
521
520
|
@pk_names = [primary_key.to_s]
|
522
521
|
@pk_cast_from_string = nil
|
523
522
|
|
524
523
|
kvpredicate = case db_schema[primary_key][:type]
|
525
524
|
when :integer
|
526
|
-
# TODO
|
525
|
+
# TODO: Harmonize this with primitive_types.rb convert_from_url
|
527
526
|
@pk_cast_from_string = ->(str) { Integer(str) }
|
528
527
|
/(\d+)/.freeze
|
529
528
|
else
|
@@ -531,9 +530,7 @@ module Safrano
|
|
531
530
|
case metadata[:edm_type]
|
532
531
|
when 'Edm.Guid'
|
533
532
|
if db_schema[primary_key][:type] == :blob # Edm.Guid but as 16byte binary Blob on DB
|
534
|
-
@pk_cast_from_string =
|
535
|
-
# TODO harmonize this with primitive_types.rb convert_from_url
|
536
|
-
# Sequel::SQL::Blob.new([ str.gsub('-', '') ].pack('H*')) }
|
533
|
+
@pk_cast_from_string = lambda { |str|
|
537
534
|
Sequel::SQL::Blob.new(UUIDTools::UUID.parse(str).raw)
|
538
535
|
}
|
539
536
|
end
|
@@ -543,9 +540,9 @@ module Safrano
|
|
543
540
|
end
|
544
541
|
end
|
545
542
|
@iuk_rgx = /\A\s*#{kvpredicate}\s*\z/
|
546
|
-
# @entity_id_url_regexp = /\A\(\s*#{kvpredicate}\s*\)(.*)/.freeze
|
547
|
-
@entity_id_url_regexp = KEYPRED_URL_REGEXP
|
548
543
|
end
|
544
|
+
# @entity_id_url_regexp = /\A\(\s*#{kvpredicate}\s*\)(.*)/.freeze
|
545
|
+
@entity_id_url_regexp = KEYPRED_URL_REGEXP
|
549
546
|
end
|
550
547
|
|
551
548
|
def prepare_fields
|
@@ -673,21 +670,19 @@ module Safrano
|
|
673
670
|
|
674
671
|
mid.split(/\s*,\s*/).each do |midpart|
|
675
672
|
mval = nil
|
676
|
-
mpk,
|
673
|
+
mpk, _mrgx = scan_rgx_parts.find do |_pk, rgx|
|
677
674
|
if (md = rgx.match(midpart))
|
678
675
|
mval = md[1]
|
679
676
|
end
|
680
677
|
end
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
return Contract::NOK
|
690
|
-
end
|
678
|
+
return Contract::NOK unless mpk && mval
|
679
|
+
|
680
|
+
mdch[mpk] = if (pk_cast = @pk_cast_from_string[mpk])
|
681
|
+
pk_cast.call(mval)
|
682
|
+
else
|
683
|
+
mval # no cast needed, eg for string
|
684
|
+
end
|
685
|
+
scan_rgx_parts.delete(mpk)
|
691
686
|
end
|
692
687
|
# normally arriving here we have mdch filled with key values pairs,
|
693
688
|
# but not in the model key ordering. lets just re-order the values
|
data/lib/odata/walker.rb
CHANGED
@@ -66,34 +66,27 @@ module Safrano
|
|
66
66
|
path
|
67
67
|
else
|
68
68
|
# path.sub!(/\A#{prefix}/, '')
|
69
|
-
# TODO check
|
69
|
+
# TODO: check
|
70
70
|
path.sub(/\A#{prefix}/, EMPTYSTR)
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
74
74
|
def get_next_transition
|
75
|
-
#
|
75
|
+
# handle multiple valid transitions
|
76
76
|
# like when we have attributes that are substring of each other
|
77
77
|
# --> instead of using detect (ie take first transition)
|
78
78
|
# we need to use select and then find the longest match
|
79
|
-
# tr_next = @context.allowed_transitions.detect do |t|
|
80
|
-
# t.do_match(@path_remain)
|
81
|
-
# end
|
82
79
|
|
83
|
-
valid_tr = @context.allowed_transitions.select do |t|
|
80
|
+
valid_tr = @context.allowed_transitions.map(&:dup).select do |t|
|
84
81
|
t.do_match(@path_remain)
|
85
82
|
end
|
86
83
|
|
87
|
-
#
|
88
|
-
# better one) to make attributes that are substrings of each other
|
84
|
+
# HACK: (wanted: a better one) to make attributes that are substrings of each other
|
89
85
|
# work well
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
valid_tr.max_by { |t| t.match_result[1].size }
|
95
|
-
end
|
96
|
-
end
|
86
|
+
return unless valid_tr
|
87
|
+
return (@tr_next = nil) if valid_tr.empty?
|
88
|
+
|
89
|
+
@tr_next = valid_tr.size == 1 ? valid_tr.first : valid_tr.max_by { |t| t.match_result[1].size }
|
97
90
|
end
|
98
91
|
|
99
92
|
# perform a content-id ($batch changeset ref) transition
|
data/lib/safrano/multipart.rb
CHANGED
@@ -45,9 +45,9 @@ module MIME
|
|
45
45
|
end
|
46
46
|
|
47
47
|
def parse_next_part(line)
|
48
|
-
if @target.parser.next_part(line)
|
48
|
+
return if @target.parser.next_part(line)
|
49
49
|
|
50
|
-
|
50
|
+
if @target.parser.last_part(line)
|
51
51
|
@state = :end
|
52
52
|
else
|
53
53
|
@target.parser.addline(line)
|
@@ -113,8 +113,8 @@ module MIME
|
|
113
113
|
MPS = 'multipart/'
|
114
114
|
MP_RGX1 = %r{^(digest|mixed);\s*boundary="(.*)"}.freeze
|
115
115
|
MP_RGX2 = %r{^(digest|mixed);\s*boundary=(.*)}.freeze
|
116
|
-
# APP_HTTP_RGX = %r{^application/http}.freeze
|
117
116
|
APP_HTTP = 'application/http'
|
117
|
+
|
118
118
|
def new_content
|
119
119
|
@target =
|
120
120
|
if @target_ct.start_with?(MPS) &&
|
@@ -138,18 +138,17 @@ module MIME
|
|
138
138
|
|
139
139
|
def parse_str(inpstr, level: 0)
|
140
140
|
# we need to keep the line separators --> use io.readlines
|
141
|
-
if inpstr.respond_to?(:readlines)
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
end
|
141
|
+
@lines = if inpstr.respond_to?(:readlines)
|
142
|
+
inpstr.readlines(@sep)
|
143
|
+
else
|
144
|
+
# rack input wrapper only has gets but not readlines
|
145
|
+
# BUT the rack SPEC says it only supports gets without argument!
|
146
|
+
# --> finally we end up using read and split into lines...
|
147
|
+
# normally should be ok for $batch POST payloads
|
148
|
+
|
149
|
+
# inpstr.read should be a String
|
150
|
+
inpstr.read.lines(@sep)
|
151
|
+
end
|
153
152
|
# tmp hack for test-tools that convert CRLF in payload to LF :-(
|
154
153
|
if @lines.size == 1
|
155
154
|
@sep = LF
|
@@ -319,7 +318,7 @@ module MIME
|
|
319
318
|
def addline(line)
|
320
319
|
@body_lines << line
|
321
320
|
end
|
322
|
-
end
|
321
|
+
end # Parser
|
323
322
|
|
324
323
|
attr_reader :boundary
|
325
324
|
|
@@ -369,12 +368,12 @@ module MIME
|
|
369
368
|
@hd[CTT_TYPE_LC] = "#{Safrano::MP_MIXED}; boundary=#{@boundary}"
|
370
369
|
end
|
371
370
|
|
372
|
-
def
|
373
|
-
get_response(
|
374
|
-
[@response.hd, @response.
|
371
|
+
def get_mult_resp(full_req)
|
372
|
+
get_response(full_req)
|
373
|
+
[202, @response.hd, @response.unparse_bodyonly]
|
375
374
|
end
|
376
375
|
|
377
|
-
def get_response(
|
376
|
+
def get_response(full_req)
|
378
377
|
@response = self.class.new(::SecureRandom.uuid)
|
379
378
|
@response.set_multipart_header
|
380
379
|
if @level == 1 # changeset need their own global transaction
|
@@ -382,9 +381,10 @@ module MIME
|
|
382
381
|
# and will be flagged with in_changeset=true
|
383
382
|
# and this will finally be used to skip the transaction
|
384
383
|
# of the changes
|
385
|
-
|
384
|
+
|
385
|
+
full_req.db.transaction do
|
386
386
|
begin
|
387
|
-
@response.content = @content.map { |part| part.get_response(
|
387
|
+
@response.content = @content.map { |part| part.get_response(full_req) }
|
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
|
@@ -394,7 +394,7 @@ module MIME
|
|
394
394
|
end
|
395
395
|
end
|
396
396
|
else
|
397
|
-
@response.content = @content.map { |
|
397
|
+
@response.content = @content.map { |part| part.get_response(full_req) }
|
398
398
|
end
|
399
399
|
@response
|
400
400
|
end
|
@@ -409,10 +409,20 @@ module MIME
|
|
409
409
|
@response
|
410
410
|
end
|
411
411
|
|
412
|
-
def unparse
|
412
|
+
def unparse
|
413
413
|
b = +String.new
|
414
|
-
b << "#{Safrano::CONTENT_TYPE}: #{@hd[CTT_TYPE_LC]}#{CRLF}"
|
414
|
+
b << "#{Safrano::CONTENT_TYPE}: #{@hd[CTT_TYPE_LC]}#{CRLF}"
|
415
|
+
|
416
|
+
# warning: duplicated code with below
|
417
|
+
b << crbdcr = "#{CRLF}--#{@boundary}#{CRLF}"
|
418
|
+
b << @content.map(&:unparse).join(crbdcr)
|
419
|
+
b << "#{CRLF}--#{@boundary}--#{CRLF}"
|
420
|
+
b
|
421
|
+
end
|
415
422
|
|
423
|
+
def unparse_bodyonly
|
424
|
+
b = +String.new
|
425
|
+
# warning: duplicated code with above
|
416
426
|
b << crbdcr = "#{CRLF}--#{@boundary}#{CRLF}"
|
417
427
|
b << @content.map(&:unparse).join(crbdcr)
|
418
428
|
b << "#{CRLF}--#{@boundary}--#{CRLF}"
|
@@ -450,6 +460,7 @@ module MIME
|
|
450
460
|
class HttpResp < Media
|
451
461
|
attr_accessor :status
|
452
462
|
attr_accessor :content
|
463
|
+
attr_accessor :rack_resp
|
453
464
|
|
454
465
|
APPLICATION_HTTP_11 = ['Content-Type: application/http',
|
455
466
|
"Content-Transfer-Encoding: binary#{CRLF}",
|
@@ -558,9 +569,9 @@ module MIME
|
|
558
569
|
@content = other.content
|
559
570
|
end
|
560
571
|
|
561
|
-
def get_response(
|
562
|
-
# self.content should be the request
|
563
|
-
rack_resp =
|
572
|
+
def get_response(full_req)
|
573
|
+
# self.content should be the part-request
|
574
|
+
rack_resp = full_req.batch_call(@content)
|
564
575
|
@response = MIME::Content::Application::HttpResp.new
|
565
576
|
@response.status = rack_resp[0]
|
566
577
|
@response.hd = rack_resp[1]
|