RackMotion 0.1
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/README.md +41 -0
- data/lib/RackMotion.rb +8 -0
- data/lib/project/RackMotion.rb +80 -0
- metadata +64 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: e25151d74f5c7f014686ffc00f30f9cea8f4c643
|
4
|
+
data.tar.gz: a9899dde82b707925d9127c85c3fe3d76b51f7eb
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6f7445f78ca154d1b7e3335aadcac83e89411df6d463827e603acb67fce62fbd7b436065e3ca49a4e46972a8f2d20af5b836f08685fac32dafb1e7ea532a9df9
|
7
|
+
data.tar.gz: e41097ff6c25e8c29538ec36b11bd45efdd5724727974e27061daba058092b2fc23c09b81c0a3966fedb8a110cf765d8079dccba757213c4f14e9ecb5c48b56b
|
data/README.md
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
<p align="center">
|
2
|
+
<img src="https://raw.github.com/drewbug/RackMotion/assets/rackmotion-logo.png" alt="RackMotion" title="RackMotion">
|
3
|
+
</p>
|
4
|
+
|
5
|
+
RackMotion provides a Rack-like interface for middleware that can intercept and alter HTTP requests and responses in RubyMotion. It's built on top of NSURLProtocol, which makes it, to borrow a line from [Mattt Thompson](http://www.nshipster.com/nsurlprotocol/), an Apple-sanctioned man-in-the-middle attack.
|
6
|
+
|
7
|
+
For example, here's how easy it is to enable [cross-origin resource sharing](http://en.wikipedia.org/wiki/Cross-origin_resource_sharing) for most Javascript XMLHttpRequests:
|
8
|
+
|
9
|
+
class EnableCORS
|
10
|
+
def initialize(app)
|
11
|
+
@app = app
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(request)
|
15
|
+
status, headers, data = @app.call(request)
|
16
|
+
|
17
|
+
if request.allHTTPHeaderFields['Origin']
|
18
|
+
headers['Access-Control-Allow-Origin'] = request.allHTTPHeaderFields['Origin']
|
19
|
+
end
|
20
|
+
|
21
|
+
return status, headers, data
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
And then, in your AppDelegate:
|
26
|
+
|
27
|
+
RackMotion.use EnableCORS
|
28
|
+
|
29
|
+
## Installation
|
30
|
+
|
31
|
+
Add this line to your application's Gemfile:
|
32
|
+
|
33
|
+
gem 'RackMotion'
|
34
|
+
|
35
|
+
And then execute:
|
36
|
+
|
37
|
+
$ bundle
|
38
|
+
|
39
|
+
Or install it yourself as:
|
40
|
+
|
41
|
+
$ gem install RackMotion
|
data/lib/RackMotion.rb
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
unless defined?(Motion::Project::Config)
|
2
|
+
raise "This file must be required within a RubyMotion project Rakefile."
|
3
|
+
end
|
4
|
+
|
5
|
+
lib_dir_path = File.dirname(File.expand_path(__FILE__))
|
6
|
+
Motion::Project::App.setup do |app|
|
7
|
+
app.files.unshift(Dir.glob(File.join(lib_dir_path, "project/**/*.rb")))
|
8
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module RackMotion
|
2
|
+
def self.use(middleware)
|
3
|
+
NSURLProtocol.registerClass URLProtocol if URLProtocol.middlewares.empty?
|
4
|
+
URLProtocol.middlewares << middleware
|
5
|
+
end
|
6
|
+
|
7
|
+
class URLProtocol < NSURLProtocol
|
8
|
+
@@middlewares = []
|
9
|
+
|
10
|
+
def self.middlewares
|
11
|
+
@@middlewares
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.canInitWithRequest(request)
|
15
|
+
return false unless request.URL
|
16
|
+
return false unless request.URL.scheme.start_with?("http")
|
17
|
+
!NSURLProtocol.propertyForKey('RackMotion', inRequest: request)
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.canonicalRequestForRequest(request)
|
21
|
+
return request
|
22
|
+
end
|
23
|
+
|
24
|
+
def startLoading
|
25
|
+
@thread = NSThread.alloc.initWithTarget(lambda do
|
26
|
+
chain = @@middlewares.inject(self) do |instance, klass|
|
27
|
+
klass.new(instance)
|
28
|
+
end
|
29
|
+
|
30
|
+
status, headers, data = chain.call self.request.mutableCopy
|
31
|
+
|
32
|
+
response = NSHTTPURLResponse.alloc.initWithURL @connection.originalRequest.URL, statusCode: status, HTTPVersion: 'HTTP/1.1', headerFields: headers
|
33
|
+
|
34
|
+
self.client.URLProtocol(self, didReceiveResponse: response, cacheStoragePolicy: NSURLCacheStorageNotAllowed)
|
35
|
+
self.client.URLProtocol(self, didLoadData: data)
|
36
|
+
self.client.URLProtocolDidFinishLoading(self)
|
37
|
+
end, selector: 'call', object: nil)
|
38
|
+
|
39
|
+
@thread.start
|
40
|
+
end
|
41
|
+
|
42
|
+
def stopLoading
|
43
|
+
@connection.cancel if @connection
|
44
|
+
@thread.cancel if @thread
|
45
|
+
end
|
46
|
+
|
47
|
+
def call(new_request)
|
48
|
+
NSURLProtocol.setProperty(true, forKey: 'RackMotion', inRequest: new_request)
|
49
|
+
|
50
|
+
connection_delegate = ConnectionDelegate.new
|
51
|
+
|
52
|
+
@connection = NSURLConnection.alloc.initWithRequest(new_request, delegate: connection_delegate, startImmediately: true)
|
53
|
+
NSRunLoop.currentRunLoop.run
|
54
|
+
|
55
|
+
connection_delegate.semaphore.wait
|
56
|
+
return connection_delegate.response.statusCode, connection_delegate.response.allHeaderFields.mutableCopy, connection_delegate.data
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
class ConnectionDelegate
|
61
|
+
attr_reader :semaphore, :data, :response
|
62
|
+
|
63
|
+
def initialize
|
64
|
+
@semaphore = Dispatch::Semaphore.new(0)
|
65
|
+
@data = NSMutableData.new
|
66
|
+
end
|
67
|
+
|
68
|
+
def connection(connection, didReceiveData: data)
|
69
|
+
@data.appendData(data)
|
70
|
+
end
|
71
|
+
|
72
|
+
def connection(connection, didReceiveResponse: response)
|
73
|
+
@response = response
|
74
|
+
end
|
75
|
+
|
76
|
+
def connectionDidFinishLoading(connection)
|
77
|
+
@semaphore.signal
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
metadata
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: RackMotion
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.1'
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Drew Carey Buglione
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-08-15 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rake
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
description: RackMotion provides a Rack-like interface for middleware that can intercept
|
28
|
+
and alter HTTP requests and responses in RubyMotion. It's built on top of NSURLProtocol,
|
29
|
+
which makes it, to borrow a line from Mattt Thompson, an Apple-sanctioned man-in-the-middle
|
30
|
+
attack.
|
31
|
+
email:
|
32
|
+
- me@drewb.ug
|
33
|
+
executables: []
|
34
|
+
extensions: []
|
35
|
+
extra_rdoc_files: []
|
36
|
+
files:
|
37
|
+
- README.md
|
38
|
+
- lib/project/RackMotion.rb
|
39
|
+
- lib/RackMotion.rb
|
40
|
+
homepage: ''
|
41
|
+
licenses:
|
42
|
+
- ''
|
43
|
+
metadata: {}
|
44
|
+
post_install_message:
|
45
|
+
rdoc_options: []
|
46
|
+
require_paths:
|
47
|
+
- lib
|
48
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - '>='
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '0'
|
53
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - '>='
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: '0'
|
58
|
+
requirements: []
|
59
|
+
rubyforge_project:
|
60
|
+
rubygems_version: 2.0.6
|
61
|
+
signing_key:
|
62
|
+
specification_version: 4
|
63
|
+
summary: Intercept and alter HTTP requests and responses in RubyMotion
|
64
|
+
test_files: []
|