include path parameters in params hash for ruby environment (#249)

* include path parameters in params hash for ruby environment

* Improve code organization and documentation for ruby environment.

* Document Ruby examples
This commit is contained in:
S. Brent Faulkner
2017-07-04 23:44:18 -07:00
committed by Soam Vasani
parent ae87c0ea37
commit 0fd60eab3b
7 changed files with 208 additions and 52 deletions
+17 -3
View File
@@ -2,9 +2,19 @@
This is the Ruby environment for Fission.
It's a Docker image containing a Ruby 2.4.1 runtime, along with a
dynamic loader. A few common dependencies are included in the
Gemfile.
It's a Docker image containing a Ruby 2.4.1 runtime. The image uses
Rack with WEBrick to host the internal web server.
The environment works via convention where you create a Ruby method
called `handler` with a single optional argument, a `Fission::Context`
object.
The `Fission::Context` object gives access to the Rack env, and a
request object. Please see `fission/context.rb` for the public api.
The `Fission::Request` object is a subclass of `Rack::Request` and
provides access to parameters and headers. See `fission/request.rb`
for the public api.
## Customizing this image
@@ -39,3 +49,7 @@ Or, if you already have an environment, you can update its image:
After this, fission functions that have the env parameter set to the
same environment name as this command will use this environment.
## Creating functions to use this image
See the [examples README](examples/ruby/README.md).
+17
View File
@@ -0,0 +1,17 @@
# frozen_string_literal: true
require_relative 'request'
module Fission
class Context
attr_reader :env
def initialize(env)
@env = env
end
def request
@request ||= Request.new(env)
end
end
end
+19
View File
@@ -0,0 +1,19 @@
# frozen_string_literal: true
require_relative 'context'
module Fission
module Handler
def self.call(env)
response = if method(:handler).arity > 0
handler(Context.new(env))
else
handler
end
response.is_a?(Array) ? response : Rack::Response.new([response]).finish
rescue
Rack::Response.new(['500 Internal Server Error'], 500, {}).finish
end
end
end
+31
View File
@@ -0,0 +1,31 @@
# frozen_string_literal: true
module Fission
HEADER_PREFIX = 'HTTP_'
PARAM_HEADER_PREFIX = 'HTTP_X_FISSION_PARAMS_'
PARAMETERS_KEY = 'fission.request.parameters'
class Request < Rack::Request
def headers
Hash[
*env.select { |k,v| k.start_with?(HEADER_PREFIX) }
.map { |k,v| [k.sub(/\A#{HEADER_PREFIX}/, '').split('_').map(&:capitalize).join('-'), v] }
.sort
.flatten
]
end
def params
env[PARAMETERS_KEY] ||= super.merge(path_parameters)
end
def path_parameters
Hash[
*env.select { |k,v| k.start_with?(PARAM_HEADER_PREFIX) }
.map { |k,v| [k.sub(/\A#{PARAM_HEADER_PREFIX}/, '').downcase, v] }
.sort
.flatten
]
end
end
end
+14
View File
@@ -0,0 +1,14 @@
# frozen_string_literal: true
module Fission
CODE_PATH = '/userfunc/user'
module Specializer
def self.call(env)
load CODE_PATH
Rack::Response.new([], 201).finish
rescue
Rack::Response.new(['500 Internal Server Error'], 500, {}).finish
end
end
end
+3 -49
View File
@@ -1,55 +1,9 @@
# frozen_string_literal: true
require 'rack'
CODEPATH = '/userfunc/user'
module Fission
class Request < Rack::Request
def headers
Hash[
*env.select { |k,v| k.start_with?('HTTP_') }
.map { |k,v| [k.sub(/\AHTTP_/, '').split('_').map(&:capitalize).join('-'), v] }
.sort
.flatten
]
end
end
class Context
attr_reader :env
def initialize(env)
@env = env
end
def request
@request ||= Request.new(env)
end
end
module Specializer
def self.call(env)
load CODEPATH
Rack::Response.new([], 201).finish
rescue
Rack::Response.new(['500 Internal Server Error'], 500, {}).finish
end
end
module Handler
def self.call(env)
response = if method(:handler).arity > 0
handler(Context.new(env))
else
handler
end
response.is_a?(Array) ? response : Rack::Response.new([response]).finish
rescue
Rack::Response.new(['500 Internal Server Error'], 500, {}).finish
end
end
end
require_relative 'fission/specializer'
require_relative 'fission/handler'
app = Rack::Builder.new do
use Rack::CommonLogger, $stderr
+107
View File
@@ -0,0 +1,107 @@
# Ruby examples
This directory contains several examples to get you started using Ruby
with Fission.
Before running any of these functions, make sure you have created a
`ruby` Fission environment:
```
$ fission env create --name ruby --image USER/ruby-env
```
## Method signature
A standard Ruby function has the basic form:
```ruby
def handler(context)
return [200, {}, []]
end
```
If the fission context is not required, the function can be simplified:
```ruby
def handler
[200, {}, ["Hello, world!\n"]]
end
```
If a simple text response is to be returned, with a status of 200, this
can be further simplified.
```ruby
def handler
"Hello, world!\n"
end
```
## Hello example (`hello.rb`)
This example is the simplest possible Ruby function, as described above.
To run the example:
```
$ fission function create --name hello --env ruby --code examples/ruby/hello.rb
$ fission route create --method GET --url /hello --function hello
$ curl http://$FISSION_ROUTER/hello
Hello, world!
```
## Request data example (`request_data.rb`)
This example shows basic use of the `Fission::Context` and
`Fission::Request` objects.
To run the example:
```
$ fission function create --name request --env ruby --code examples/ruby/request_data.rb
$ fission route create --method GET --url /request/{id} --function request
$ curl http://$FISSION_ROUTER/request/123?key=abc
---ENV---
GATEWAY_INTERFACE=CGI/1.1
PATH_INFO=/
QUERY_STRING=key=abc
REMOTE_ADDR=172.17.0.8
REMOTE_HOST=172.17.0.8
REQUEST_METHOD=GET
REQUEST_URI=http://192.168.64.200:31314/?key=abc
SCRIPT_NAME=
SERVER_NAME=192.168.64.200
SERVER_PORT=31314
SERVER_PROTOCOL=HTTP/1.1
SERVER_SOFTWARE=WEBrick/1.3.1 (Ruby/2.4.1/2017-03-22)
HTTP_HOST=192.168.64.200:31314
HTTP_USER_AGENT=curl/7.52.1
HTTP_ACCEPT=*/*
HTTP_X_FISSION_PARAMS_ID=123
HTTP_X_FORWARDED_FOR=172.17.0.1
HTTP_ACCEPT_ENCODING=gzip
rack.version=1=3
...
HTTP_VERSION=HTTP/1.1
REQUEST_PATH=/
---HEADERS---
Accept: */*
Accept-Encoding: gzip
Host: 192.168.64.200:31314
User-Agent: curl/7.52.1
Version: HTTP/1.1
X-Fission-Params-Id: 123
X-Forwarded-For: 172.17.0.1
---PARAMS---
key=abc
id=123
--BODY--
```