functions_framework 1.3.0 → 1.4.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/CHANGELOG.md +6 -0
- data/README.md +1 -1
- data/lib/functions_framework/function.rb +24 -1
- data/lib/functions_framework/registry.rb +23 -0
- data/lib/functions_framework/server.rb +44 -0
- data/lib/functions_framework/testing.rb +48 -14
- data/lib/functions_framework/version.rb +1 -1
- data/lib/functions_framework.rb +33 -3
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 57eed57ea92eee1e51f3285c883f0f757a87f8379b7316fe5cd1eed46e1782fc
|
4
|
+
data.tar.gz: c039b2139d3692727dffcbe715b390460445d4c8b5728e2c4fbe2c59db3030c8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d1369b3334e1605956829e6077fe7d76f5f49155985598d2098928cc6a54d4f58b1252f8e6971cfd3784e104ca15162ec1e37fc0e80f2d0eadf60ad5698d7657
|
7
|
+
data.tar.gz: 9fa3b2e12ff0ad195ad0dd808c147ad30adf9eeb8ac25a2990ebddb11ef8945f80b8091455415cb0462fbc334e3eacc77afeb55175a01a713bbc2f808a3018b8
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Functions Framework for Ruby [](https://googlecloudplatform.github.io/functions-framework-ruby/latest) [](https://badge.fury.io/rb/functions_framework)
|
1
|
+
# Functions Framework for Ruby [](https://googlecloudplatform.github.io/functions-framework-ruby/latest) [](https://badge.fury.io/rb/functions_framework) 
|
2
2
|
|
3
3
|
An open source framework for writing lightweight, portable Ruby functions that
|
4
4
|
run in a serverless environment. Functions written to this Framework will run
|
@@ -70,6 +70,23 @@ module FunctionsFramework
|
|
70
70
|
new name, :http, callable: callable, &block
|
71
71
|
end
|
72
72
|
|
73
|
+
##
|
74
|
+
# Create a new Typed function definition.
|
75
|
+
#
|
76
|
+
# @param name [String] The function name
|
77
|
+
# @param callable [Class,#call] A callable object or class.
|
78
|
+
# @param request_class [#decode_json] A class that can be read from JSON.
|
79
|
+
# @param block [Proc] The function code as a block.
|
80
|
+
# @return [FunctionsFramework::Function]
|
81
|
+
#
|
82
|
+
def self.typed name, request_class: nil, callable: nil, &block
|
83
|
+
if request_class && !(request_class.respond_to? :decode_json)
|
84
|
+
raise ::ArgumentError, "Type does not implement 'decode_json' class method"
|
85
|
+
end
|
86
|
+
|
87
|
+
new name, :typed, callable: callable, request_class: request_class, &block
|
88
|
+
end
|
89
|
+
|
73
90
|
##
|
74
91
|
# Create a new CloudEvents function definition.
|
75
92
|
#
|
@@ -102,9 +119,10 @@ module FunctionsFramework
|
|
102
119
|
# @param callable [Class,#call] A callable object or class.
|
103
120
|
# @param block [Proc] The function code as a block.
|
104
121
|
#
|
105
|
-
def initialize name, type, callable: nil, &block
|
122
|
+
def initialize name, type, callable: nil, request_class: nil, &block
|
106
123
|
@name = name
|
107
124
|
@type = type
|
125
|
+
@request_class = request_class
|
108
126
|
@callable = @callable_class = nil
|
109
127
|
if callable.respond_to? :call
|
110
128
|
@callable = callable
|
@@ -129,6 +147,11 @@ module FunctionsFramework
|
|
129
147
|
#
|
130
148
|
attr_reader :type
|
131
149
|
|
150
|
+
##
|
151
|
+
# @return [#decode_json] The class for the request parameter. Only used for typed functions.
|
152
|
+
#
|
153
|
+
attr_reader :request_class
|
154
|
+
|
132
155
|
##
|
133
156
|
# Populate the given globals hash with this function's info.
|
134
157
|
#
|
@@ -81,6 +81,29 @@ module FunctionsFramework
|
|
81
81
|
self
|
82
82
|
end
|
83
83
|
|
84
|
+
##
|
85
|
+
# Add a Typed function to the registry.
|
86
|
+
#
|
87
|
+
# You must provide a name for the function, and a block that implements the
|
88
|
+
# function. The block should take a single `Hash` argument which will be the
|
89
|
+
# JSON decoded request payload. It should return a `Hash` response which
|
90
|
+
# will be JSON encoded and written to the response.
|
91
|
+
#
|
92
|
+
# @param name [String] The function name.
|
93
|
+
# @param request_class [#decode_json] An optional class which will be used
|
94
|
+
# to decode the request.
|
95
|
+
# @param block [Proc] The function code as a proc
|
96
|
+
# @return [self]
|
97
|
+
#
|
98
|
+
def add_typed name, request_class: nil, &block
|
99
|
+
name = name.to_s
|
100
|
+
@mutex.synchronize do
|
101
|
+
raise ::ArgumentError, "Function already defined: #{name}" if @functions.key? name
|
102
|
+
@functions[name] = Function.typed name, request_class: request_class, &block
|
103
|
+
end
|
104
|
+
self
|
105
|
+
end
|
106
|
+
|
84
107
|
##
|
85
108
|
# Add a CloudEvent function to the registry.
|
86
109
|
#
|
@@ -54,6 +54,8 @@ module FunctionsFramework
|
|
54
54
|
HttpApp.new function, globals, @config
|
55
55
|
when :cloud_event
|
56
56
|
EventApp.new function, globals, @config
|
57
|
+
when :typed
|
58
|
+
TypedApp.new function, globals, @config
|
57
59
|
else
|
58
60
|
raise "Unrecognized function type: #{function.type}"
|
59
61
|
end
|
@@ -405,6 +407,11 @@ module FunctionsFramework
|
|
405
407
|
string_response message, 500
|
406
408
|
end
|
407
409
|
|
410
|
+
def bad_request message
|
411
|
+
message = "Bad Request" unless @config.show_error_details?
|
412
|
+
string_response message, 400
|
413
|
+
end
|
414
|
+
|
408
415
|
def flush_streams
|
409
416
|
$stdout.flush
|
410
417
|
$stderr.flush
|
@@ -436,6 +443,43 @@ module FunctionsFramework
|
|
436
443
|
end
|
437
444
|
end
|
438
445
|
|
446
|
+
## @private
|
447
|
+
class TypedApp < AppBase
|
448
|
+
def initialize function, globals, config
|
449
|
+
super config
|
450
|
+
@function = function
|
451
|
+
@globals = globals
|
452
|
+
end
|
453
|
+
|
454
|
+
def call env
|
455
|
+
return notfound_response if excluded_path? env
|
456
|
+
begin
|
457
|
+
logger = env[::Rack::RACK_LOGGER] ||= @config.logger
|
458
|
+
request = ::Rack::Request.new env
|
459
|
+
logger.info "FunctionsFramework: Handling Typed #{request.request_method} request"
|
460
|
+
|
461
|
+
begin
|
462
|
+
req = if @function.request_class
|
463
|
+
request_class.decode_json request.body.read.to_s
|
464
|
+
else
|
465
|
+
JSON.parse request.body.read.to_s
|
466
|
+
end
|
467
|
+
rescue JSON::ParserError => e
|
468
|
+
return bad_request e.message
|
469
|
+
end
|
470
|
+
|
471
|
+
res = @function.call req, globals: @globals, logger: logger
|
472
|
+
return string_response res.to_json, 200, content_type: "application/json" if res
|
473
|
+
|
474
|
+
string_response "", 204
|
475
|
+
rescue ::StandardError => e
|
476
|
+
interpret_response e
|
477
|
+
end
|
478
|
+
ensure
|
479
|
+
flush_streams
|
480
|
+
end
|
481
|
+
end
|
482
|
+
|
439
483
|
## @private
|
440
484
|
class EventApp < AppBase
|
441
485
|
def initialize function, globals, config
|
@@ -134,16 +134,42 @@ module FunctionsFramework
|
|
134
134
|
#
|
135
135
|
def call_http name, request, globals: nil, logger: nil
|
136
136
|
globals ||= run_startup_tasks name, logger: logger, lenient: true
|
137
|
-
|
138
|
-
case function&.type
|
139
|
-
when :http
|
137
|
+
Testing.call :http, name, readable_name: "HTTP" do |function|
|
140
138
|
Testing.interpret_response do
|
141
139
|
function.call request, globals: globals, logger: logger
|
142
140
|
end
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
##
|
145
|
+
# Call the given Typed function for testing. The underlying function must
|
146
|
+
# be of type `:typed`. Returns the Rack response.
|
147
|
+
#
|
148
|
+
# By default, the startup tasks will be run for the given function if they
|
149
|
+
# have not already been run. You can, however, disable running startup
|
150
|
+
# tasks by providing an explicit globals hash.
|
151
|
+
#
|
152
|
+
# By default, the {FunctionsFramework.logger} will be used, but you can
|
153
|
+
# override that by providing your own logger. In particular, to disable
|
154
|
+
# logging, you can pass `Logger.new(nil)`.
|
155
|
+
#
|
156
|
+
# @param name [String] The name of the function to call
|
157
|
+
# @param request [Rack::Request] The Rack request to send
|
158
|
+
# @param globals [Hash] Do not run startup tasks, and instead provide the
|
159
|
+
# globals directly. Optional.
|
160
|
+
# @param logger [Logger] Use the given logger instead of the Functions
|
161
|
+
# Framework's global logger. Optional.
|
162
|
+
# @return [Rack::Response]
|
163
|
+
#
|
164
|
+
def call_typed name, request, globals: nil, logger: nil
|
165
|
+
globals ||= run_startup_tasks name, logger: logger, lenient: true
|
166
|
+
Testing.call :typed, name, readable_name: "Typed" do |function|
|
167
|
+
Testing.interpret_response do
|
168
|
+
config = FunctionsFramework::Server::Config.new
|
169
|
+
config.logger = logger
|
170
|
+
app = FunctionsFramework::Server::TypedApp.new function, globals, config
|
171
|
+
app.call request.env
|
172
|
+
end
|
147
173
|
end
|
148
174
|
end
|
149
175
|
|
@@ -169,15 +195,9 @@ module FunctionsFramework
|
|
169
195
|
#
|
170
196
|
def call_event name, event, globals: nil, logger: nil
|
171
197
|
globals ||= run_startup_tasks name, logger: logger, lenient: true
|
172
|
-
|
173
|
-
case function&.type
|
174
|
-
when :cloud_event
|
198
|
+
Testing.call :cloud_event, name, readable_name: "CloudEvent" do |function|
|
175
199
|
function.call event, globals: globals, logger: logger
|
176
200
|
nil
|
177
|
-
when nil
|
178
|
-
raise "Unknown function name #{name}"
|
179
|
-
else
|
180
|
-
raise "Function #{name} is not a CloudEvent function"
|
181
201
|
end
|
182
202
|
end
|
183
203
|
|
@@ -316,6 +336,20 @@ module FunctionsFramework
|
|
316
336
|
end
|
317
337
|
end
|
318
338
|
|
339
|
+
## @private
|
340
|
+
def call type, name, readable_name: nil
|
341
|
+
readable_name ||= type
|
342
|
+
function = Testing.current_registry[name]
|
343
|
+
case function&.type
|
344
|
+
when type
|
345
|
+
yield function
|
346
|
+
when nil
|
347
|
+
raise "Unknown function name #{name}"
|
348
|
+
else
|
349
|
+
raise "Function #{name} is not a #{readable_name} function"
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
319
353
|
## @private
|
320
354
|
def interpret_response
|
321
355
|
response =
|
data/lib/functions_framework.rb
CHANGED
@@ -115,9 +115,9 @@ module FunctionsFramework
|
|
115
115
|
attr_accessor :logger
|
116
116
|
|
117
117
|
##
|
118
|
-
# Define a function that
|
118
|
+
# Define a function that responds to HTTP requests.
|
119
119
|
#
|
120
|
-
# You must provide a name for the function, and a block that
|
120
|
+
# You must provide a name for the function, and a block that implements the
|
121
121
|
# function. The block should take a single `Rack::Request` argument. It
|
122
122
|
# should return one of the following:
|
123
123
|
# * A standard 3-element Rack response array. See
|
@@ -142,10 +142,40 @@ module FunctionsFramework
|
|
142
142
|
self
|
143
143
|
end
|
144
144
|
|
145
|
+
## Define a Typed function that responds to HTTP requests.
|
146
|
+
#
|
147
|
+
# You must provide a name for the function, and a block that implements the
|
148
|
+
# function. The block should take a single argument representing the request
|
149
|
+
# payload. If a `request_type` is provided, the argument object will be of
|
150
|
+
# the given decoded type; otherwise, it will be a JSON hash. The block
|
151
|
+
# should return a JSON hash or an object that implements `#to_json`.
|
152
|
+
#
|
153
|
+
# ## Example
|
154
|
+
# FunctionsFramework.typed "my-sum-function" do |add_request|
|
155
|
+
# {sum: add_request["num1"] + add_response["num2"]}
|
156
|
+
# end
|
157
|
+
#
|
158
|
+
# ## Example with Type
|
159
|
+
# FunctionsFramework.typed "identity",
|
160
|
+
# request_class: MyCustomType do |custom_type|
|
161
|
+
# custom_type
|
162
|
+
# end
|
163
|
+
#
|
164
|
+
# @param name [String] The function name. Defaults to {DEFAULT_TARGET}
|
165
|
+
# @param request_class [#decode_json] An optional class which will be used to
|
166
|
+
# decode the request if it implements a `decode_json` static method.
|
167
|
+
# @param block [Proc] The function code as a proc @return [self]
|
168
|
+
# @return [self]
|
169
|
+
#
|
170
|
+
def typed name = DEFAULT_TARGET, request_class: nil, &block
|
171
|
+
global_registry.add_typed name, request_class: request_class, &block
|
172
|
+
self
|
173
|
+
end
|
174
|
+
|
145
175
|
##
|
146
176
|
# Define a function that responds to CloudEvents.
|
147
177
|
#
|
148
|
-
# You must provide a name for the function, and a block that
|
178
|
+
# You must provide a name for the function, and a block that implements the
|
149
179
|
# function. The block should take one argument: the event object of type
|
150
180
|
# [`CloudEvents::Event`](https://cloudevents.github.io/sdk-ruby/latest/CloudEvents/Event).
|
151
181
|
# Any return value is ignored.
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: functions_framework
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Azuma
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-06-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: cloud_events
|
@@ -106,10 +106,10 @@ homepage: https://github.com/GoogleCloudPlatform/functions-framework-ruby
|
|
106
106
|
licenses:
|
107
107
|
- Apache-2.0
|
108
108
|
metadata:
|
109
|
-
changelog_uri: https://googlecloudplatform.github.io/functions-framework-ruby/v1.
|
109
|
+
changelog_uri: https://googlecloudplatform.github.io/functions-framework-ruby/v1.4.0/file.CHANGELOG.html
|
110
110
|
source_code_uri: https://github.com/GoogleCloudPlatform/functions-framework-ruby
|
111
111
|
bug_tracker_uri: https://github.com/GoogleCloudPlatform/functions-framework-ruby/issues
|
112
|
-
documentation_uri: https://googlecloudplatform.github.io/functions-framework-ruby/v1.
|
112
|
+
documentation_uri: https://googlecloudplatform.github.io/functions-framework-ruby/v1.4.0
|
113
113
|
post_install_message:
|
114
114
|
rdoc_options: []
|
115
115
|
require_paths:
|