functions_framework 1.3.0 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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 [![Documentation](https://img.shields.io/badge/docs-FunctionsFramework-red.svg)](https://googlecloudplatform.github.io/functions-framework-ruby/latest) [![Gem Version](https://badge.fury.io/rb/functions_framework.svg)](https://badge.fury.io/rb/functions_framework)
|
1
|
+
# Functions Framework for Ruby [![Documentation](https://img.shields.io/badge/docs-FunctionsFramework-red.svg)](https://googlecloudplatform.github.io/functions-framework-ruby/latest) [![Gem Version](https://badge.fury.io/rb/functions_framework.svg)](https://badge.fury.io/rb/functions_framework) ![Security Scorecard](https://api.securityscorecards.dev/projects/github.com/GoogleCloudPlatform/functions-framework-ruby/badge)
|
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:
|