functions_framework 0.1.0 → 0.3.1

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.
@@ -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
- registry = ::FunctionsFramework::Registry.new
75
- old_registry = ::FunctionsFramework.global_registry
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
- env = Testing.build_standard_env URI(url), headers
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 data [String] The body to post.
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, data, headers = []
146
- env = Testing.build_standard_env URI(url), headers
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
- name, value = header.split ":"
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
@@ -17,5 +17,5 @@ module FunctionsFramework
17
17
  # Version of the Ruby Functions Framework
18
18
  # @return [String]
19
19
  #
20
- VERSION = "0.1.0".freeze
20
+ VERSION = "0.3.1".freeze
21
21
  end
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.0
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-01-30 00:00:00.000000000 Z
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.9.3
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.9.3
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/json_structure.rb
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