tina4ruby 3.13.30 → 3.13.31
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/tina4/graphql.rb +3 -1
- data/lib/tina4/request.rb +49 -13
- data/lib/tina4/response.rb +32 -5
- data/lib/tina4/version.rb +1 -1
- data/lib/tina4/wsdl.rb +11 -6
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6140bb67a60387c462e70052c88bbde69ba3b669c0371380df401bd8f9a0b039
|
|
4
|
+
data.tar.gz: 7e0043ae026ed273a444f6185f289d0099458fc9ce605bfe4380c1fda9b6f672
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 83b74a98d73ebcfdd0f22a9335b09382d5e518d51f3443b5e29dafdddb892374e41c8b9cbbc0b4a3d354e3bd405996a376c2e93df1f996778a73d349561a2879
|
|
7
|
+
data.tar.gz: 4eadb6a043ec78b5058465b73e4f10f2bf8d91ed19f5e22e5a5a00e2f4b57de8f59fe321b89b5e1e6417dc2dd15ff9142bb36635eed1275f85b59148149498fd
|
data/lib/tina4/graphql.rb
CHANGED
|
@@ -1026,7 +1026,9 @@ module Tina4
|
|
|
1026
1026
|
|
|
1027
1027
|
graphql = self
|
|
1028
1028
|
Tina4.post path, auth: false do |request, response|
|
|
1029
|
-
|
|
1029
|
+
# handle_request expects the raw JSON text (it JSON.parses internally),
|
|
1030
|
+
# so read body_raw — request.body now returns the PARSED payload.
|
|
1031
|
+
body = request.body_raw
|
|
1030
1032
|
result = graphql.handle_request(body, context: { request: request })
|
|
1031
1033
|
response.json(result)
|
|
1032
1034
|
end
|
data/lib/tina4/request.rb
CHANGED
|
@@ -35,6 +35,26 @@ module Tina4
|
|
|
35
35
|
end
|
|
36
36
|
end
|
|
37
37
|
|
|
38
|
+
# Per-file upload hash: indifferent access plus a lazily-materialised
|
|
39
|
+
# `content` field. The raw bytes are read from the tempfile only on first
|
|
40
|
+
# access to `content` (then rewound, so :tempfile streaming still works),
|
|
41
|
+
# so :tempfile-only handlers never buffer large uploads in memory.
|
|
42
|
+
class FileUpload < IndifferentHash
|
|
43
|
+
def [](key)
|
|
44
|
+
if key.to_s == "content" && !key?("content") && (tf = super("tempfile"))
|
|
45
|
+
self["content"] = begin
|
|
46
|
+
tf.rewind if tf.respond_to?(:rewind)
|
|
47
|
+
data = tf.read
|
|
48
|
+
tf.rewind if tf.respond_to?(:rewind)
|
|
49
|
+
data
|
|
50
|
+
rescue StandardError
|
|
51
|
+
nil
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
super(key)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
38
58
|
# Hash subclass for HTTP headers — string keys are case-insensitive.
|
|
39
59
|
#
|
|
40
60
|
# HTTP header field-names are case-insensitive per RFC 7230 §3.2. With
|
|
@@ -161,16 +181,25 @@ module Tina4
|
|
|
161
181
|
@session ||= Tina4::Session.new(@env)
|
|
162
182
|
end
|
|
163
183
|
|
|
164
|
-
#
|
|
184
|
+
# Parsed body (JSON -> Hash, form-urlencoded -> Hash, multipart ->
|
|
185
|
+
# fields Hash, else the current fallback). This matches Python's
|
|
186
|
+
# `request.body`, PHP's, and Node's: `body` is the PARSED payload, not
|
|
187
|
+
# the raw bytes. For the raw string use `body_raw`.
|
|
165
188
|
def body
|
|
166
|
-
@
|
|
189
|
+
@body_parsed ||= parse_body
|
|
167
190
|
end
|
|
168
191
|
|
|
169
|
-
#
|
|
170
|
-
|
|
171
|
-
|
|
192
|
+
# Raw body string — the bytes exactly as the client sent them.
|
|
193
|
+
# (This is what `body` used to return before the cross-framework
|
|
194
|
+
# parity flip; SOAP/GraphQL and any consumer that needs the raw text
|
|
195
|
+
# reads this.)
|
|
196
|
+
def body_raw
|
|
197
|
+
@body_raw ||= read_body
|
|
172
198
|
end
|
|
173
199
|
|
|
200
|
+
# Backwards-compatible alias of `body` — both return the parsed payload.
|
|
201
|
+
alias body_parsed body
|
|
202
|
+
|
|
174
203
|
# Parsed query string as hash
|
|
175
204
|
def query
|
|
176
205
|
@query_hash ||= parse_query_to_hash(@query_string)
|
|
@@ -204,7 +233,7 @@ module Tina4
|
|
|
204
233
|
|
|
205
234
|
def json_body
|
|
206
235
|
@json_body ||= begin
|
|
207
|
-
JSON.parse(
|
|
236
|
+
JSON.parse(body_raw)
|
|
208
237
|
rescue JSON::ParserError, TypeError
|
|
209
238
|
{}
|
|
210
239
|
end
|
|
@@ -273,7 +302,7 @@ module Tina4
|
|
|
273
302
|
if @content_type.include?("application/json")
|
|
274
303
|
json_body
|
|
275
304
|
elsif @content_type.include?("application/x-www-form-urlencoded")
|
|
276
|
-
parse_query_to_hash(
|
|
305
|
+
parse_query_to_hash(body_raw)
|
|
277
306
|
elsif @content_type.include?("multipart/form-data")
|
|
278
307
|
# Extract form fields from Rack's parsed multipart data.
|
|
279
308
|
# Files are handled separately by extract_files.
|
|
@@ -324,12 +353,19 @@ module Tina4
|
|
|
324
353
|
if form_hash
|
|
325
354
|
form_hash.each do |key, value|
|
|
326
355
|
if value.is_a?(Hash) && value[:tempfile]
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
356
|
+
tempfile = value[:tempfile]
|
|
357
|
+
|
|
358
|
+
# Indifferent-access per-file hash so file["content"],
|
|
359
|
+
# file[:content], file["filename"], file[:filename] all work.
|
|
360
|
+
# `content` (raw bytes, never base64) is materialised lazily on
|
|
361
|
+
# first access (see FileUpload) — :tempfile-only handlers never
|
|
362
|
+
# buffer large uploads in memory.
|
|
363
|
+
file = FileUpload.new
|
|
364
|
+
file[:filename] = value[:filename]
|
|
365
|
+
file[:type] = value[:type]
|
|
366
|
+
file[:tempfile] = tempfile
|
|
367
|
+
file[:size] = tempfile.size
|
|
368
|
+
result[key] = file
|
|
333
369
|
end
|
|
334
370
|
end
|
|
335
371
|
end
|
data/lib/tina4/response.rb
CHANGED
|
@@ -285,9 +285,19 @@ module Tina4
|
|
|
285
285
|
self
|
|
286
286
|
end
|
|
287
287
|
|
|
288
|
-
# Stream
|
|
288
|
+
# Stream a response for Server-Sent Events (SSE) / chunked transfer.
|
|
289
289
|
#
|
|
290
|
-
#
|
|
290
|
+
# Two equivalent call styles (cross-framework parity — Python/PHP/Node
|
|
291
|
+
# pass a generator positionally; Ruby additionally supports a block):
|
|
292
|
+
#
|
|
293
|
+
# # 1. Positional generator (Enumerator, or anything responding to
|
|
294
|
+
# # #each or #call that yields string chunks):
|
|
295
|
+
# gen = Enumerator.new do |y|
|
|
296
|
+
# 10.times { |i| y << "data: message #{i}\n\n" }
|
|
297
|
+
# end
|
|
298
|
+
# response.stream(gen)
|
|
299
|
+
#
|
|
300
|
+
# # 2. Block form (unchanged):
|
|
291
301
|
# Tina4::Router.get "/events" do |request, response|
|
|
292
302
|
# response.stream do |out|
|
|
293
303
|
# 10.times do |i|
|
|
@@ -297,16 +307,18 @@ module Tina4
|
|
|
297
307
|
# end
|
|
298
308
|
# end
|
|
299
309
|
#
|
|
310
|
+
# @param generator [#each, #call, nil] Optional source of string chunks.
|
|
300
311
|
# @param content_type [String] Content type (default: text/event-stream)
|
|
301
312
|
# @yield [Enumerator::Yielder] Block receives a yielder to push chunks
|
|
302
313
|
# @return [self]
|
|
303
|
-
def stream(content_type: "text/event-stream", &block)
|
|
314
|
+
def stream(generator = nil, content_type: "text/event-stream", &block)
|
|
304
315
|
@status_code = @status_code || 200
|
|
305
316
|
@headers["content-type"] = content_type
|
|
306
317
|
@headers["cache-control"] = "no-cache"
|
|
307
318
|
@headers["connection"] = "keep-alive"
|
|
308
319
|
@headers["x-accel-buffering"] = "no"
|
|
309
320
|
@_streaming = true
|
|
321
|
+
@_stream_generator = generator
|
|
310
322
|
@_stream_block = block
|
|
311
323
|
self
|
|
312
324
|
end
|
|
@@ -330,9 +342,24 @@ module Tina4
|
|
|
330
342
|
final_headers["set-cookie"] = @cookies.join("\n") if @cookies && !@cookies.empty?
|
|
331
343
|
|
|
332
344
|
if @_streaming
|
|
333
|
-
# Streaming mode — return an Enumerator as the body
|
|
345
|
+
# Streaming mode — return an Enumerator as the Rack body. A positional
|
|
346
|
+
# generator wins over a block when both are somehow present.
|
|
347
|
+
gen = @_stream_generator
|
|
348
|
+
blk = @_stream_block
|
|
334
349
|
body = Enumerator.new do |yielder|
|
|
335
|
-
|
|
350
|
+
if gen
|
|
351
|
+
if gen.respond_to?(:each)
|
|
352
|
+
# Enumerator / array / any Enumerable of string chunks
|
|
353
|
+
gen.each { |chunk| yielder << chunk }
|
|
354
|
+
elsif gen.respond_to?(:call)
|
|
355
|
+
# Callable that receives the yielder, like the block form
|
|
356
|
+
gen.call(yielder)
|
|
357
|
+
else
|
|
358
|
+
yielder << gen.to_s
|
|
359
|
+
end
|
|
360
|
+
elsif blk
|
|
361
|
+
blk.call(yielder)
|
|
362
|
+
end
|
|
336
363
|
end
|
|
337
364
|
return [@status_code, final_headers, body]
|
|
338
365
|
end
|
data/lib/tina4/version.rb
CHANGED
data/lib/tina4/wsdl.rb
CHANGED
|
@@ -116,9 +116,18 @@ module Tina4
|
|
|
116
116
|
def handle
|
|
117
117
|
return generate_wsdl if @request.nil?
|
|
118
118
|
|
|
119
|
+
# SOAP bodies are raw XML, so read the raw bytes. On a real
|
|
120
|
+
# Tina4::Request use body_raw (request.body now returns the PARSED
|
|
121
|
+
# payload); test stubs that only expose `body` fall back to it.
|
|
122
|
+
raw_body = if @request.respond_to?(:body_raw)
|
|
123
|
+
@request.body_raw
|
|
124
|
+
elsif @request.respond_to?(:body)
|
|
125
|
+
@request.body
|
|
126
|
+
end
|
|
127
|
+
|
|
119
128
|
method = if @request.respond_to?(:method)
|
|
120
129
|
@request.method.to_s.upcase
|
|
121
|
-
elsif
|
|
130
|
+
elsif raw_body && !raw_body.to_s.empty?
|
|
122
131
|
"POST"
|
|
123
132
|
else
|
|
124
133
|
"GET"
|
|
@@ -131,11 +140,7 @@ module Tina4
|
|
|
131
140
|
return generate_wsdl
|
|
132
141
|
end
|
|
133
142
|
|
|
134
|
-
body =
|
|
135
|
-
@request.body.is_a?(String) ? @request.body : @request.body.to_s
|
|
136
|
-
else
|
|
137
|
-
""
|
|
138
|
-
end
|
|
143
|
+
body = raw_body.is_a?(String) ? raw_body : raw_body.to_s
|
|
139
144
|
|
|
140
145
|
process_soap(body)
|
|
141
146
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: tina4ruby
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.13.
|
|
4
|
+
version: 3.13.31
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Tina4 Team
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-06-
|
|
11
|
+
date: 2026-06-17 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rack
|