safrano 0.7.1 → 0.8.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/odata/entity.rb +3 -10
- data/lib/odata/error.rb +5 -1
- data/lib/safrano/rack_app.rb +7 -2
- data/lib/safrano/rack_builder.rb +63 -2
- data/lib/safrano/request.rb +11 -9
- data/lib/safrano/service.rb +5 -3
- data/lib/safrano/version.rb +1 -1
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3c19f9f9e0a4700de60c1a177c1555663f50ab02e2e5fb0449e21f3c43751dbc
|
4
|
+
data.tar.gz: 0a56ca92c60b1e1a943f7710f7993c325b8e1e9d20b9df745b87dea954170722
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9f273cc9008c3bdab427268c5bf139aeb30093c515611714110da1b3f48d90b86ab40c62e6c96aea6dacc8eb7381793d126850fc8bccab991d89fcf010075647
|
7
|
+
data.tar.gz: 3d1e65f46c4e3fe1765288fb1f06e3f488b708216ce708103945fbf2aa12dd088e7fe6da8e06ebc8c6fa18b6bbd65b67506a5c8a8dde2097f405b57ceaa9d2b4
|
data/lib/odata/entity.rb
CHANGED
@@ -184,16 +184,9 @@ module Safrano
|
|
184
184
|
if req.walker.media_value
|
185
185
|
odata_media_value_put(req)
|
186
186
|
elsif req.accept?(APPJSON)
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
set_fields(data, self.class.data_fields, missing: :skip)
|
191
|
-
save(transaction: false)
|
192
|
-
else
|
193
|
-
update_fields(data, self.class.data_fields, missing: :skip)
|
194
|
-
end
|
195
|
-
|
196
|
-
[202, EMPTY_HASH, to_odata_post_json(service: req.service)]
|
187
|
+
|
188
|
+
AlreadyExistsUnprocessableError.odata_get(req)
|
189
|
+
|
197
190
|
else # TODO: other formats
|
198
191
|
415
|
199
192
|
end
|
data/lib/odata/error.rb
CHANGED
@@ -142,7 +142,11 @@ module Safrano
|
|
142
142
|
@msg = reason
|
143
143
|
end
|
144
144
|
end
|
145
|
-
|
145
|
+
|
146
|
+
class AlreadyExistsUnprocessableError < UnprocessableEntityError
|
147
|
+
@msg = 'The ressource you are trying to create already exists'
|
148
|
+
end
|
149
|
+
|
146
150
|
# http Bad Req.
|
147
151
|
class BadRequestError
|
148
152
|
extend ErrorClass
|
data/lib/safrano/rack_app.rb
CHANGED
@@ -8,7 +8,7 @@ require_relative 'response'
|
|
8
8
|
module Safrano
|
9
9
|
# Note there is a strong 1 to 1 relation between an app instance
|
10
10
|
# and a published service. --> actually means also
|
11
|
-
# we only support
|
11
|
+
# we only support one service per App-class because publishing is
|
12
12
|
# made on app class level
|
13
13
|
class ServerApp
|
14
14
|
def initialize
|
@@ -36,7 +36,12 @@ module Safrano
|
|
36
36
|
def self.get_service_base
|
37
37
|
@service_base
|
38
38
|
end
|
39
|
-
|
39
|
+
|
40
|
+
# needed for safrano-rack_builder
|
41
|
+
def get_path_prefix
|
42
|
+
self.class.get_service_base.xpath_prefix
|
43
|
+
end
|
44
|
+
|
40
45
|
def self.set_servicebase(sbase)
|
41
46
|
@service_base = sbase
|
42
47
|
@service_base.enable_v1_service
|
data/lib/safrano/rack_builder.rb
CHANGED
@@ -7,12 +7,73 @@ module Rack
|
|
7
7
|
module Safrano
|
8
8
|
# just a Wrapper to ensure (force?) that mandatory middlewares are acutally
|
9
9
|
# used
|
10
|
+
LOCALHOST_ANY_PORT_RGX = /\A(?:https?:\/\/)?localhost(?::\d+)?\z/
|
10
11
|
class Builder < ::Rack::Builder
|
12
|
+
|
11
13
|
def initialize(default_app = nil, &block)
|
12
14
|
super(default_app) {}
|
13
|
-
|
15
|
+
@middlewares = []
|
16
|
+
|
14
17
|
instance_eval(&block) if block_given?
|
15
|
-
|
18
|
+
prepend_rackcors_ifneeded
|
19
|
+
end
|
20
|
+
|
21
|
+
def use(middleware, *args, &block)
|
22
|
+
@middlewares << middleware
|
23
|
+
super(middleware, *args, &block)
|
24
|
+
end
|
25
|
+
|
26
|
+
def prepend_rackcors_ifneeded
|
27
|
+
return if stack_has_rackcors
|
28
|
+
|
29
|
+
# get the safrano app path prefix
|
30
|
+
# normally @run is a Safrano Server app
|
31
|
+
return unless @run.is_a? ::Safrano::ServerApp
|
32
|
+
|
33
|
+
|
34
|
+
service_path_prefix = @run.get_path_prefix.dup
|
35
|
+
|
36
|
+
# due to a bug in rack-cors
|
37
|
+
# we cant use the batch ressource path as
|
38
|
+
# a string but need to pass it as a regexp
|
39
|
+
# ( bug fixed in rack-cors git / new release? but still need to workaround it for
|
40
|
+
# current/old releases ),
|
41
|
+
batch_path_regexp = if service_path_prefix.empty?
|
42
|
+
# Ressource /$batch
|
43
|
+
/\A\/\$batch\z/
|
44
|
+
else
|
45
|
+
# Ressource like /foo/bar/baz/$batch
|
46
|
+
service_path_prefix.sub!(::Safrano::TRAILING_SLASH_RGX, '')
|
47
|
+
service_path_prefix.sub!(::Safrano::LEADING_SLASH_RGX, '')
|
48
|
+
# now is foo/bar/baz
|
49
|
+
path_prefix_rgx = Regexp.escape("/#{service_path_prefix}/$batch")
|
50
|
+
# now escaped path regexp /foo/bar/baz/$batch
|
51
|
+
# finaly just add start / end anchors
|
52
|
+
/\A#{path_prefix_rgx}\z/
|
53
|
+
end
|
54
|
+
# this will append rack-cors mw
|
55
|
+
# per default allow GET * from everywhere
|
56
|
+
# allow POST $batch from localhost only
|
57
|
+
use ::Rack::Cors do
|
58
|
+
allow do
|
59
|
+
origins LOCALHOST_ANY_PORT_RGX
|
60
|
+
resource (batch_path_regexp), headers: :any, methods: [:post, :head, :options]
|
61
|
+
resource '*', headers: :any, methods: [:get, :post, :put, :patch, :head, :options]
|
62
|
+
end
|
63
|
+
allow do
|
64
|
+
origins '*'
|
65
|
+
resource '*', headers: :any, methods: [:get, :head, :options]
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
# we need it in first place... move last element to beginin of mw stack
|
71
|
+
rackcors = @use.delete_at(-1)
|
72
|
+
@use.insert(0, rackcors)
|
73
|
+
end
|
74
|
+
|
75
|
+
def stack_has_rackcors
|
76
|
+
@middlewares.find{|mw| mw == Rack::Cors }
|
16
77
|
end
|
17
78
|
end
|
18
79
|
end
|
data/lib/safrano/request.rb
CHANGED
@@ -7,14 +7,16 @@ module Safrano
|
|
7
7
|
# handle GET PUT etc
|
8
8
|
module MethodHandlers
|
9
9
|
def odata_options
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
10
|
+
# cf. stackoverflow.com/questions/22924678/sinatra-delete-response-headers
|
11
|
+
headers.delete('Content-Type')
|
12
|
+
@response.headers.delete('Content-Type')
|
13
|
+
@response.headers['Content-Type'] = ''
|
14
|
+
|
15
|
+
# we only let rack-cors handle Cors OPTIONS .
|
16
|
+
# otherwise dont do it...
|
17
|
+
# see https://www.mnot.net/blog/2012/10/29/NO_OPTIONS
|
18
|
+
# 501 not implemented
|
19
|
+
[501, EMPTY_HASH, '']
|
18
20
|
end
|
19
21
|
|
20
22
|
def odata_delete
|
@@ -39,7 +41,7 @@ module Safrano
|
|
39
41
|
|
40
42
|
def odata_post
|
41
43
|
@walker.finalize.tap_error { |err| return err.odata_get(self) }
|
42
|
-
|
44
|
+
.if_valid { |context| context.odata_post(self) }
|
43
45
|
end
|
44
46
|
|
45
47
|
def odata_head
|
data/lib/safrano/service.rb
CHANGED
@@ -107,6 +107,8 @@ module Safrano
|
|
107
107
|
MIN_DATASERVICE_VERSION = '1'
|
108
108
|
CV_MAX_DATASERVICE_VERSION = Contract.valid(MAX_DATASERVICE_VERSION).freeze
|
109
109
|
CV_MIN_DATASERVICE_VERSION = Contract.valid(MIN_DATASERVICE_VERSION).freeze
|
110
|
+
TRAILING_SLASH_RGX = %r{/\z}.freeze
|
111
|
+
LEADING_SLASH_RGX = %r{\A/}.freeze
|
110
112
|
include XMLNS
|
111
113
|
# Base class for service. Subclass will be for V1, V2 etc...
|
112
114
|
class ServiceBase
|
@@ -166,7 +168,6 @@ module Safrano
|
|
166
168
|
instance_eval(&block) if block_given?
|
167
169
|
end
|
168
170
|
|
169
|
-
TRAILING_SLASH = %r{/\z}.freeze
|
170
171
|
DEFAULT_PATH_PREFIX = '/'
|
171
172
|
DEFAULT_SERVER_URL = 'http://localhost:9494'
|
172
173
|
|
@@ -200,13 +201,14 @@ module Safrano
|
|
200
201
|
end
|
201
202
|
|
202
203
|
def path_prefix(path_pr)
|
203
|
-
@xpath_prefix = path_pr.sub(
|
204
|
+
@xpath_prefix = path_pr.sub(TRAILING_SLASH_RGX, '')
|
205
|
+
@xpath_prefix.freeze
|
204
206
|
(@v1.xpath_prefix = @xpath_prefix) if @v1
|
205
207
|
(@v2.xpath_prefix = @xpath_prefix) if @v2
|
206
208
|
end
|
207
209
|
|
208
210
|
def server_url(surl)
|
209
|
-
@xserver_url = surl.sub(
|
211
|
+
@xserver_url = surl.sub(TRAILING_SLASH_RGX, '')
|
210
212
|
(@v1.xserver_url = @xserver_url) if @v1
|
211
213
|
(@v2.xserver_url = @xserver_url) if @v2
|
212
214
|
end
|
data/lib/safrano/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: safrano
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- oz
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-10-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|
@@ -253,7 +253,7 @@ metadata:
|
|
253
253
|
changelog_uri: https://gitlab.com/dm0da/safrano/blob/master/CHANGELOG
|
254
254
|
source_code_uri: https://gitlab.com/dm0da/safrano/tree/master
|
255
255
|
documentation_uri: https://gitlab.com/dm0da/safrano/-/blob/master/README.md
|
256
|
-
post_install_message:
|
256
|
+
post_install_message:
|
257
257
|
rdoc_options: []
|
258
258
|
require_paths:
|
259
259
|
- lib
|
@@ -268,8 +268,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
268
268
|
- !ruby/object:Gem::Version
|
269
269
|
version: '0'
|
270
270
|
requirements: []
|
271
|
-
rubygems_version: 3.
|
272
|
-
signing_key:
|
271
|
+
rubygems_version: 3.3.15
|
272
|
+
signing_key:
|
273
273
|
specification_version: 4
|
274
274
|
summary: Safrano is an OData server library
|
275
275
|
test_files: []
|