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:
committed by
Soam Vasani
parent
ae87c0ea37
commit
0fd60eab3b
@@ -2,9 +2,19 @@
|
|||||||
|
|
||||||
This is the Ruby environment for Fission.
|
This is the Ruby environment for Fission.
|
||||||
|
|
||||||
It's a Docker image containing a Ruby 2.4.1 runtime, along with a
|
It's a Docker image containing a Ruby 2.4.1 runtime. The image uses
|
||||||
dynamic loader. A few common dependencies are included in the
|
Rack with WEBrick to host the internal web server.
|
||||||
Gemfile.
|
|
||||||
|
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
|
## 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
|
After this, fission functions that have the env parameter set to the
|
||||||
same environment name as this command will use this environment.
|
same environment name as this command will use this environment.
|
||||||
|
|
||||||
|
## Creating functions to use this image
|
||||||
|
|
||||||
|
See the [examples README](examples/ruby/README.md).
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -1,55 +1,9 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'rack'
|
require 'rack'
|
||||||
|
|
||||||
CODEPATH = '/userfunc/user'
|
require_relative 'fission/specializer'
|
||||||
|
require_relative 'fission/handler'
|
||||||
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
|
|
||||||
|
|
||||||
app = Rack::Builder.new do
|
app = Rack::Builder.new do
|
||||||
use Rack::CommonLogger, $stderr
|
use Rack::CommonLogger, $stderr
|
||||||
|
|||||||
@@ -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--
|
||||||
|
|
||||||
|
```
|
||||||
Reference in New Issue
Block a user