functions_framework 0.1.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.yardopts +6 -2
- data/CHANGELOG.md +38 -0
- data/README.md +57 -137
- data/bin/functions-framework-ruby +19 -0
- data/docs/deploying-functions.md +182 -0
- data/docs/overview.md +142 -0
- data/docs/running-a-functions-server.md +122 -0
- data/docs/testing-functions.md +169 -0
- data/docs/writing-functions.md +261 -0
- data/lib/functions_framework.rb +19 -42
- data/lib/functions_framework/cli.rb +71 -13
- data/lib/functions_framework/cloud_events.rb +9 -109
- data/lib/functions_framework/cloud_events/errors.rb +42 -0
- data/lib/functions_framework/cloud_events/event.rb +51 -249
- data/lib/functions_framework/cloud_events/event/v1.rb +363 -0
- data/lib/functions_framework/cloud_events/http_binding.rb +270 -0
- data/lib/functions_framework/cloud_events/json_format.rb +122 -0
- data/lib/functions_framework/function.rb +7 -11
- data/lib/functions_framework/legacy_event_converter.rb +145 -0
- data/lib/functions_framework/registry.rb +3 -27
- data/lib/functions_framework/server.rb +63 -42
- data/lib/functions_framework/testing.rb +60 -20
- data/lib/functions_framework/version.rb +1 -1
- metadata +16 -6
- data/lib/functions_framework/cloud_events/binary_content.rb +0 -59
- data/lib/functions_framework/cloud_events/json_structure.rb +0 -88
@@ -70,16 +70,9 @@ module FunctionsFramework
|
|
70
70
|
#
|
71
71
|
# @param path [String] File path to load
|
72
72
|
#
|
73
|
-
def load_temporary path
|
74
|
-
|
75
|
-
|
76
|
-
::FunctionsFramework.global_registry = registry
|
77
|
-
begin
|
78
|
-
::Kernel.load path
|
79
|
-
yield
|
80
|
-
ensure
|
81
|
-
::FunctionsFramework.global_registry = old_registry
|
82
|
-
end
|
73
|
+
def load_temporary path, &block
|
74
|
+
path = ::File.expand_path path
|
75
|
+
Testing.load_for_testing path, &block
|
83
76
|
end
|
84
77
|
|
85
78
|
##
|
@@ -123,30 +116,52 @@ module FunctionsFramework
|
|
123
116
|
end
|
124
117
|
end
|
125
118
|
|
119
|
+
##
|
120
|
+
# Make a Rack request, for passing to a function test.
|
121
|
+
#
|
122
|
+
# @param url [URI,String] The URL to get, including query params.
|
123
|
+
# @param method [String] The HTTP method (defaults to "GET").
|
124
|
+
# @param body [String] The HTTP body, if any.
|
125
|
+
# @param headers [Array,Hash] HTTP headers. May be given as a hash (of
|
126
|
+
# header names mapped to values), an array of strings (where each
|
127
|
+
# string is of the form `Header-Name: Header value`), or an array of
|
128
|
+
# two-element string arrays.
|
129
|
+
# @return [Rack::Request]
|
130
|
+
#
|
131
|
+
def make_request url, method: ::Rack::GET, body: nil, headers: []
|
132
|
+
env = Testing.build_standard_env URI(url), headers
|
133
|
+
env[::Rack::REQUEST_METHOD] = method
|
134
|
+
env[::Rack::RACK_INPUT] = ::StringIO.new body if body
|
135
|
+
::Rack::Request.new env
|
136
|
+
end
|
137
|
+
|
126
138
|
##
|
127
139
|
# Make a simple GET request, for passing to a function test.
|
128
140
|
#
|
129
141
|
# @param url [URI,String] The URL to get.
|
142
|
+
# @param headers [Array,Hash] HTTP headers. May be given as a hash (of
|
143
|
+
# header names mapped to values), an array of strings (where each
|
144
|
+
# string is of the form `Header-Name: Header value`), or an array of
|
145
|
+
# two-element string arrays.
|
130
146
|
# @return [Rack::Request]
|
131
147
|
#
|
132
148
|
def make_get_request url, headers = []
|
133
|
-
|
134
|
-
env[::Rack::REQUEST_METHOD] = ::Rack::GET
|
135
|
-
::Rack::Request.new env
|
149
|
+
make_request url, headers: headers
|
136
150
|
end
|
137
151
|
|
138
152
|
##
|
139
153
|
# Make a simple POST request, for passing to a function test.
|
140
154
|
#
|
141
155
|
# @param url [URI,String] The URL to post to.
|
142
|
-
# @param
|
156
|
+
# @param body [String] The body to post.
|
157
|
+
# @param headers [Array,Hash] HTTP headers. May be given as a hash (of
|
158
|
+
# header names mapped to values), an array of strings (where each
|
159
|
+
# string is of the form `Header-Name: Header value`), or an array of
|
160
|
+
# two-element string arrays.
|
143
161
|
# @return [Rack::Request]
|
144
162
|
#
|
145
|
-
def make_post_request url,
|
146
|
-
|
147
|
-
env[::Rack::REQUEST_METHOD] = ::Rack::POST
|
148
|
-
env[::Rack::INPUT_STREAM] = ::StringIO.new data
|
149
|
-
::Rack::Request.new env
|
163
|
+
def make_post_request url, body, headers = []
|
164
|
+
make_request url, method: ::Rack::POST, body: body, headers: headers
|
150
165
|
end
|
151
166
|
|
152
167
|
##
|
@@ -180,7 +195,28 @@ module FunctionsFramework
|
|
180
195
|
|
181
196
|
extend self
|
182
197
|
|
198
|
+
@testing_registries = {}
|
199
|
+
@mutex = ::Mutex.new
|
200
|
+
|
183
201
|
class << self
|
202
|
+
## @private
|
203
|
+
def load_for_testing path
|
204
|
+
old_registry = ::FunctionsFramework.global_registry
|
205
|
+
@mutex.synchronize do
|
206
|
+
if @testing_registries.key? path
|
207
|
+
::FunctionsFramework.global_registry = @testing_registries[path]
|
208
|
+
else
|
209
|
+
new_registry = ::FunctionsFramework::Registry.new
|
210
|
+
::FunctionsFramework.global_registry = new_registry
|
211
|
+
::Kernel.load path
|
212
|
+
@testing_registries[path] = new_registry
|
213
|
+
end
|
214
|
+
end
|
215
|
+
yield
|
216
|
+
ensure
|
217
|
+
::FunctionsFramework.global_registry = old_registry
|
218
|
+
end
|
219
|
+
|
184
220
|
## @private
|
185
221
|
def interpret_response
|
186
222
|
response =
|
@@ -231,7 +267,11 @@ module FunctionsFramework
|
|
231
267
|
::Rack::RACK_ERRORS => ::StringIO.new
|
232
268
|
}
|
233
269
|
headers.each do |header|
|
234
|
-
|
270
|
+
if header.is_a? String
|
271
|
+
name, value = header.split ":"
|
272
|
+
elsif header.is_a? Array
|
273
|
+
name, value = header
|
274
|
+
end
|
235
275
|
next unless name && value
|
236
276
|
name = name.strip.upcase.tr "-", "_"
|
237
277
|
name = "HTTP_#{name}" unless ["CONTENT_TYPE", "CONTENT_LENGTH"].include? name
|
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: 0.1
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Azuma
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-06-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: puma
|
@@ -114,14 +114,14 @@ dependencies:
|
|
114
114
|
requirements:
|
115
115
|
- - "~>"
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: 0.
|
117
|
+
version: 0.10.0
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
122
|
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version: 0.
|
124
|
+
version: 0.10.0
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
126
|
name: yard
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -141,6 +141,7 @@ email:
|
|
141
141
|
- dazuma@google.com
|
142
142
|
executables:
|
143
143
|
- functions-framework
|
144
|
+
- functions-framework-ruby
|
144
145
|
extensions: []
|
145
146
|
extra_rdoc_files: []
|
146
147
|
files:
|
@@ -149,14 +150,23 @@ files:
|
|
149
150
|
- LICENSE
|
150
151
|
- README.md
|
151
152
|
- bin/functions-framework
|
153
|
+
- bin/functions-framework-ruby
|
154
|
+
- docs/deploying-functions.md
|
155
|
+
- docs/overview.md
|
156
|
+
- docs/running-a-functions-server.md
|
157
|
+
- docs/testing-functions.md
|
158
|
+
- docs/writing-functions.md
|
152
159
|
- lib/functions_framework.rb
|
153
160
|
- lib/functions_framework/cli.rb
|
154
161
|
- lib/functions_framework/cloud_events.rb
|
155
|
-
- lib/functions_framework/cloud_events/binary_content.rb
|
156
162
|
- lib/functions_framework/cloud_events/content_type.rb
|
163
|
+
- lib/functions_framework/cloud_events/errors.rb
|
157
164
|
- lib/functions_framework/cloud_events/event.rb
|
158
|
-
- lib/functions_framework/cloud_events/
|
165
|
+
- lib/functions_framework/cloud_events/event/v1.rb
|
166
|
+
- lib/functions_framework/cloud_events/http_binding.rb
|
167
|
+
- lib/functions_framework/cloud_events/json_format.rb
|
159
168
|
- lib/functions_framework/function.rb
|
169
|
+
- lib/functions_framework/legacy_event_converter.rb
|
160
170
|
- lib/functions_framework/registry.rb
|
161
171
|
- lib/functions_framework/server.rb
|
162
172
|
- lib/functions_framework/testing.rb
|
@@ -1,59 +0,0 @@
|
|
1
|
-
# Copyright 2020 Google LLC
|
2
|
-
#
|
3
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
-
# you may not use this file except in compliance with the License.
|
5
|
-
# You may obtain a copy of the License at
|
6
|
-
#
|
7
|
-
# https://www.apache.org/licenses/LICENSE-2.0
|
8
|
-
#
|
9
|
-
# Unless required by applicable law or agreed to in writing, software
|
10
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
-
# See the License for the specific language governing permissions and
|
13
|
-
# limitations under the License.
|
14
|
-
|
15
|
-
module FunctionsFramework
|
16
|
-
module CloudEvents
|
17
|
-
##
|
18
|
-
# A content handler for the binary mode.
|
19
|
-
# See https://github.com/cloudevents/spec/blob/master/http-protocol-binding.md
|
20
|
-
#
|
21
|
-
module BinaryContent
|
22
|
-
class << self
|
23
|
-
##
|
24
|
-
# Decode an event from the given Rack environment
|
25
|
-
#
|
26
|
-
# @param env [Hash] Rack environment hash
|
27
|
-
# @param content_type [FunctionsFramework::CloudEvents::ContentType]
|
28
|
-
# the content type from the Rack environment
|
29
|
-
# @return [FunctionsFramework::CloudEvents::Event]
|
30
|
-
#
|
31
|
-
def decode_rack_env env, content_type
|
32
|
-
data = env["rack.input"]&.read
|
33
|
-
spec_version = interpret_header env, "HTTP_CE_SPECVERSION"
|
34
|
-
raise "Unrecognized specversion: #{spec_version}" unless spec_version == "1.0"
|
35
|
-
Event.new \
|
36
|
-
id: interpret_header(env, "HTTP_CE_ID"),
|
37
|
-
source: interpret_header(env, "HTTP_CE_SOURCE"),
|
38
|
-
type: interpret_header(env, "HTTP_CE_TYPE"),
|
39
|
-
spec_version: spec_version,
|
40
|
-
data: data,
|
41
|
-
data_content_type: content_type,
|
42
|
-
data_schema: interpret_header(env, "HTTP_CE_DATASCHEMA"),
|
43
|
-
subject: interpret_header(env, "HTTP_CE_SUBJECT"),
|
44
|
-
time: interpret_header(env, "HTTP_CE_TIME")
|
45
|
-
end
|
46
|
-
|
47
|
-
private
|
48
|
-
|
49
|
-
def interpret_header env, key
|
50
|
-
escaped_value = env[key]
|
51
|
-
return nil if escaped_value.nil?
|
52
|
-
escaped_value.gsub(/%([0-9a-fA-F]{2})/) do
|
53
|
-
[$1.to_i(16)].pack "C" # rubocop:disable Style/PerlBackrefs
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
@@ -1,88 +0,0 @@
|
|
1
|
-
# Copyright 2020 Google LLC
|
2
|
-
#
|
3
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
-
# you may not use this file except in compliance with the License.
|
5
|
-
# You may obtain a copy of the License at
|
6
|
-
#
|
7
|
-
# https://www.apache.org/licenses/LICENSE-2.0
|
8
|
-
#
|
9
|
-
# Unless required by applicable law or agreed to in writing, software
|
10
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
-
# See the License for the specific language governing permissions and
|
13
|
-
# limitations under the License.
|
14
|
-
|
15
|
-
require "base64"
|
16
|
-
require "json"
|
17
|
-
|
18
|
-
module FunctionsFramework
|
19
|
-
module CloudEvents
|
20
|
-
##
|
21
|
-
# A content handler for the JSON structure and JSON batch format.
|
22
|
-
# See https://github.com/cloudevents/spec/blob/master/json-format.md
|
23
|
-
#
|
24
|
-
module JsonStructure
|
25
|
-
class << self
|
26
|
-
##
|
27
|
-
# Decode an event from the given input string
|
28
|
-
#
|
29
|
-
# @param input [IO] An IO-like object providing a JSON-formatted string
|
30
|
-
# @param content_type [FunctionsFramework::CloudEvents::ContentType]
|
31
|
-
# the content type
|
32
|
-
# @return [FunctionsFramework::CloudEvents::Event]
|
33
|
-
#
|
34
|
-
def decode_structured_content input, content_type
|
35
|
-
input = input.read if input.respond_to? :read
|
36
|
-
charset = content_type.charset
|
37
|
-
input = input.encode charset if charset
|
38
|
-
structure = ::JSON.parse input
|
39
|
-
decode_hash_structure structure
|
40
|
-
end
|
41
|
-
|
42
|
-
##
|
43
|
-
# Decode a batch of events from the given input string
|
44
|
-
#
|
45
|
-
# @param input [IO] An IO-like object providing a JSON-formatted string
|
46
|
-
# @param content_type [FunctionsFramework::CloudEvents::ContentType]
|
47
|
-
# the content type
|
48
|
-
# @return [Array<FunctionsFramework::CloudEvents::Event>]
|
49
|
-
#
|
50
|
-
def decode_batched_content input, content_type
|
51
|
-
input = input.read if input.respond_to? :read
|
52
|
-
charset = content_type.charset
|
53
|
-
input = input.encode charset if charset
|
54
|
-
structure_array = Array(::JSON.parse(input))
|
55
|
-
structure_array.map { |structure| decode_hash_structure structure }
|
56
|
-
end
|
57
|
-
|
58
|
-
##
|
59
|
-
# Decode a single event from a hash data structure with keys and types
|
60
|
-
# conforming to the JSON event format
|
61
|
-
#
|
62
|
-
# @param structure [Hash] Input hash
|
63
|
-
# @return [FunctionsFramework::CloudEvents::Event]
|
64
|
-
#
|
65
|
-
def decode_hash_structure structure
|
66
|
-
data =
|
67
|
-
if structure.key? "data_base64"
|
68
|
-
::Base64.decode64 structure["data_base64"]
|
69
|
-
else
|
70
|
-
structure["data"]
|
71
|
-
end
|
72
|
-
spec_version = structure["specversion"]
|
73
|
-
raise "Unrecognized specversion: #{spec_version}" unless spec_version == "1.0"
|
74
|
-
Event.new \
|
75
|
-
id: structure["id"],
|
76
|
-
source: structure["source"],
|
77
|
-
type: structure["type"],
|
78
|
-
spec_version: spec_version,
|
79
|
-
data: data,
|
80
|
-
data_content_type: structure["datacontenttype"],
|
81
|
-
data_schema: structure["dataschema"],
|
82
|
-
subject: structure["subject"],
|
83
|
-
time: structure["time"]
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|