rack-json_response_wrapper 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 1b045582186350a205ba09cd1b9ef961283d4bda
4
+ data.tar.gz: 1bab96a3396b352f8c8149180a1b00da138aa996
5
+ SHA512:
6
+ metadata.gz: 8ec0543023c93957f5f78e54a78d674dda6cc98fe432f6fa69f0d15d7c1f6eaaab937be283a6fe5f44e13ba9790c61caa6679ba637d932e669f2e2daab7e4040
7
+ data.tar.gz: e21ce554077dc7f3e4c94c27e93f92bdaf9a765743c2b77ee013d3709009fce5a6d04034956f4d0fbfb92c6d9a736c3d5f3852f2a4faf6f6ce4fff250147b630
data/LICENSE ADDED
@@ -0,0 +1,24 @@
1
+ This is free and unencumbered software released into the public domain.
2
+
3
+ Anyone is free to copy, modify, publish, use, compile, sell, or
4
+ distribute this software, either in source code form or as a compiled
5
+ binary, for any purpose, commercial or non-commercial, and by any
6
+ means.
7
+
8
+ In jurisdictions that recognize copyright laws, the author or authors
9
+ of this software dedicate any and all copyright interest in the
10
+ software to the public domain. We make this dedication for the benefit
11
+ of the public at large and to the detriment of our heirs and
12
+ successors. We intend this dedication to be an overt act of
13
+ relinquishment in perpetuity of all present and future rights to this
14
+ software under copyright law.
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 NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20
+ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+ For more information, please refer to <http://unlicense.org/>
@@ -0,0 +1,17 @@
1
+ rack-json_response_wrapper
2
+ ==========================
3
+
4
+ Rack Middleware for JSON APIs accessed cross-domain from legacy browsers
5
+
6
+ Firefox version 4 does not support response headers for cross-domain requests. This middleware intercepts all requests and if the X-WRAP-RESPONSE is set, the response will be wrappped in JSON as follows:
7
+
8
+ Suppose the following is the original response body:
9
+
10
+ {"key": "value"}
11
+
12
+ With X-WRAP-RESPONSE set to true, the new response will be:
13
+
14
+ {
15
+ "header": { ... bunch of headers ... },
16
+ "body": {"key": "value"}
17
+ }
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "bundler/setup"
3
+
4
+ task default: [:spec]
5
+
6
+ desc 'run rspec specs'
7
+ task :spec do
8
+ ENV['RACK_ENV'] ||= 'test'
9
+ sh 'rspec'
10
+ end
@@ -0,0 +1,62 @@
1
+ module Rack
2
+ class JsonResponseWrapper
3
+ def initialize(app)
4
+ @app = app
5
+ end
6
+
7
+ def call(env)
8
+ response = @app.call(env)
9
+
10
+ if should_wrap? env, response
11
+ wrap_response(response)
12
+ else
13
+ response
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def should_wrap?(env, response)
20
+ response_header = response[1]
21
+
22
+ is_json = response_header['Content-Type'].match(/application\/json/)
23
+ wants_wrap = env.include? 'X-WRAP-RESPONSE'
24
+
25
+ is_json && wants_wrap
26
+ end
27
+
28
+ def wrap_response(response)
29
+ response_body = response[2].reduce(&:concat)
30
+ response_header = response[1]
31
+
32
+ response_obj = JSON.parse(response_body)
33
+
34
+ wrapped_obj = {
35
+ header: response_header,
36
+ body: response_obj
37
+ }
38
+
39
+ # dump JSON to get new content length
40
+ wrapped_body = JSON.dump(wrapped_obj)
41
+
42
+ # when we change the content-length, the length will change.
43
+ # therefore, calculate the offset by comparing the length of the old vs. new
44
+ original_content_length = response_header['Content-Length']
45
+ new_content_length = wrapped_body.length
46
+ adjusted_content_length =
47
+ new_content_length.to_s.to_json.length - original_content_length.to_s.to_json.length
48
+
49
+ # adjust the new content-length by this offset
50
+ new_content_length += adjusted_content_length
51
+
52
+ # set the content length part of the header and redump the JSON
53
+ wrapped_obj[:header]['Content-Length'] = new_content_length.to_s
54
+ wrapped_body = JSON.dump(wrapped_obj)
55
+
56
+ wrapped = response.dup
57
+ wrapped[2] = [wrapped_body]
58
+
59
+ wrapped
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,64 @@
1
+ require 'json'
2
+ require_relative '../spec_helper'
3
+
4
+ describe Rack::JsonResponseWrapper do
5
+ include Rack::Test::Methods
6
+
7
+ class MockedApp < Sinatra::Base
8
+ post '/' do
9
+ content_type 'application/json'
10
+ JSON.dump(JSON.parse(request.body.read))
11
+ end
12
+
13
+ post '/html' do
14
+ content_type 'text/html'
15
+ JSON.dump(JSON.parse(request.body.read))
16
+ end
17
+ end
18
+
19
+ def app
20
+ @app ||= Rack::JsonResponseWrapper.new(MockedApp)
21
+ end
22
+
23
+ describe 'call' do
24
+ before do
25
+ @obj = { foo: true, bar: 1, baz: 'hoagie' }
26
+ @json = JSON.dump(@obj)
27
+ end
28
+
29
+ it 'does nothing to the response if X-WRAP-RESPONSE is not defined' do
30
+ post '/', @json
31
+
32
+ expect(last_response.body).to eq @json
33
+ end
34
+
35
+ it 'does nothing to the response if Content-Type is not json, even with X-WRAP-RESPONSE' do
36
+ post '/html', @json, 'X-WRAP-RESPONSE' => true
37
+
38
+ expect(last_response.body).to eq @json
39
+ end
40
+
41
+ it 'wraps the response if X-WRAP-RESPONSE is set' do
42
+ post '/', @json, 'X-WRAP-RESPONSE' => true
43
+
44
+ @response_obj = JSON.parse(last_response.body)
45
+
46
+ expect(@response_obj).to include 'header'
47
+ expect(@response_obj).to include 'body'
48
+
49
+
50
+ expect(JSON.dump(@response_obj['body'])).to eq @json
51
+ end
52
+
53
+ it 'when wrapping, includes response header in body' do
54
+ post '/', @json, 'X-WRAP-RESPONSE' => true
55
+
56
+ @response_obj = JSON.parse(last_response.body)
57
+ @response_header = last_response.header
58
+
59
+ @response_wrapped_header = @response_obj['header']
60
+
61
+ expect(JSON.dump(@response_wrapped_header)).to eq JSON.dump(@response_header)
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,9 @@
1
+ require 'rspec'
2
+ require 'rack/test'
3
+ require 'sinatra/base'
4
+
5
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'rack', 'json_response_wrapper.rb')
6
+
7
+ RSpec.configure do |config|
8
+ ENV['RACK_ENV'] ||= 'test'
9
+ end
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rack-json_response_wrapper
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - g. nicholas d'andrea
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-08-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 3.0.0
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 3.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: rack-test
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '='
32
+ - !ruby/object:Gem::Version
33
+ version: 0.6.2
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '='
39
+ - !ruby/object:Gem::Version
40
+ version: 0.6.2
41
+ - !ruby/object:Gem::Dependency
42
+ name: sinatra
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '='
46
+ - !ruby/object:Gem::Version
47
+ version: 1.4.5
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '='
53
+ - !ruby/object:Gem::Version
54
+ version: 1.4.5
55
+ description: "Rack Middleware for JSON APIs accessed cross-domain from legacy browsers\n\nFirefox
56
+ version 4 does not support response headers for cross-domain requests.\nThis middleware
57
+ intercepts all requests and if the X-WRAP-RESPONSE is set, \nthe response will be
58
+ wrappped in JSON like {header: ..., body: ...}\n"
59
+ email: nick@gnidan.org
60
+ executables: []
61
+ extensions: []
62
+ extra_rdoc_files: []
63
+ files:
64
+ - LICENSE
65
+ - README.md
66
+ - Rakefile
67
+ - lib/rack/json_response_wrapper.rb
68
+ - spec/rack/json_response_wrapper_spec.rb
69
+ - spec/spec_helper.rb
70
+ homepage: http://github.com/gnidan/rack-json_response_wrapper
71
+ licenses:
72
+ - Unlicense / Public Domain
73
+ metadata: {}
74
+ post_install_message:
75
+ rdoc_options: []
76
+ require_paths:
77
+ - lib
78
+ required_ruby_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ required_rubygems_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ requirements: []
89
+ rubyforge_project:
90
+ rubygems_version: 2.2.2
91
+ signing_key:
92
+ specification_version: 4
93
+ summary: Rack Middleware for JSON APIs accessed cross-domain from legacy browsers
94
+ test_files: []