temescal 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +20 -0
- data/README.md +53 -0
- data/Rakefile +5 -0
- data/lib/temescal.rb +6 -0
- data/lib/temescal/configuration.rb +54 -0
- data/lib/temescal/middleware.rb +55 -0
- data/lib/temescal/monitors.rb +35 -0
- data/lib/temescal/response.rb +25 -0
- data/lib/temescal/version.rb +3 -0
- data/spec/lib/temescal/configuration_spec.rb +25 -0
- data/spec/lib/temescal/middleware_spec.rb +112 -0
- data/spec/lib/temescal/monitors_spec.rb +29 -0
- data/spec/spec_helper.rb +29 -0
- data/temescal.gemspec +22 -0
- metadata +86 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 668a0e9c9bb3d5400a4b9b28302607767828bc0c
|
4
|
+
data.tar.gz: 1f1a62d3e48d5db8cd32b853a06ea116be8a3b69
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 614f71816ca80c27852abe47a8aef37702fc8eced6143613ed25735dd1bc3bc051a7e9d4f4dd1eefb1709aedc6537191354abaab13a837cc57bbc70469f91564
|
7
|
+
data.tar.gz: 1bf5f51abe2f31d8e2cd7b8595f97c4d6a86083f99d34f1d800e7e96495de41bae2017b62ec1bb6b7f1ced4a8ccf4fd04062b7c7ea7edde87484a2fd3c0799e9
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2013-2014 Todd Bealmear
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
7
|
+
the Software without restriction, including without limitation the rights to
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
10
|
+
subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
temescal
|
2
|
+
========
|
3
|
+
|
4
|
+
[![Build Status](https://travis-ci.org/todd/temescal.png?branch=master)](https://travis-ci.org/todd/temescal) [![Coverage Status](https://coveralls.io/repos/todd/temescal/badge.png?branch=master)](https://coveralls.io/r/todd/temescal?branch=master) [![Code Climate](https://codeclimate.com/github/todd/temescal.png)](https://codeclimate.com/github/todd/temescal) [![Dependency Status](https://gemnasium.com/todd/temescal.png)](https://gemnasium.com/todd/temescal)
|
5
|
+
|
6
|
+
Temescal is Rack middleware that will automatically rescue exceptions for JSON APIs and render a nice, clean JSON response with the error information. No need to write custom error handling logic for your apps - Temescal will take care of it for you!
|
7
|
+
## Getting Started
|
8
|
+
Add the gem to your Gemfile and run `bundle install`:
|
9
|
+
```
|
10
|
+
gem 'temescal'
|
11
|
+
```
|
12
|
+
Since Temescal is just Rack middleware, adding it to your application is super easy. For Rails, add an initializer:
|
13
|
+
```ruby
|
14
|
+
Rails.application.config.middleware.use Temescal::Middleware do |config|
|
15
|
+
config.monitors = :airbrake, :new_relic
|
16
|
+
config.default_message = "Oops! Something went kablooey!"
|
17
|
+
end
|
18
|
+
```
|
19
|
+
For Sinatra:
|
20
|
+
```ruby
|
21
|
+
use Temescal::Middleware do |config|
|
22
|
+
config.monitors = :airbrake, :new_relic
|
23
|
+
config.default_message = "Oops! Something went kablooey!"
|
24
|
+
end
|
25
|
+
```
|
26
|
+
## Default Behavior
|
27
|
+
By default, Temescal will render a JSON response formatted as such (using StandardError with a message of "Foobar" as an example):
|
28
|
+
```json
|
29
|
+
{
|
30
|
+
meta: {
|
31
|
+
status: 500,
|
32
|
+
error: "StandardError",
|
33
|
+
message: "Foobar"
|
34
|
+
}
|
35
|
+
}
|
36
|
+
```
|
37
|
+
Temescal will also log the error for you through STDERR.
|
38
|
+
## Monitors
|
39
|
+
Though Temescal will log an error for you, it won't necessarily be picked up by your monitoring solution of choice in a production environment. Luckily, Temescal provides integration with popular monitoring services. At the moment, only two (Airbrake, New Relic) are supported, but more will be added if there's a need. If you use a different monitoring service that you'd like to see supported, pull requests are more than welcome!
|
40
|
+
|
41
|
+
Note that you'll need the gem for your monitor installed and configured for your application in order for Temescal to properly work with it.
|
42
|
+
|
43
|
+
## Configuration
|
44
|
+
Temescal provides several configuration options for you. You can set these options when configuring the middleware for your application.
|
45
|
+
|
46
|
+
`monitors` to set the monitors you'd like to use with Temescal. It takes symbols of monitor names (currently `:airbrake` and `:new_relic`).
|
47
|
+
|
48
|
+
`raise_errors` to set whether you'd like to override Temescal and raise all errors without rendering a Temescal response. Set to `true` to enable.
|
49
|
+
|
50
|
+
`default_message` to set an all-encompasing message to use in responses instead of the exception's message. Takes a string.
|
51
|
+
|
52
|
+
## License
|
53
|
+
Copyright 2013-2014 Todd Bealmear. See LICENSE for details.
|
data/Rakefile
ADDED
data/lib/temescal.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
module Temescal
|
2
|
+
class Configuration
|
3
|
+
|
4
|
+
# Public: Getter for monitors array.
|
5
|
+
attr_reader :monitors
|
6
|
+
|
7
|
+
# Public: Setter for raise_errors option.
|
8
|
+
attr_writer :raise_errors
|
9
|
+
|
10
|
+
# Public: Getter/Setter for default JSON message.
|
11
|
+
attr_accessor :default_message
|
12
|
+
|
13
|
+
# Public: Initializes configuration and monitors option.
|
14
|
+
#
|
15
|
+
# Returns a new Configuration object.
|
16
|
+
def initialize
|
17
|
+
@monitors = []
|
18
|
+
end
|
19
|
+
|
20
|
+
# Public: Setter for monitors option.
|
21
|
+
#
|
22
|
+
# monitors - Zero or more Symbols representing monitoring services
|
23
|
+
# supported by Temescal.
|
24
|
+
#
|
25
|
+
# Raises NameError if a monitor Symbol is invalid.
|
26
|
+
def monitors=(*monitors)
|
27
|
+
monitors.flatten.each do |monitor|
|
28
|
+
monitor = camelize_symbol(monitor)
|
29
|
+
@monitors << Temescal::Monitors.const_get(monitor)
|
30
|
+
end
|
31
|
+
|
32
|
+
rescue NameError => exception
|
33
|
+
strategy = exception.message.split(" ").last
|
34
|
+
raise NameError.new("#{strategy} is not a valid monitoring strategy")
|
35
|
+
end
|
36
|
+
|
37
|
+
# Public: Getter for raise_errors.
|
38
|
+
#
|
39
|
+
# Returns true if raise_errors is configured to true or the application is
|
40
|
+
# running in a test environment, false otherwise.
|
41
|
+
def raise_errors?
|
42
|
+
@raise_errors == true || ENV["RACK_ENV"] == "test"
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
# Private: Converts a snake cased Symbol to a camel cased String.
|
48
|
+
#
|
49
|
+
# Returns the converted String.
|
50
|
+
def camelize_symbol(symbol)
|
51
|
+
symbol.to_s.split(/_/).map { |word| word.capitalize }.join
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Temescal
|
2
|
+
class Middleware
|
3
|
+
|
4
|
+
# Public: Initializes the middleware.
|
5
|
+
#
|
6
|
+
# app - The Rack application.
|
7
|
+
# block - Optional block for configuring the middleware.
|
8
|
+
#
|
9
|
+
# Returns an instance of the middleware.
|
10
|
+
def initialize(app, &block)
|
11
|
+
@app = app
|
12
|
+
yield(configuration) if block
|
13
|
+
end
|
14
|
+
|
15
|
+
# Public: call method for Rack application. Rescues from an exception and
|
16
|
+
# does the following: 1) Logs the error 2) Reports error to configured
|
17
|
+
# monitoring services 3) Generates a JSON response with error information.
|
18
|
+
#
|
19
|
+
# env - The environment of the request.
|
20
|
+
#
|
21
|
+
# Returns an array of response data for Rack.
|
22
|
+
def call(env)
|
23
|
+
begin
|
24
|
+
@status, @headers, @response = @app.call(env)
|
25
|
+
rescue => error
|
26
|
+
raise if configuration.raise_errors?
|
27
|
+
|
28
|
+
@error = error
|
29
|
+
message = configuration.default_message || @error.message
|
30
|
+
|
31
|
+
$stderr.print formatted_error
|
32
|
+
configuration.monitors.each { |monitor| monitor.report(@error) }
|
33
|
+
|
34
|
+
@status = @error.respond_to?(:http_status) ? @error.http_status : 500
|
35
|
+
@response = Response.build(@status, @error, message)
|
36
|
+
@headers = { "Content-Type" => "application/json" }
|
37
|
+
end
|
38
|
+
[@status, @headers, @response]
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
# Private: Getter for middleware configuration.
|
44
|
+
def configuration
|
45
|
+
@_configuration ||= Configuration.new
|
46
|
+
end
|
47
|
+
|
48
|
+
# Private: Formats the exception for logging.
|
49
|
+
def formatted_error
|
50
|
+
message = "\n#{@error.class}: #{@error.message}\n "
|
51
|
+
message << @error.backtrace.join("\n ")
|
52
|
+
message << "\n\n"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Temescal
|
2
|
+
|
3
|
+
# Public: Collection of reporting strategies for different monitoring
|
4
|
+
# services.
|
5
|
+
module Monitors
|
6
|
+
|
7
|
+
# Public: Abstract strategy for monitor reporting strategies.
|
8
|
+
class MonitorsStrategy
|
9
|
+
# Raises NotImplementedError
|
10
|
+
def self.report(exception)
|
11
|
+
raise NotImplementedError
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# Public: Reporting strategy for Airbrake.
|
16
|
+
class Airbrake < MonitorsStrategy
|
17
|
+
# Public: Reports an exception to Airbrake.
|
18
|
+
#
|
19
|
+
# exception - The caught exception.
|
20
|
+
def self.report(exception)
|
21
|
+
::Airbrake.notify exception
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Public: Reporting strategy for New Relic.
|
26
|
+
class NewRelic < MonitorsStrategy
|
27
|
+
# Public: Reports an exception to New Relic.
|
28
|
+
#
|
29
|
+
# exception - The caught exception.
|
30
|
+
def self.report(exception)
|
31
|
+
::NewRelic::Agent.notice_error exception
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Temescal
|
4
|
+
module Response
|
5
|
+
|
6
|
+
# Public: Builds a response body for the Rack response.
|
7
|
+
#
|
8
|
+
# status - The HTTP status code of the response.
|
9
|
+
# exception - The caught exception.
|
10
|
+
# message - The error message.
|
11
|
+
#
|
12
|
+
# Returns an Array containing a JSON string as the response body.
|
13
|
+
def self.build(status, exception, message)
|
14
|
+
[
|
15
|
+
{
|
16
|
+
meta: {
|
17
|
+
status: status,
|
18
|
+
error: exception.class.to_s,
|
19
|
+
message: message
|
20
|
+
}
|
21
|
+
}.to_json
|
22
|
+
]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
class Temescal::Monitors::Monitor; end
|
4
|
+
class Temescal::Monitors::FakeMonitor; end
|
5
|
+
class Temescal::Monitors::FooMonitor; end
|
6
|
+
|
7
|
+
describe Temescal::Configuration do
|
8
|
+
let(:config) { Temescal::Configuration.new }
|
9
|
+
|
10
|
+
context "#monitors=" do
|
11
|
+
it "should add a list of valid monitor classes to the monitors array from snake-cased arguments" do
|
12
|
+
config.monitors = :monitor, :fake_monitor, :foo_monitor
|
13
|
+
|
14
|
+
expect(config.monitors).to eq [
|
15
|
+
Temescal::Monitors::Monitor,
|
16
|
+
Temescal::Monitors::FakeMonitor,
|
17
|
+
Temescal::Monitors::FooMonitor
|
18
|
+
]
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should raise an error if a monitor strategy is invalid" do
|
22
|
+
expect { config.monitors = :foo }.to raise_error(NameError, /Foo is not a valid monitoring strategy/)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Temescal::Middleware do
|
4
|
+
context "Ok response" do
|
5
|
+
let(:app) { ->(env) { [200, env, "app" ] } }
|
6
|
+
|
7
|
+
let(:middleware) do
|
8
|
+
Temescal::Middleware.new(app)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should render the application's response" do
|
12
|
+
code, _, _ = middleware.call env_for('http://foobar.com')
|
13
|
+
|
14
|
+
expect(code).to eq 200
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
context "Bad response" do
|
19
|
+
before do
|
20
|
+
Temescal::Monitors::NewRelic.stub(:report)
|
21
|
+
$stderr.stub(:print)
|
22
|
+
|
23
|
+
# Travis automatically sets RACK_ENV=test
|
24
|
+
# Need to override for tests to run correctly.
|
25
|
+
ENV["RACK_ENV"] = nil
|
26
|
+
end
|
27
|
+
|
28
|
+
let(:app) { ->(env) { raise StandardError.new("Foobar") } }
|
29
|
+
|
30
|
+
let(:middleware) do
|
31
|
+
Temescal::Middleware.new(app) do |config|
|
32
|
+
config.monitors = :new_relic
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should respond with a 500 if the exception does not have a http_status attribute" do
|
37
|
+
code, _, _ = middleware.call env_for("http://foobar.com")
|
38
|
+
|
39
|
+
expect(code).to eq 500
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should respond with the appropriate status if the exception has a http_status attribute" do
|
43
|
+
StandardError.any_instance.stub(:http_status).and_return(403)
|
44
|
+
|
45
|
+
code, _, _ = middleware.call env_for("http://foobar.com")
|
46
|
+
|
47
|
+
expect(code).to eq 403
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should set the correct content type header" do
|
51
|
+
_, headers, _ = middleware.call env_for("http://foobar.com")
|
52
|
+
|
53
|
+
expect(headers["Content-Type"]).to eq "application/json"
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should render a JSON response for the error" do
|
57
|
+
_, _, response = middleware.call env_for("http://foobar.com")
|
58
|
+
|
59
|
+
json = JSON.parse(response.first)["meta"]
|
60
|
+
expect(json["status"]).to eq 500
|
61
|
+
expect(json["error"]).to eq "StandardError"
|
62
|
+
expect(json["message"]).to eq "Foobar"
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should log the error" do
|
66
|
+
expect($stderr).to receive(:print).with(an_instance_of String)
|
67
|
+
|
68
|
+
middleware.call env_for("http://foobar.com")
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should report the error to the specified monitors" do
|
72
|
+
expect(Temescal::Monitors::NewRelic).to receive(:report).with(an_instance_of StandardError)
|
73
|
+
|
74
|
+
middleware.call env_for("http://foobar.com")
|
75
|
+
end
|
76
|
+
|
77
|
+
context "with default_message set" do
|
78
|
+
it "should build a response with the specified message instead of the exception message" do
|
79
|
+
middleware = Temescal::Middleware.new(app) do |config|
|
80
|
+
config.default_message = "An error has occured - we'll get on it right away!"
|
81
|
+
end
|
82
|
+
|
83
|
+
_, _, response = middleware.call env_for("http://foobar.com")
|
84
|
+
|
85
|
+
json = JSON.parse(response.first)["meta"]
|
86
|
+
expect(json["message"]).to eq "An error has occured - we'll get on it right away!"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
context "Override middleware to raise exception" do
|
92
|
+
before do
|
93
|
+
$stderr.stub(:print)
|
94
|
+
end
|
95
|
+
|
96
|
+
let(:app) { ->(env) { raise StandardError.new("Foobar") } }
|
97
|
+
|
98
|
+
let(:middleware) do
|
99
|
+
Temescal::Middleware.new(app) do |config|
|
100
|
+
config.raise_errors = true
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should raise the error" do
|
105
|
+
expect { middleware.call env_for("http://foobar.com") }.to raise_error StandardError
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def env_for url, opts={}
|
110
|
+
Rack::MockRequest.env_for(url, opts)
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Temescal::Monitors do
|
4
|
+
let(:exception) { StandardError.new }
|
5
|
+
|
6
|
+
context "MonitorsStrategy" do
|
7
|
+
it "should raise an error when the report method is called" do
|
8
|
+
expect { Temescal::Monitors::MonitorsStrategy.report(exception) }.to raise_error(NotImplementedError)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
context "Airbrake" do
|
13
|
+
it "should send the exception to Airbrake when report is called" do
|
14
|
+
Airbrake.stub(:send_notice)
|
15
|
+
|
16
|
+
expect(Airbrake).to receive(:notify).with(exception)
|
17
|
+
|
18
|
+
Temescal::Monitors::Airbrake.report exception
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context "NewRelic" do
|
23
|
+
it "should send the exception to New Relic when report is called" do
|
24
|
+
expect(NewRelic::Agent).to receive(:notice_error).with(exception)
|
25
|
+
|
26
|
+
Temescal::Monitors::NewRelic.report exception
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
if ENV['CI']
|
2
|
+
require 'coveralls'
|
3
|
+
Coveralls.wear!
|
4
|
+
else
|
5
|
+
require 'awesome_print'
|
6
|
+
require 'pry-debugger'
|
7
|
+
|
8
|
+
require 'simplecov'
|
9
|
+
SimpleCov.start
|
10
|
+
end
|
11
|
+
|
12
|
+
require 'rack'
|
13
|
+
|
14
|
+
require 'airbrake'
|
15
|
+
require 'newrelic_rpm'
|
16
|
+
|
17
|
+
require 'temescal'
|
18
|
+
|
19
|
+
RSpec.configure do |config|
|
20
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
21
|
+
config.run_all_when_everything_filtered = true
|
22
|
+
config.filter_run :focus
|
23
|
+
|
24
|
+
# Run specs in random order to surface order dependencies. If you find an
|
25
|
+
# order dependency and want to debug it, you can fix the order by providing
|
26
|
+
# the seed, which is printed after each run.
|
27
|
+
# --seed 1234
|
28
|
+
config.order = 'random'
|
29
|
+
end
|
data/temescal.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
$:.unshift File.expand_path('../lib', __FILE__)
|
4
|
+
require 'temescal/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.add_dependency 'rack'
|
8
|
+
spec.add_development_dependency 'bundler'
|
9
|
+
|
10
|
+
spec.authors = ['Todd Bealmear']
|
11
|
+
spec.description = %q{Rack Middleware for gracefully handling exceptions for JSON APIs.}
|
12
|
+
spec.email = ['todd@t0dd.io']
|
13
|
+
spec.files = %w(LICENSE README.md Rakefile temescal.gemspec)
|
14
|
+
spec.files += Dir.glob('lib/**/*.rb')
|
15
|
+
spec.files += Dir.glob('spec/**/*')
|
16
|
+
spec.homepage = 'https://github.com/todd/temescal'
|
17
|
+
spec.licenses = ['MIT']
|
18
|
+
spec.name = 'temescal'
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
spec.summary = spec.description
|
21
|
+
spec.version = Temescal::VERSION
|
22
|
+
end
|
metadata
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: temescal
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Todd Bealmear
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-01-13 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rack
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: Rack Middleware for gracefully handling exceptions for JSON APIs.
|
42
|
+
email:
|
43
|
+
- todd@t0dd.io
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- LICENSE
|
49
|
+
- README.md
|
50
|
+
- Rakefile
|
51
|
+
- temescal.gemspec
|
52
|
+
- lib/temescal/configuration.rb
|
53
|
+
- lib/temescal/middleware.rb
|
54
|
+
- lib/temescal/monitors.rb
|
55
|
+
- lib/temescal/response.rb
|
56
|
+
- lib/temescal/version.rb
|
57
|
+
- lib/temescal.rb
|
58
|
+
- spec/lib/temescal/configuration_spec.rb
|
59
|
+
- spec/lib/temescal/middleware_spec.rb
|
60
|
+
- spec/lib/temescal/monitors_spec.rb
|
61
|
+
- spec/spec_helper.rb
|
62
|
+
homepage: https://github.com/todd/temescal
|
63
|
+
licenses:
|
64
|
+
- MIT
|
65
|
+
metadata: {}
|
66
|
+
post_install_message:
|
67
|
+
rdoc_options: []
|
68
|
+
require_paths:
|
69
|
+
- lib
|
70
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - '>='
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - '>='
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '0'
|
80
|
+
requirements: []
|
81
|
+
rubyforge_project:
|
82
|
+
rubygems_version: 2.1.10
|
83
|
+
signing_key:
|
84
|
+
specification_version: 4
|
85
|
+
summary: Rack Middleware for gracefully handling exceptions for JSON APIs.
|
86
|
+
test_files: []
|