riddl 0.125 → 0.127
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/ruby/riddl/protocols/generator.rb +118 -0
- data/lib/ruby/riddl/protocols/parser.rb +205 -0
- data/riddl.gemspec +3 -3
- metadata +10 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '0695959f6c714b4aca4c11debdcd59d22fefbbe6c11f69400c2b0ebd252d43fc'
|
4
|
+
data.tar.gz: cabfaef2d61eb9cd5010af81f891684dce71f761255e65531ef146362b6b884a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5d53d1d0a1aba73908811c361dfeed70e79dcec182b5c6c20863e9c1d9e7c5886c022d78dc4f97277c7519cf155a7abbb136a2b79852e64830151b73b53bf6ff
|
7
|
+
data.tar.gz: 442afaa166e57b02f1d29a262e693c3a5f7843e56fdbe98fe8c77f4087b94c31f58876a5a53eb83565a385e473b1b0263bc4e4a8f936896c1435fa6e0a788cee
|
@@ -0,0 +1,118 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../constants')
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/../utils')
|
3
|
+
require 'stringio'
|
4
|
+
|
5
|
+
module Riddl
|
6
|
+
module Protocols
|
7
|
+
module HTTP
|
8
|
+
class Generator
|
9
|
+
def initialize(params,headers)
|
10
|
+
@params = params
|
11
|
+
@headers = headers
|
12
|
+
end
|
13
|
+
|
14
|
+
def generate(mode=:output)
|
15
|
+
if @params.is_a?(Array) && @params.length == 1
|
16
|
+
body(@params[0],mode)
|
17
|
+
elsif @params.class == Riddl::Parameter::Simple || @params.class == Riddl::Parameter::Complex
|
18
|
+
body(@params,mode)
|
19
|
+
elsif @params.is_a?(Array) && @params.length > 1
|
20
|
+
multipart(mode)
|
21
|
+
else
|
22
|
+
if mode == :output
|
23
|
+
@headers['Content-Type'] = 'text/plain'
|
24
|
+
StringIO.new('','r+b')
|
25
|
+
else
|
26
|
+
StringIO.new('','r+b')
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def body(r,mode)
|
32
|
+
tmp = StringIO.new('','r+b')
|
33
|
+
case r
|
34
|
+
when Riddl::Parameter::Simple
|
35
|
+
if mode == :output
|
36
|
+
tmp.write r.value
|
37
|
+
@headers['Content-Type'] = 'text/plain'
|
38
|
+
@headers['Content-ID'] = r.name
|
39
|
+
@headers['RIDDL-TYPE'] = 'simple'
|
40
|
+
end
|
41
|
+
if mode == :input
|
42
|
+
@headers['Content-Type'] = 'application/x-www-form-urlencoded'
|
43
|
+
tmp.write Riddl::Protocols::Utils::escape(r.name) + '=' + Riddl::Protocols::Utils::escape(r.value)
|
44
|
+
end
|
45
|
+
when Riddl::Parameter::Complex
|
46
|
+
tmp.write(r.value.respond_to?(:read) ? r.value.read : r.value)
|
47
|
+
@headers['Content-Type'] = r.mimetype + r.mimextra
|
48
|
+
@headers['RIDDL-TYPE'] = 'complex'
|
49
|
+
if r.filename.nil?
|
50
|
+
@headers['Content-ID'] = r.name
|
51
|
+
else
|
52
|
+
@headers['Content-Disposition'] = "riddl-data; name=\"#{r.name}\"; filename=\"#{r.filename}\""
|
53
|
+
end
|
54
|
+
end
|
55
|
+
tmp.flush
|
56
|
+
tmp.rewind
|
57
|
+
tmp
|
58
|
+
end
|
59
|
+
private :body
|
60
|
+
|
61
|
+
def multipart(mode)
|
62
|
+
tmp = StringIO.new('','r+b')
|
63
|
+
scount = ccount = 0
|
64
|
+
@params.each do |r|
|
65
|
+
case r
|
66
|
+
when Riddl::Parameter::Simple
|
67
|
+
scount += 1
|
68
|
+
when Riddl::Parameter::Complex
|
69
|
+
ccount += 1
|
70
|
+
end
|
71
|
+
end
|
72
|
+
if scount > 0 && ccount == 0
|
73
|
+
@headers['Content-Type'] = 'application/x-www-form-urlencoded'
|
74
|
+
res = []
|
75
|
+
@params.each do |r|
|
76
|
+
case r
|
77
|
+
when Riddl::Parameter::Simple
|
78
|
+
res << Riddl::Protocols::Utils::escape(r.name) + '=' + Riddl::Protocols::Utils::escape(r.value)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
tmp.write res.join('&')
|
82
|
+
else
|
83
|
+
if scount + ccount > 0
|
84
|
+
@headers['Content-Type'] = "multipart/#{mode == :input ? 'form-data' : 'mixed'}; boundary=\"#{BOUNDARY}\""
|
85
|
+
@params.each do |r|
|
86
|
+
case r
|
87
|
+
when Riddl::Parameter::Simple
|
88
|
+
tmp.write '--' + BOUNDARY + EOL
|
89
|
+
tmp.write 'RIDDL-TYPE: simple' + EOL
|
90
|
+
tmp.write "Content-Disposition: #{mode == :input ? 'form-data' : 'riddl-data'}; name=\"#{r.name}\"" + EOL
|
91
|
+
tmp.write EOL
|
92
|
+
tmp.write r.value
|
93
|
+
tmp.write EOL
|
94
|
+
when Riddl::Parameter::Complex
|
95
|
+
tmp.write '--' + BOUNDARY + EOL
|
96
|
+
tmp.write 'RIDDL-TYPE: complex' + EOL
|
97
|
+
tmp.write "Content-Disposition: #{mode == :input ? 'form-data' : 'riddl-data'}; name=\"#{r.name}\""
|
98
|
+
tmp.write r.filename.nil? ? '; filename=""' + EOL : "; filename=\"#{r.filename}\"" + EOL
|
99
|
+
tmp.write 'Content-Transfer-Encoding: binary' + EOL
|
100
|
+
tmp.write 'Content-Type: ' + r.mimetype + r.mimextra + EOL
|
101
|
+
tmp.write EOL
|
102
|
+
tmp.write(r.value.respond_to?(:read) ? r.value.read : r.value)
|
103
|
+
tmp.write EOL
|
104
|
+
end
|
105
|
+
end
|
106
|
+
tmp.write '--' + BOUNDARY + EOL
|
107
|
+
end
|
108
|
+
end
|
109
|
+
tmp.flush
|
110
|
+
tmp.rewind
|
111
|
+
tmp
|
112
|
+
end
|
113
|
+
private :multipart
|
114
|
+
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,205 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../constants')
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../parameter')
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + '/../utils')
|
4
|
+
|
5
|
+
module Riddl
|
6
|
+
module Protocols
|
7
|
+
module HTTP
|
8
|
+
class Parser
|
9
|
+
MULTIPART_CONTENT_TYPES = [
|
10
|
+
#{{{
|
11
|
+
'multipart/form-data',
|
12
|
+
'multipart/related',
|
13
|
+
'multipart/mixed'
|
14
|
+
#}}}
|
15
|
+
].freeze
|
16
|
+
FORM_CONTENT_TYPES = [
|
17
|
+
#{{{
|
18
|
+
'application/x-www-form-urlencoded'
|
19
|
+
#}}}
|
20
|
+
].freeze
|
21
|
+
|
22
|
+
def parse_content(input,ctype,content_length,content_disposition,content_id,riddl_type)
|
23
|
+
#{{{
|
24
|
+
# fixing for chunked?
|
25
|
+
|
26
|
+
ctype = nil if riddl_type == 'simple'
|
27
|
+
filename = content_disposition[/ filename="?([^\";]*)"?/ni, 1]
|
28
|
+
name = content_disposition[/ name="?([^\";]*)"?/ni, 1] || content_id
|
29
|
+
|
30
|
+
if ctype || filename
|
31
|
+
body = Parameter::Tempfile.new("RiddlMultipart")
|
32
|
+
body.binmode if body.respond_to?(:binmode)
|
33
|
+
else
|
34
|
+
body = ''
|
35
|
+
end
|
36
|
+
|
37
|
+
if content_length == 0
|
38
|
+
bufsize = 16384
|
39
|
+
until input.eof?
|
40
|
+
c = input.read(bufsize)
|
41
|
+
raise EOFError, "bad content body" if c.nil? || c.empty?
|
42
|
+
body << c
|
43
|
+
content_length -= c.size
|
44
|
+
end
|
45
|
+
body << input.read
|
46
|
+
else
|
47
|
+
bufsize = 16384
|
48
|
+
until content_length <= 0
|
49
|
+
c = input.read(bufsize < content_length ? bufsize : content_length)
|
50
|
+
raise EOFError, "bad content body" if c.nil? || c.empty?
|
51
|
+
body << c
|
52
|
+
content_length -= c.size
|
53
|
+
end
|
54
|
+
end
|
55
|
+
body.rewind if body.respond_to?(:binmode)
|
56
|
+
|
57
|
+
add_to_params(name,body,filename,ctype,nil) if body.length > 0
|
58
|
+
#}}}
|
59
|
+
end
|
60
|
+
private :parse_content
|
61
|
+
|
62
|
+
def parse_multipart(input,content_type,content_length)
|
63
|
+
#{{{
|
64
|
+
content_type =~ %r|\Amultipart/.*boundary=\"?([^\";,]+)\"?|n
|
65
|
+
boundary = "--#{$1}"
|
66
|
+
|
67
|
+
boundary_size = boundary.size + EOL.size
|
68
|
+
content_length -= boundary_size
|
69
|
+
status = input.read(boundary_size)
|
70
|
+
raise EOFError, "bad content body" unless status == boundary + EOL
|
71
|
+
|
72
|
+
rx = /(?:#{EOL})?#{Regexp.quote boundary}(#{EOL}|--)/n
|
73
|
+
|
74
|
+
buf = ""
|
75
|
+
bufsize = 16384
|
76
|
+
loop do
|
77
|
+
head = nil
|
78
|
+
body = ''
|
79
|
+
filename = ctype = name = nil
|
80
|
+
|
81
|
+
until head && buf =~ rx
|
82
|
+
if !head && i = buf.index(EOL+EOL)
|
83
|
+
head = buf.slice!(0, i+2) # First \r\n
|
84
|
+
buf.slice!(0, 2) # Second \r\n
|
85
|
+
|
86
|
+
filename = head[/Content-Disposition:.* filename="?([^\";]*)"?/ni, 1]
|
87
|
+
ctype = head[/Content-Type: (.*)#{EOL}/ni, 1]
|
88
|
+
name = head[/Content-Disposition:.*\s+name="?([^\";]*)"?/ni, 1] || head[/Content-ID:\s*([^#{EOL}]*)/ni, 1]
|
89
|
+
|
90
|
+
if ctype || filename
|
91
|
+
body = Parameter::Tempfile.new("RiddlMultipart")
|
92
|
+
body.binmode if body.respond_to?(:binmode)
|
93
|
+
end
|
94
|
+
|
95
|
+
next
|
96
|
+
end
|
97
|
+
|
98
|
+
# Save the read body part.
|
99
|
+
if head && (boundary_size+4 < buf.size)
|
100
|
+
body << buf.slice!(0, buf.size - (boundary_size+4))
|
101
|
+
end
|
102
|
+
|
103
|
+
c = input.read(bufsize < content_length ? bufsize : content_length)
|
104
|
+
raise EOFError, "bad content body" if c.nil? || c.empty?
|
105
|
+
content_length -= c.size
|
106
|
+
|
107
|
+
buf << c
|
108
|
+
end
|
109
|
+
|
110
|
+
# Save the rest.
|
111
|
+
if i = buf.index(rx)
|
112
|
+
body << buf.slice!(0, i)
|
113
|
+
buf.slice!(0, boundary_size+2)
|
114
|
+
content_length = -1 if $1 == "--"
|
115
|
+
end
|
116
|
+
|
117
|
+
p name
|
118
|
+
p body
|
119
|
+
p filename
|
120
|
+
p ctype
|
121
|
+
p head
|
122
|
+
p '----'
|
123
|
+
|
124
|
+
add_to_params(name,body,filename == '' ? nil : filename,ctype,head)
|
125
|
+
|
126
|
+
break if buf.empty? || content_length == -1
|
127
|
+
end
|
128
|
+
#}}}
|
129
|
+
end
|
130
|
+
private :parse_multipart
|
131
|
+
|
132
|
+
def add_to_params(name,body,filename,ctype,head)
|
133
|
+
#{{{
|
134
|
+
if filename == ""
|
135
|
+
# filename is blank which means no file has been selected
|
136
|
+
elsif filename && ctype
|
137
|
+
body.rewind
|
138
|
+
|
139
|
+
# Take the basename of the upload's original filename.
|
140
|
+
# This handles the full Windows paths given by Internet Explorer
|
141
|
+
# (and perhaps other broken user agents) without affecting
|
142
|
+
# those which give the lone filename.
|
143
|
+
filename =~ /^(?:.*[:\\\/])?(.*)/m
|
144
|
+
filename = $1
|
145
|
+
|
146
|
+
@params << Parameter::Complex.new(name, ctype, body, filename, head)
|
147
|
+
elsif !filename && ctype
|
148
|
+
body.rewind
|
149
|
+
|
150
|
+
# Generic multipart cases, not coming from a form
|
151
|
+
@params << Parameter::Complex.new(name, ctype, body, nil, head)
|
152
|
+
else
|
153
|
+
@params << Parameter::Simple.new(name, body, :body)
|
154
|
+
end
|
155
|
+
#}}}
|
156
|
+
end
|
157
|
+
private :add_to_params
|
158
|
+
|
159
|
+
def parse_nested_query(qs, type)
|
160
|
+
#{{{
|
161
|
+
(qs || '').split(/[#{D}] */n).each do |p|
|
162
|
+
k, v = Riddl::Protocols::Utils::unescape(p).split('=', 2)
|
163
|
+
@params << Parameter::Simple.new(k,v,type)
|
164
|
+
end
|
165
|
+
#}}}
|
166
|
+
end
|
167
|
+
private :parse_nested_query
|
168
|
+
|
169
|
+
def initialize(query_string,input,content_type,content_length,content_disposition,content_id,riddl_type)
|
170
|
+
#{{{
|
171
|
+
# rewind because in some cases it is not at start (when multipart without length)
|
172
|
+
|
173
|
+
begin
|
174
|
+
input.rewind if input.respond_to?(:rewind)
|
175
|
+
rescue Errno::ESPIPE
|
176
|
+
# Handles exceptions raised by input streams that cannot be rewound
|
177
|
+
# such as when using plain CGI under Apache
|
178
|
+
end
|
179
|
+
|
180
|
+
media_type = content_type && content_type.split(/\s*[;,]\s*/, 2).first.downcase
|
181
|
+
@params = Riddl::Parameter::Array.new
|
182
|
+
parse_nested_query(query_string,:query)
|
183
|
+
if MULTIPART_CONTENT_TYPES.include?(media_type)
|
184
|
+
parse_multipart(input,content_type,content_length.to_i)
|
185
|
+
elsif FORM_CONTENT_TYPES.include?(media_type)
|
186
|
+
# sub is a fix for Safari Ajax postings that always append \0
|
187
|
+
parse_nested_query(input.read.sub(/\0\z/, ''),:body)
|
188
|
+
else
|
189
|
+
parse_content(input,content_type,content_length.to_i,content_disposition||'',content_id||'',riddl_type||'')
|
190
|
+
end
|
191
|
+
|
192
|
+
begin
|
193
|
+
input.rewind if input.respond_to?(:rewind)
|
194
|
+
rescue Errno::ESPIPE
|
195
|
+
# Handles exceptions raised by input streams that cannot be rewound
|
196
|
+
# such as when using plain CGI under Apache
|
197
|
+
end
|
198
|
+
#}}}
|
199
|
+
end
|
200
|
+
|
201
|
+
attr_reader :params
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
data/riddl.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = "riddl"
|
3
|
-
s.version = "0.
|
3
|
+
s.version = "0.127"
|
4
4
|
s.platform = Gem::Platform::RUBY
|
5
5
|
s.license = "LGPL-3.0"
|
6
6
|
s.summary = "restful interface description and declaration language: tools and client/server libs"
|
@@ -22,7 +22,7 @@ Gem::Specification.new do |s|
|
|
22
22
|
|
23
23
|
s.required_ruby_version = '>=2.2.0'
|
24
24
|
|
25
|
-
s.add_runtime_dependency 'daemonite', '~>0.
|
25
|
+
s.add_runtime_dependency 'daemonite', '~>0.7', '>=0.7.0'
|
26
26
|
s.add_runtime_dependency 'typhoeus', '~>1.3'
|
27
27
|
s.add_runtime_dependency 'xml-smart', '>=0.4.3', '~>0'
|
28
28
|
s.add_runtime_dependency 'rdf-smart', '>=0.0.160', '~>0'
|
@@ -34,5 +34,5 @@ Gem::Specification.new do |s|
|
|
34
34
|
s.add_runtime_dependency 'mime-types', '>= 3.0', '~>3'
|
35
35
|
s.add_runtime_dependency 'minitest', '>= 5.0.0', '~>5'
|
36
36
|
s.add_runtime_dependency 'charlock_holmes', '>= 0.7', '~>0'
|
37
|
-
s.add_runtime_dependency 'redis', '~>
|
37
|
+
s.add_runtime_dependency 'redis', '~> 5.0'
|
38
38
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: riddl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.127'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Juergen 'eTM' Mangler
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: tools
|
12
12
|
cert_chain: []
|
13
|
-
date: 2023-02
|
13
|
+
date: 2023-03-02 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: daemonite
|
@@ -18,20 +18,20 @@ dependencies:
|
|
18
18
|
requirements:
|
19
19
|
- - "~>"
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: '0.
|
21
|
+
version: '0.7'
|
22
22
|
- - ">="
|
23
23
|
- !ruby/object:Gem::Version
|
24
|
-
version: 0.
|
24
|
+
version: 0.7.0
|
25
25
|
type: :runtime
|
26
26
|
prerelease: false
|
27
27
|
version_requirements: !ruby/object:Gem::Requirement
|
28
28
|
requirements:
|
29
29
|
- - "~>"
|
30
30
|
- !ruby/object:Gem::Version
|
31
|
-
version: '0.
|
31
|
+
version: '0.7'
|
32
32
|
- - ">="
|
33
33
|
- !ruby/object:Gem::Version
|
34
|
-
version: 0.
|
34
|
+
version: 0.7.0
|
35
35
|
- !ruby/object:Gem::Dependency
|
36
36
|
name: typhoeus
|
37
37
|
requirement: !ruby/object:Gem::Requirement
|
@@ -240,14 +240,14 @@ dependencies:
|
|
240
240
|
requirements:
|
241
241
|
- - "~>"
|
242
242
|
- !ruby/object:Gem::Version
|
243
|
-
version: '
|
243
|
+
version: '5.0'
|
244
244
|
type: :runtime
|
245
245
|
prerelease: false
|
246
246
|
version_requirements: !ruby/object:Gem::Requirement
|
247
247
|
requirements:
|
248
248
|
- - "~>"
|
249
249
|
- !ruby/object:Gem::Version
|
250
|
-
version: '
|
250
|
+
version: '5.0'
|
251
251
|
description: rest service interface definition, mixing, and evolution. supports mixed
|
252
252
|
http and xmpp servers.
|
253
253
|
email: juergen.mangler@gmail.com
|
@@ -459,8 +459,10 @@ files:
|
|
459
459
|
- lib/ruby/riddl/ns/description/1.0/description.rng
|
460
460
|
- lib/ruby/riddl/option.rb
|
461
461
|
- lib/ruby/riddl/parameter.rb
|
462
|
+
- lib/ruby/riddl/protocols/generator.rb
|
462
463
|
- lib/ruby/riddl/protocols/http/generator.rb
|
463
464
|
- lib/ruby/riddl/protocols/http/parser.rb
|
465
|
+
- lib/ruby/riddl/protocols/parser.rb
|
464
466
|
- lib/ruby/riddl/protocols/sse.rb
|
465
467
|
- lib/ruby/riddl/protocols/utils.rb
|
466
468
|
- lib/ruby/riddl/protocols/websocket.rb
|