rack-json_parser 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d50763e213f11a75f3c2c990b6ed9eb76eb0e4a1
4
+ data.tar.gz: 16a9d5f905b50f2aa5773bfa9c77cf94987b1a42
5
+ SHA512:
6
+ metadata.gz: bd11e5fb0a4e8bafb6e704699ac07327c284bdbff81b52bc6649f0b059bcfade3c370b0eec609822da86b05ddc853e4abe2911010be3ac76063274c2240e6eb4
7
+ data.tar.gz: 298beff0f18a69fab3ff1d240cbdb158bf9cf97d45133ca9922825fc24568a0d1ae454b8f59c1e6a2a41ac189d1d46f04fb56f6d80709e0f21f3c221194f4658
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+
11
+ # rspec failure tracking
12
+ .rspec_status
13
+
14
+ # bundler
15
+ /vendor/bundle/
16
+
17
+ # log dir
18
+ /log/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.rubocop.yml ADDED
@@ -0,0 +1,6 @@
1
+ require: rubocop-rspec
2
+
3
+ Metrics/BlockLength:
4
+ Exclude:
5
+ - 'spec/**/*.rb'
6
+ - '*.gemspec'
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.3.1
data/.simplecov ADDED
@@ -0,0 +1,9 @@
1
+ unless ARGV.any? { |e| e =~ /guard-rspec/ }
2
+ SimpleCov.start do
3
+ coverage_dir 'log/coverage'
4
+ formatter SimpleCov::Formatter::HTMLFormatter
5
+
6
+ command_name 'rspec'
7
+ maximum_coverage_drop 1
8
+ end
9
+ end
data/.travis.yml ADDED
@@ -0,0 +1,10 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.3.1
5
+ addons:
6
+ code_climate:
7
+ repo_token: b6750d5cc830de5ca5da5f6ba3c95b7129924f36b6c572e1a38301892b241e2a
8
+ before_install: gem install bundler -v 1.12.5
9
+ after_success:
10
+ - bundle exec codeclimate-test-reporter log/coverage/.resultset.json
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+ source 'https://rubygems.org'
3
+
4
+ # Specify your gem's dependencies in log_syringe.gemspec
5
+ gemspec
6
+
7
+ group :development do
8
+ gem 'codeclimate-test-reporter', github: 'codeclimate/ruby-test-reporter'
9
+ end
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 MESO Digital Services GmbH
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all 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,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,56 @@
1
+ # Rack::JsonParser
2
+
3
+ [![Travis CI](https://travis-ci.org/meso-unimpressed/rack-json_parser.svg?branch=master)](https://travis-ci.org/meso-unimpressed/rack-json_parser)
4
+ [![Code Climate](https://codeclimate.com/github/meso-unimpressed/rack-json_parser/badges/gpa.svg)](https://codeclimate.com/github/meso-unimpressed/rack-json_parser)
5
+ [![Test Coverage](https://codeclimate.com/github/meso-unimpressed/rack-json_parser/badges/coverage.svg)](https://codeclimate.com/github/meso-unimpressed/rack-json_parser/coverage)
6
+ [![Issue Count](https://codeclimate.com/github/meso-unimpressed/rack-json_parser/badges/issue_count.svg)](https://codeclimate.com/github/meso-unimpressed/rack-json_parser)
7
+
8
+ A simple Rack middleware for parsing json from request bodies
9
+
10
+ ## Installation
11
+
12
+ Add this line to your application's Gemfile:
13
+
14
+ ```ruby
15
+ gem 'rack-json_parser'
16
+ ```
17
+
18
+ And then execute:
19
+
20
+ $ bundle
21
+
22
+ Or install it yourself as:
23
+
24
+ $ gem install rack-json_parser
25
+
26
+ ## Usage
27
+
28
+ ```ruby
29
+ # config.ru
30
+
31
+ use MyErrorHandler
32
+ use Rack::JSONParser, content_type: 'application/json'
33
+ run MyApp
34
+ ```
35
+
36
+ The named param `content_type` is optional and defaults to `application/json`
37
+ you can use arrays, regexes or arrays of regexes here. Anything really which
38
+ will evaluate to true when using the case operator `===` against the request
39
+ content type.
40
+
41
+ ## Development
42
+
43
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run
44
+ `rake spec` to run the tests. You can also run `bin/console` for an interactive
45
+ prompt that will allow you to experiment.
46
+
47
+ To install this gem onto your local machine, run `bundle exec rake install`. To
48
+ release a new version, update the version number in `version.rb`, and then run
49
+ `bundle exec rake release`, which will create a git tag for the version, push
50
+ git commits and tags, and push the `.gem` file to
51
+ [rubygems.org](https://rubygems.org).
52
+
53
+ ## Contributing
54
+
55
+ Bug reports and pull requests are welcome on GitHub at
56
+ [meso-unimpressed/rack-json_parser](https://github.com/meso-unimpressed/rack-json_parser).
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+ require 'bundler/gem_tasks'
3
+ require 'rspec/core/rake_task'
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task default: :spec
data/bin/console ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler/setup'
5
+ require 'rack/json_parser'
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require "pry"
12
+ # Pry.start
13
+
14
+ require 'irb'
15
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+ require 'json'
3
+ require 'rack'
4
+
5
+ require 'rack/json_parser/version'
6
+ require 'rack/json_parser/bad_request'
7
+ require 'rack/json_parser/unprocessable_entity'
8
+
9
+ module Rack
10
+ # Parses JSON body of requests and handles errors
11
+ class JSONParser
12
+ # An error indicatating that parsing the json body failed
13
+ class ParseError < BadRequest
14
+ def initialize(error)
15
+ super("parsing json failed: #{error.message}")
16
+ end
17
+ end
18
+
19
+ # An error raised if body is nil or empty
20
+ class EmptyBodyError < BadRequest
21
+ def initialize
22
+ super('cannot process empty body')
23
+ end
24
+ end
25
+
26
+ # An error raised on invalid content types
27
+ class InvalidContentTypeError < BadRequest
28
+ def initialize(content_type)
29
+ super("cannot process content type #{content_type}")
30
+ end
31
+ end
32
+
33
+ # An error raised if the top level of the json document is not a hash
34
+ class NotAnObjectError < UnprocessableEntity
35
+ def initialize
36
+ super("document's top level must be an object")
37
+ end
38
+ end
39
+
40
+ def initialize(app, content_type: 'application/json')
41
+ @app = app
42
+ @content_type = content_type
43
+ end
44
+
45
+ def call(env)
46
+ parse(env) if should_have_body?(env)
47
+ @app.call(env)
48
+ end
49
+
50
+ private
51
+
52
+ def should_have_body?(env)
53
+ env.key?('CONTENT_LENGTH')
54
+ end
55
+
56
+ def parse(env)
57
+ request = Rack::Request.new(env)
58
+ body = request.body.read
59
+ request.body.rewind
60
+ validate_request!(request, body)
61
+
62
+ parsed_body = JSON.parse(body)
63
+ raise NotAnObjectError unless parsed_body.is_a?(Hash)
64
+
65
+ env['rack.request.form_input'] = request.body
66
+ env['rack.request.form_hash'] = parsed_body
67
+ rescue JSON::ParserError => error
68
+ raise ParseError, error
69
+ end
70
+
71
+ def validate_request!(request, body)
72
+ validate_body!(body)
73
+ validate_content_type!(request)
74
+ end
75
+
76
+ def validate_body!(body)
77
+ raise EmptyBodyError if body.nil? || body.empty?
78
+ end
79
+
80
+ def validate_content_type!(request)
81
+ content_type = request.content_type
82
+
83
+ case content_type
84
+ when *@content_type then true
85
+ else raise InvalidContentTypeError, content_type
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+ require 'rack/json_parser/error'
3
+
4
+ module Rack
5
+ class JSONParser
6
+ # A error signaling that the application should respond with bad request
7
+ class BadRequest < Error
8
+ def initialize(detail)
9
+ super('Bad request', detail: detail, status_code: 400)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+ module Rack
3
+ class JSONParser
4
+ # Base class for all JSONParser errors
5
+ class Error < RuntimeError
6
+ attr_reader :status_code, :title, :detail
7
+
8
+ def initialize(title, detail: nil, status_code: 500)
9
+ @status_code = status_code
10
+ @title = title
11
+ @detail = detail
12
+
13
+ super([title, detail].compact.join(' - '))
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+ require 'rack/json_parser/error'
3
+
4
+ module Rack
5
+ class JSONParser
6
+ # A error signaling that the application should respond with
7
+ # unprocessable entity
8
+ class UnprocessableEntity < Error
9
+ def initialize(detail)
10
+ super('UnprocessableEntity', detail: detail, status_code: 422)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+ module Rack
3
+ class JSONParser
4
+ VERSION = '0.1.0'
5
+ end
6
+ end
@@ -0,0 +1,33 @@
1
+ # coding: utf-8
2
+ # frozen_string_literal: true
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'rack/json_parser/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'rack-json_parser'
9
+ spec.version = Rack::JSONParser::VERSION
10
+ spec.authors = ['Joakim Reinert']
11
+ spec.email = ['reinert@meso.net']
12
+
13
+ spec.summary = 'A tiny rack middleware for parsing json request bodies'
14
+ spec.description =
15
+ 'Provides a middleware for parsing json from request bodies to be ' \
16
+ 'accessed from request params'
17
+ spec.homepage = 'https://github.com/meso-unimpressed/rack-json_parser'
18
+
19
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
20
+ f.match(%r{^spec/})
21
+ end
22
+ spec.require_paths = ['lib']
23
+
24
+ spec.add_development_dependency 'bundler', '~> 1.14'
25
+ spec.add_development_dependency 'rake', '~> 10.0'
26
+ spec.add_development_dependency 'rspec', '~> 3.0'
27
+ spec.add_development_dependency 'rubocop', '~> 0.4'
28
+ spec.add_development_dependency 'rubocop-rspec', '~> 1.1'
29
+ spec.add_development_dependency 'simplecov', '~> 0.1'
30
+ spec.add_development_dependency 'codeclimate-test-reporter', '~> 1.0'
31
+
32
+ spec.add_dependency 'rack', '~> 2.0'
33
+ end
metadata ADDED
@@ -0,0 +1,174 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rack-json_parser
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Joakim Reinert
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-02-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.14'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.14'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubocop
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.4'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.4'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rubocop-rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.1'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.1'
83
+ - !ruby/object:Gem::Dependency
84
+ name: simplecov
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0.1'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '0.1'
97
+ - !ruby/object:Gem::Dependency
98
+ name: codeclimate-test-reporter
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '1.0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '1.0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rack
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '2.0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '2.0'
125
+ description: Provides a middleware for parsing json from request bodies to be accessed
126
+ from request params
127
+ email:
128
+ - reinert@meso.net
129
+ executables: []
130
+ extensions: []
131
+ extra_rdoc_files: []
132
+ files:
133
+ - ".gitignore"
134
+ - ".rspec"
135
+ - ".rubocop.yml"
136
+ - ".ruby-version"
137
+ - ".simplecov"
138
+ - ".travis.yml"
139
+ - Gemfile
140
+ - LICENSE
141
+ - README.md
142
+ - Rakefile
143
+ - bin/console
144
+ - bin/setup
145
+ - lib/rack/json_parser.rb
146
+ - lib/rack/json_parser/bad_request.rb
147
+ - lib/rack/json_parser/error.rb
148
+ - lib/rack/json_parser/unprocessable_entity.rb
149
+ - lib/rack/json_parser/version.rb
150
+ - rack-json_parser.gemspec
151
+ homepage: https://github.com/meso-unimpressed/rack-json_parser
152
+ licenses: []
153
+ metadata: {}
154
+ post_install_message:
155
+ rdoc_options: []
156
+ require_paths:
157
+ - lib
158
+ required_ruby_version: !ruby/object:Gem::Requirement
159
+ requirements:
160
+ - - ">="
161
+ - !ruby/object:Gem::Version
162
+ version: '0'
163
+ required_rubygems_version: !ruby/object:Gem::Requirement
164
+ requirements:
165
+ - - ">="
166
+ - !ruby/object:Gem::Version
167
+ version: '0'
168
+ requirements: []
169
+ rubyforge_project:
170
+ rubygems_version: 2.5.1
171
+ signing_key:
172
+ specification_version: 4
173
+ summary: A tiny rack middleware for parsing json request bodies
174
+ test_files: []