sinatra-rpc 0.1.0
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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.ruby-version +1 -0
- data/.travis.yml +5 -0
- data/.yardopts +1 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +113 -0
- data/Rakefile +6 -0
- data/lib/sinatra/rpc.rb +99 -0
- data/lib/sinatra/rpc/fault.rb +39 -0
- data/lib/sinatra/rpc/handler/echo.rb +17 -0
- data/lib/sinatra/rpc/handler/introspection.rb +44 -0
- data/lib/sinatra/rpc/helpers.rb +70 -0
- data/lib/sinatra/rpc/serializer.rb +31 -0
- data/lib/sinatra/rpc/serializer/base.rb +52 -0
- data/lib/sinatra/rpc/serializer/xmlrpc.rb +37 -0
- data/lib/sinatra/rpc/utils.rb +107 -0
- data/lib/sinatra/rpc/version.rb +5 -0
- data/sinatra-rpc.gemspec +30 -0
- data/spec/sinatra/rpc/fault_spec.rb +10 -0
- data/spec/sinatra/rpc/handler/echo_spec.rb +12 -0
- data/spec/sinatra/rpc/handler/introspection_spec.rb +74 -0
- data/spec/sinatra/rpc/helpers_spec.rb +148 -0
- data/spec/sinatra/rpc/serializer/base_spec.rb +50 -0
- data/spec/sinatra/rpc/serializer/xmlrpc_spec.rb +20 -0
- data/spec/sinatra/rpc/serializer_spec.rb +47 -0
- data/spec/sinatra/rpc/utils_spec.rb +166 -0
- data/spec/sinatra/rpc_spec.rb +115 -0
- data/spec/spec_helper.rb +12 -0
- metadata +198 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 8fcab4c48c8b4a2f1ed7b7dfbd1c3671020b1ae9
|
|
4
|
+
data.tar.gz: a7857d2902d7bb8780f36287738e6b11122d157a
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: c17ffccd1215344c8fa82c37a1f02996f42310e8c2e410776e81a4abbfd81c3fa968b5f44da3555c3ca035f2d24e4db67bee843af1b35475de7582ee37ce2f22
|
|
7
|
+
data.tar.gz: cd9e615a3eec9dc3941bcbc842d6b009a64eb45dfcaa4f20d116d9e6ddaed3ab27385d2d2fe863b7065e60f640b2d087a2f73f2748ba667788c0e2d42d837cc2
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.ruby-version
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2.0.0-p247
|
data/.travis.yml
ADDED
data/.yardopts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
--markup=markdown
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Copyright (c) 2014 Andrea Bernardo Ciddio
|
|
2
|
+
|
|
3
|
+
MIT License
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
+
a copy of this software and associated documentation files (the
|
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
11
|
+
the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be
|
|
14
|
+
included in all copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
[](https://travis-ci.org/bcandrea/sinatra-rpc)
|
|
2
|
+
[](https://coveralls.io/r/bcandrea/sinatra-rpc)
|
|
3
|
+
|
|
4
|
+
# Sinatra::Rpc
|
|
5
|
+
|
|
6
|
+
A simple [Sinatra extension module](http://www.sinatrarb.com/extensions.html) providing the functionality of an
|
|
7
|
+
[RPC server](http://wikipedia.org/wiki/Remote_procedure_call).
|
|
8
|
+
|
|
9
|
+
This module allows exposure of all the public methods of any object via RPC. The only supported serialization
|
|
10
|
+
method is [XML-RPC](http://wikipedia.org/wiki/XML-RPC) at the moment.
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
Add this line to your application's Gemfile:
|
|
15
|
+
|
|
16
|
+
gem 'sinatra-rpc'
|
|
17
|
+
|
|
18
|
+
And then execute:
|
|
19
|
+
|
|
20
|
+
$ bundle
|
|
21
|
+
|
|
22
|
+
Or install it yourself as:
|
|
23
|
+
|
|
24
|
+
$ gem install sinatra-rpc
|
|
25
|
+
|
|
26
|
+
## Usage
|
|
27
|
+
|
|
28
|
+
### Minimal example
|
|
29
|
+
|
|
30
|
+
The most basic example involves the definition of a _handler_ class first:
|
|
31
|
+
|
|
32
|
+
```ruby
|
|
33
|
+
class MyHandler
|
|
34
|
+
# A greeting method.
|
|
35
|
+
# @param people [String] the people to greet
|
|
36
|
+
# @return [String] the greeting
|
|
37
|
+
def hello(people)
|
|
38
|
+
"Hello, #{people}!"
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
The class does not need to include any module or implement a specific API; however, its methods need to be
|
|
44
|
+
properly documented (following the [YARD](http://yardoc.org) conventions) to take advantage of the built-in
|
|
45
|
+
introspection (more on that later).
|
|
46
|
+
|
|
47
|
+
Once the handler is defined, it can be added to a standard Sinatra application by registering the
|
|
48
|
+
`Sinatra::RPC` extension.
|
|
49
|
+
|
|
50
|
+
```ruby
|
|
51
|
+
require 'spec_helper'
|
|
52
|
+
require 'sinatra/base'
|
|
53
|
+
|
|
54
|
+
class MyApp < Sinatra::Base
|
|
55
|
+
register Sinatra::RPC
|
|
56
|
+
add_rpc_handler MyHandler
|
|
57
|
+
|
|
58
|
+
post '/RPC2' do
|
|
59
|
+
handle_rpc request
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
This application class will respond to XMLRPC POST requests sent to the '/RPC2' path. It can be easily tested
|
|
65
|
+
with the Ruby [built-in XMLRPC client](http://www.ruby-doc.org/stdlib/libdoc/xmlrpc/rdoc/XMLRPC/Client.html):
|
|
66
|
+
|
|
67
|
+
```ruby
|
|
68
|
+
require 'xmlrpc/client'
|
|
69
|
+
cli = XMLRPC::Client.new_from_uri 'http://myserver/RPC2'
|
|
70
|
+
cli.http_header_extra = {"accept-encoding" => "identity"}
|
|
71
|
+
cli.call 'hello', 'World' # => this call should return 'Hello, World!'
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
(the extra header is needed because of a bug in Ruby 2.0.0 and 2.1.0, see https://bugs.ruby-lang.org/issues/8182).
|
|
75
|
+
|
|
76
|
+
### Namespacing and multiple handlers
|
|
77
|
+
|
|
78
|
+
Of course multiple objects can be registered as handlers. The `add_rpc_handler` method takes an optional
|
|
79
|
+
namespace parameter that can be used to group and organize them.
|
|
80
|
+
|
|
81
|
+
```ruby
|
|
82
|
+
require 'spec_helper'
|
|
83
|
+
require 'sinatra/base'
|
|
84
|
+
|
|
85
|
+
class MyApp < Sinatra::Base
|
|
86
|
+
register Sinatra::RPC
|
|
87
|
+
add_rpc_handler MyHandler
|
|
88
|
+
add_rpc_handler 'customHandler', CustomHandlerClass.new(:some_argument)
|
|
89
|
+
|
|
90
|
+
post '/RPC2' do
|
|
91
|
+
handle_rpc request
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
As you can see, handler instances can be passed as well as classes.
|
|
97
|
+
|
|
98
|
+
### Echo server and introspection
|
|
99
|
+
|
|
100
|
+
The RPC server implements the commonly adopted introspection interface for XML-RPC: the `system.listMethods`,
|
|
101
|
+
`system.methodHelp` and `system.methodSignature` methods are automatically available. The metadata is only extracted
|
|
102
|
+
from the YARD-style comments in the handler classes, so expect inaccurate results if the code is not completely
|
|
103
|
+
documented.
|
|
104
|
+
|
|
105
|
+
Another facility is a simple `test.echo` method, which just return the passed argument.
|
|
106
|
+
|
|
107
|
+
## Contributing
|
|
108
|
+
|
|
109
|
+
1. Fork it
|
|
110
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
111
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
|
112
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
|
113
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/lib/sinatra/rpc.rb
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
require "sinatra/rpc/version"
|
|
2
|
+
require "sinatra/rpc/helpers"
|
|
3
|
+
require "sinatra/rpc/fault"
|
|
4
|
+
require "sinatra/rpc/handler/echo"
|
|
5
|
+
require "sinatra/rpc/handler/introspection"
|
|
6
|
+
|
|
7
|
+
module Sinatra
|
|
8
|
+
# This extension provides the functionality of an RPC server.
|
|
9
|
+
# The resulting server will handle all POST requests to /RPC2 and dispatch methods
|
|
10
|
+
# to the underlying handler objects. For example, calling the 'myHandler.myMethod'
|
|
11
|
+
# method will actually execute
|
|
12
|
+
#
|
|
13
|
+
# my_handler.my_method
|
|
14
|
+
#
|
|
15
|
+
# on the target handler. RPC methods are usually camelcased, so an automatic
|
|
16
|
+
# conversion to and from standard method names with underscores is performed at registration.
|
|
17
|
+
#
|
|
18
|
+
# @example Application class
|
|
19
|
+
# require "sinatra/base"
|
|
20
|
+
# require "sinatra/rpc"
|
|
21
|
+
#
|
|
22
|
+
# class MyApp < Sinatra::Base
|
|
23
|
+
# register Sinatra::RPC
|
|
24
|
+
#
|
|
25
|
+
# # Map custom error codes to Ruby exceptions: this will
|
|
26
|
+
# # generate a class named SomeErrorFault
|
|
27
|
+
# register_rpc_fault :some_error, 399
|
|
28
|
+
#
|
|
29
|
+
# # Add a new sub-handler in the 'myHandler' namespace
|
|
30
|
+
# add_rpc_handler 'myHandler', MyHandlerClass.new(1, 2, 3, 4)
|
|
31
|
+
#
|
|
32
|
+
# # The class name is enough if there is a no-arg constructor
|
|
33
|
+
# add_rpc_handler 'otherHandler', OtherHandler
|
|
34
|
+
#
|
|
35
|
+
# # If the handler namespace is omitted, all the methods are added directly
|
|
36
|
+
# # to the server (empty) namespace
|
|
37
|
+
# add_rpc_handler MyDefaultRPCHandler
|
|
38
|
+
#
|
|
39
|
+
# # Define the RPC endpoint (it must be a POST request)
|
|
40
|
+
# post '/RPC2' do
|
|
41
|
+
# handle_rpc(request)
|
|
42
|
+
# end
|
|
43
|
+
# end
|
|
44
|
+
module RPC
|
|
45
|
+
|
|
46
|
+
# (see Fault.register)
|
|
47
|
+
# @example
|
|
48
|
+
# require "sinatra/base"
|
|
49
|
+
# require "sinatra/rpc"
|
|
50
|
+
#
|
|
51
|
+
# class MyApp < Sinatra::Base
|
|
52
|
+
# register Sinatra::RPC
|
|
53
|
+
# register_rpc_fault :some_error, 399
|
|
54
|
+
# end
|
|
55
|
+
def register_rpc_fault(fault_name, error_code)
|
|
56
|
+
Fault.register fault_name, error_code
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Add a new RPC handler object. If specified, the namespace is used as a
|
|
60
|
+
# prefix for all the RPC method calls. All the public methods exposed by the
|
|
61
|
+
# handler object will be made available as RPC methods (with a camelcase name).
|
|
62
|
+
#
|
|
63
|
+
# @param namespace [String] the (optional) namespace for all the exposed methods
|
|
64
|
+
# @param handler [Object, Class] a handler instance, or its class (if a no-arg
|
|
65
|
+
# constructor is available)
|
|
66
|
+
# @example
|
|
67
|
+
# require "sinatra/base"
|
|
68
|
+
# require "sinatra/rpc"
|
|
69
|
+
#
|
|
70
|
+
# class MyApp < Sinatra::Base
|
|
71
|
+
# register Sinatra::RPC
|
|
72
|
+
# add_rpc_handler 'list', MyListInterface
|
|
73
|
+
# add_rpc_handler BaseObject.new(some_status)
|
|
74
|
+
# end
|
|
75
|
+
def add_rpc_handler(namespace = nil, handler)
|
|
76
|
+
handler = handler.new if Class === handler
|
|
77
|
+
settings.rpc_method_index.merge! Utils.rpc_methods namespace, handler
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# A custom exception raised when a call is made to a non-existent handler or
|
|
81
|
+
# method.
|
|
82
|
+
class NotFound < RuntimeError; end
|
|
83
|
+
|
|
84
|
+
# Callback executed when the app registers this extension module. Here we set
|
|
85
|
+
# the default property values and register standard error codes and handlers.
|
|
86
|
+
def self.registered(app)
|
|
87
|
+
app.helpers Helpers
|
|
88
|
+
|
|
89
|
+
# Initialize the method index
|
|
90
|
+
app.set(:rpc_method_index, {})
|
|
91
|
+
|
|
92
|
+
# Register the echo handler class
|
|
93
|
+
app.add_rpc_handler 'test', Handler::Echo
|
|
94
|
+
|
|
95
|
+
# Register the introspection handler class
|
|
96
|
+
app.add_rpc_handler 'system', Handler::Introspection.new(app)
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
require "sinatra/rpc/utils"
|
|
2
|
+
module Sinatra
|
|
3
|
+
module RPC
|
|
4
|
+
|
|
5
|
+
# This module is used to generate all custom RPC errors.
|
|
6
|
+
module Fault
|
|
7
|
+
# Generate a new fault class. The class will be a subclass of RuntimeError,
|
|
8
|
+
# and always include the Fault module.
|
|
9
|
+
#
|
|
10
|
+
# @param fault_name [String, Symbol] An identifier for the fault; if
|
|
11
|
+
# the name is e.g. 'bad_request', a new class named BadRequestFault
|
|
12
|
+
# is generated
|
|
13
|
+
# @param error_code [Integer] A unique numeric code for this fault
|
|
14
|
+
# @example
|
|
15
|
+
# Sinatra::RPC::Fault.register :bad_request, 400
|
|
16
|
+
# Sinatra::RPC::BadRequestFault::CODE # => 400
|
|
17
|
+
# raise Sinatra::RPC::BadRequestFault, "Bad request"
|
|
18
|
+
# RuntimeError === Sinatra::RPC::BadRequestFault.new # => true
|
|
19
|
+
# Sinatra::RPC::Fault === Sinatra::RPC::BadRequestFault.new # => true
|
|
20
|
+
def self.register(fault_name, error_code)
|
|
21
|
+
fault_class = Class.new(RuntimeError) do
|
|
22
|
+
include Sinatra::RPC::Fault
|
|
23
|
+
def code
|
|
24
|
+
self.class.const_get 'CODE'
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
fault_class.const_set 'CODE', error_code
|
|
29
|
+
|
|
30
|
+
class_name = "#{Sinatra::RPC::Utils.camelize fault_name}Fault"
|
|
31
|
+
Sinatra::RPC.const_set(class_name, fault_class)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Register some generic fault codes (can be overridden)
|
|
35
|
+
register :generic, -1
|
|
36
|
+
register :bad_request, 100
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module Sinatra
|
|
2
|
+
module RPC
|
|
3
|
+
module Handler
|
|
4
|
+
# A simple test handler. Its only purpose is to provide a method that
|
|
5
|
+
# returns the passed string.
|
|
6
|
+
class Echo
|
|
7
|
+
|
|
8
|
+
# A simple echo method. It returns the passed string.
|
|
9
|
+
# @param object [String] the string to return
|
|
10
|
+
# @return [String] the string itself
|
|
11
|
+
def echo(string)
|
|
12
|
+
string
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
module Sinatra
|
|
2
|
+
module RPC
|
|
3
|
+
module Handler
|
|
4
|
+
# The instrospection handler can be used to display metadata about the
|
|
5
|
+
# RPC server. It adds the `listMethods`, `methodSignature` and `methodHelp` RPC methods to
|
|
6
|
+
# the `system` namespace.
|
|
7
|
+
class Introspection
|
|
8
|
+
|
|
9
|
+
# The initializer requires a reference the current application.
|
|
10
|
+
#
|
|
11
|
+
# @param app [Sinatra::Base] the current Sinatra application
|
|
12
|
+
def initialize(app)
|
|
13
|
+
@app = app
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# List the available methods.
|
|
17
|
+
# @return [Array] the array of methods exposed by this RPC server.
|
|
18
|
+
def list_methods
|
|
19
|
+
index.keys.sort
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Return the signature of the given method.
|
|
23
|
+
# @param method_name [String] the method name in the form `handler.methodName`.
|
|
24
|
+
# @return [Array] a list of the form [return, param1, param2, ...].
|
|
25
|
+
def method_signature(method_name)
|
|
26
|
+
index[method_name][:signature]
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Return a help for the given method.
|
|
30
|
+
# @param method_name [String] the method name in the form `handler.methodName`.
|
|
31
|
+
# @return [String] a description of the method.
|
|
32
|
+
def method_help(method_name)
|
|
33
|
+
index[method_name][:help]
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
def index
|
|
39
|
+
@app.settings.rpc_method_index
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
require 'sinatra/rpc/serializer'
|
|
2
|
+
module Sinatra
|
|
3
|
+
module RPC
|
|
4
|
+
# Some methods to include in the app class.
|
|
5
|
+
module Helpers
|
|
6
|
+
|
|
7
|
+
# Generate a serializer instance suitable for the incoming RPC request.
|
|
8
|
+
# (see Sinatra::RPC::Serializer.find)
|
|
9
|
+
def select_serializer(content_type)
|
|
10
|
+
Sinatra::RPC::Serializer.find(content_type).new
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Execute an RPC method with the given name and arguments.
|
|
14
|
+
#
|
|
15
|
+
# @param method [String] the RPC method name, e.g. 'system.listMethods'
|
|
16
|
+
# @param arguments [Array] the list of arguments
|
|
17
|
+
# @return [Object] the return value of the method call on the target handler
|
|
18
|
+
def call_rpc_method(method, arguments)
|
|
19
|
+
m = settings.rpc_method_index[method]
|
|
20
|
+
raise Sinatra::RPC::NotFound if m.nil?
|
|
21
|
+
m[:handler].send m[:method], *arguments
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Handle RPC requests. This method should be called inside a POST definition.
|
|
25
|
+
# @param request the incoming HTTP request object
|
|
26
|
+
# @example
|
|
27
|
+
# class MyApp < Sinatra:Base
|
|
28
|
+
# register Sinatra::RPC
|
|
29
|
+
# add_rpc_handler MyHandlerClass
|
|
30
|
+
#
|
|
31
|
+
# post '/RPC2' do
|
|
32
|
+
# handle_rpc(request)
|
|
33
|
+
# end
|
|
34
|
+
# end
|
|
35
|
+
def handle_rpc(request)
|
|
36
|
+
# The request/response serializer can be XML-RPC (the default)
|
|
37
|
+
# or any serializer implemented as a subclass of Sinatra::RPC::Serializer::Base.
|
|
38
|
+
# The serializer class is chosen by reading the 'Content-Type' header in the request.
|
|
39
|
+
serializer = select_serializer(request.env['CONTENT_TYPE'])
|
|
40
|
+
|
|
41
|
+
body = request.body.read
|
|
42
|
+
|
|
43
|
+
# An empty request is not acceptable in RPC.
|
|
44
|
+
if body.empty?
|
|
45
|
+
halt 400
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Generate the response.
|
|
49
|
+
resp = begin
|
|
50
|
+
# Parse the contents of the request.
|
|
51
|
+
method, arguments = serializer.parse body
|
|
52
|
+
|
|
53
|
+
# Execute the method call.
|
|
54
|
+
call_rpc_method(method, arguments)
|
|
55
|
+
rescue Sinatra::RPC::NotFound
|
|
56
|
+
halt 404
|
|
57
|
+
rescue Sinatra::RPC::Fault => ex
|
|
58
|
+
ex
|
|
59
|
+
rescue ArgumentError => ex
|
|
60
|
+
Sinatra::RPC::BadRequestFault.new(ex.message)
|
|
61
|
+
rescue Exception => ex
|
|
62
|
+
Sinatra::RPC::GenericFault.new("#{ex.class.name}: #{ex.message}")
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
content_type(serializer.content_type, serializer.content_type_options)
|
|
66
|
+
serializer.dump(resp)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|