motion-http 0.1.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 295321b18316c5b3a47c29692b4831e25ed4b1c7
4
- data.tar.gz: afcdbfc33304f05cf290fcdd33e339ad693fcb74
2
+ SHA256:
3
+ metadata.gz: 9a2a08f70352d4ca6c4a4b3a79ab5825e806787ab90088bcad88350360d5c11f
4
+ data.tar.gz: 9bfc38b0f0138c7c4fb5ab98974ddb4ab852ed96e083d001ec683463d2e5f0ce
5
5
  SHA512:
6
- metadata.gz: '095e68b01bca380833a6e93c2e25e5e6abd389727b6ff92aa1b39c9fef79132bec440ea2b280b4e0e5436535534dc158e234d1ed54bc9c99cc518a246fa5cf77'
7
- data.tar.gz: 0667af5350564fb4f4199437a3ae827435f5ce942842ca333adba98ed46efaa7a8c4ff1dce85dc67c17b9fa382abdf28b7ba5645fa0e6064581cf405e9e3e5ed
6
+ metadata.gz: 2a3d796b3c9654461fb66b42456e7f43bfd6d896e5d3f0165c5d00dcb184ca5867b55a089d2eb75d2508b76697bec120bc1047874bc02530cb5e0c93896aa2ec
7
+ data.tar.gz: caf9553c2567c658ffd23c303dba63014a30fba3f5f4f111339753a8bab2c4b8bb9dbde0aa39d0d2e4dbac689bb826e75760123b502411687c4ea93dcee8c7cf
data/README.md CHANGED
@@ -1,16 +1,14 @@
1
1
  # motion-http
2
2
 
3
- Motion::HTTP is a cross-platform HTTP Client for RubyMotion that's quick and easy to use.
3
+ A cross-platform HTTP Client for RubyMotion that's quick and easy to use.
4
4
 
5
5
  Supported platforms:
6
6
  - iOS, macOS, tvOS, watchOS
7
7
  - Android
8
8
 
9
- This gem depends on two really popular networking libraries:
10
- - [AFNetworking](https://github.com/AFNetworking/AFNetworking) (for Cocoa platforms)
11
- - [OkHttp](http://square.github.io/okhttp/) (for Android)
9
+ It makes use of the officially supported networking libraries provided by Apple and Google. The goal of this gem is to provide you with a stable alternative to using these libraries directly, using a syntax that is much easier to use.
12
10
 
13
- Please note that this library is still a work in progress. Please report bugs and suggestions for improvement!
11
+ Please report any bugs or suggestions for improvement!
14
12
 
15
13
  ## Installation
16
14
 
@@ -21,33 +19,35 @@ Add this line to your application's Gemfile:
21
19
  And then execute:
22
20
 
23
21
  $ bundle
24
- $ rake pod:install # for iOS apps
25
- $ rake gradle:install # for Android apps
22
+ $ rake gradle:install # Android only
26
23
 
27
24
  ### iOS Specific Configuration
28
25
 
29
- If you will be making insecure HTTP requests (not HTTPS), you will need to explicitly allow insecure HTTP requests by adding this line to your app's configuration in your Rakefile:
26
+ If you will be making insecure requests (not using HTTPS), you will need to explicitly allow insecure HTTP requests by adding this line to your app's configuration (in your `Rakefile`). You might want to do this if you are trying to access localhost in development.
30
27
 
31
- app.info_plist['NSAppTransportSecurity'] = { 'NSAllowsArbitraryLoads' => true }
28
+ ```ruby
29
+ app.development do
30
+ app.info_plist['NSAppTransportSecurity'] = { 'NSAllowsArbitraryLoads' => true }
31
+ end
32
+ ```
32
33
 
33
34
  ## Usage
34
35
 
35
- Using `Motion::HTTP` is quick and easy. You can use the simple approach for making one-off requests, or the advanced approach of creating a reusable API client for further customization.
36
+ Using `motion-http` is quick and easy. You can either make one-off requests or create a reusable API client for further customization.
36
37
 
37
- ### Simple Usage
38
+ ### Basic Usage
38
39
 
39
- The basic syntax for a simple request looks like this:
40
+ The basic syntax for a request looks like this:
40
41
  ```ruby
41
- Motion::HTTP.method(url, params) do |response|
42
- # this block will be called asynchronously
42
+ HTTP.method(url, options) do |response|
43
+ # this will be called asynchronously
43
44
  end
44
45
  ```
46
+ Where `method` can be either `get`, `post`, `put`, `patch`, `delete`, `head`, `options`, or `trace`.
45
47
 
46
- To make a simple `GET` request:
48
+ For example, to make a simple `GET` request:
47
49
  ```ruby
48
- Motion::HTTP.get("http://www.example.com") do |response|
49
- puts "status code: #{response.status_code}"
50
- puts "response body: #{response.body}"
50
+ HTTP.get("http://www.example.com") do |response|
51
51
  if response.success?
52
52
  puts "Success!"
53
53
  else
@@ -56,16 +56,29 @@ Motion::HTTP.get("http://www.example.com") do |response|
56
56
  end
57
57
  ```
58
58
 
59
- You can specify query params as the second argument:
59
+ If you need to specify query params:
60
60
  ```ruby
61
- Motion::HTTP.get("http://www.example.com/search", term: "my search term") do |response|
61
+ HTTP.get("http://www.example.com/search", params: { term: "my search term" }) do |response|
62
62
  # ...
63
63
  end
64
64
  ```
65
65
 
66
- `Motion::HTTP` will automatically parse JSON responses:
66
+ The response object contains the status code, headers, body, and shortcut methods for checking the response status:
67
+ ```ruby
68
+ HTTP.get("http://example.com") do |response|
69
+ puts response.status_code.to_s
70
+ puts response.headers.inspect
71
+ puts response.body
72
+ response.success? # 2xx status
73
+ response.redirect? # 3xx status
74
+ response.client_error? # 4xx status
75
+ response.server_error? # 5xx status
76
+ end
77
+ ```
78
+
79
+ If the response body has a JSON content type it will automatically be parsed when requesting the `response.object`:
67
80
  ```ruby
68
- Motion::HTTP.get("http://api.example.com/people.json") do |response|
81
+ HTTP.get("http://api.example.com/people.json") do |response|
69
82
  if response.success?
70
83
  response.object["people"].each do |person|
71
84
  puts "name: #{person["name"]}"
@@ -76,25 +89,66 @@ Motion::HTTP.get("http://api.example.com/people.json") do |response|
76
89
  end
77
90
  ```
78
91
 
79
- To make a simple `POST` request, the value passed as the second argument will be encoded as the request body:
92
+ Use the `follow_redirects` option to specify whether or not to follow redirects. The default is `true`:
80
93
  ```ruby
81
- json = { widget: { name: "Foobar" } }
82
- Motion::HTTP.post("http://www.example.com/widgets", json) do |response|
94
+ HTTP.get("http://example.com/redirect", follow_redirects: false) do |response|
95
+ # ...
96
+ end
97
+ ```
98
+
99
+ #### POST Requests
100
+
101
+ When making a `POST` request, specifying the request body is easy:
102
+ ```ruby
103
+ HTTP.post("http://www.example.com/endpoint", body: raw_request_body) do |response|
104
+ # ...
105
+ end
106
+ ```
107
+
108
+ Specify the `:form` option and it will automatically be encoded as `application/x-www-form-urlencoded` request body:
109
+ ```ruby
110
+ HTTP.post("http://www.example.com/login", form: { user: 'andrew', password: 'secret'}) do |response|
83
111
  if response.success?
84
- puts "Widget created!"
112
+ puts "Authenticated!"
85
113
  elsif response.client_error?
114
+ puts "Bad username or password"
115
+ else
116
+ puts "Oops! Something went wrong."
117
+ end
118
+ end
119
+ ```
120
+
121
+ Likewise, to send a JSON encoded request body, use the `:json` option:
122
+ ```ruby
123
+ HTTP.post("http://www.example.com/widgets", json: { widget: { name: "Foobar" } }) do |response|
124
+ if response.success?
125
+ puts "Widget created!"
126
+ elsif response.status_code == 422
86
127
  puts "Oops, you did something wrong: #{response.object["error_message"]}"
87
128
  else
88
- puts "Oops! Something else went wrong."
129
+ puts "Oops! Something went wrong."
89
130
  end
90
131
  end
91
132
  ```
92
133
 
93
- `PUT`, `PATCH`, and `DELETE` requests work the same way:
134
+ To specify request specific headers, use the `:headers` option. This overrides any previously set headers. In this example, we override the default JSON content type:
135
+ ```ruby
136
+ HTTP.post("http://www.example.com/widgets",
137
+ headers: { 'Content-Type' => 'application/vnd.api+json' },
138
+ json: { widget: { name: "Foobar" } }
139
+ ) do |response|
140
+ # ...
141
+ end
142
+ ```
143
+
144
+ All other HTTP method requests work the same way:
94
145
  ```ruby
95
- Motion::HTTP.put(url, params) { ... }
96
- Motion::HTTP.patch(url, params) { ... }
97
- Motion::HTTP.delete(url, params) { ... }
146
+ HTTP.put(url, options) { ... }
147
+ HTTP.patch(url, options) { ... }
148
+ HTTP.delete(url, options) { ... }
149
+ HTTP.head(url, options) { ... }
150
+ HTTP.options(url, options) { ... }
151
+ HTTP.trace(url, options) { ... }
98
152
  ```
99
153
 
100
154
  ### Advanced Usage
@@ -102,27 +156,63 @@ Motion::HTTP.delete(url, params) { ... }
102
156
  A common use case is to create a reusable HTTP client that uses a common base URL or request headers.
103
157
 
104
158
  ```ruby
105
- client = Motion::HTTP::Client.new("http://www.example.com")
159
+ client = HTTP::Client.new("http://api.example.com")
106
160
  # Set or replace a single header:
107
161
  client.header "X-API-TOKEN", "abc123xyz"
162
+ client.header["X-API-TOKEN"] = "abc123xyz"
108
163
 
109
164
  # To set or replace multiple headers:
110
165
  client.headers "X-API-TOKEN" => "abc123xyz",
111
166
  "Accept" => "application/json"
112
167
 
113
- # It is valid for some headers to appear multiple times (Accept, Vary, etc).
168
+ # Note that it is valid for some headers to appear multiple times (Accept, Vary, etc).
114
169
  # To append multiple headers of the same key:
115
170
  client.add_header "Accept", "application/json"
116
- client.add_header "Accept", "application/vnd.api+json"
171
+ client.headers.add "Accept", "application/json"
117
172
  ```
118
173
 
119
- Then make your requests relative to the base URL that you specified when creating your client.
174
+ Then you can make your requests relative to the base URL that you specified when creating your client.
120
175
  ```ruby
121
176
  client.get("/people") do |response|
122
177
  # ...
123
178
  end
124
179
  ```
125
180
 
181
+ ### Basic Auth / Token Auth
182
+
183
+ To make Basic Auth requests, either set the credentials before the request, or set it on your client:
184
+
185
+ ```ruby
186
+ HTTP.basic_auth('username', 'password').get('https://example.com/protected')
187
+ # or
188
+ client.basic_auth('username', 'password')
189
+ client.get('/protected')
190
+ ```
191
+
192
+ The `auth` method is another shortcut for setting any value of the Authorization header:
193
+
194
+ ```ruby
195
+ HTTP.auth("Token token=#{my_token}")
196
+ # or
197
+ client.auth("Token token=#{my_token}")
198
+ # same as
199
+ client.headers['Authorization'] = "Token token=#{my_token}"
200
+ ```
201
+
202
+ ### Logging
203
+
204
+ Logging is disabled by default. To enable logging:
205
+
206
+ ```
207
+ HTTP.logger.enable!
208
+ ```
209
+
210
+ To disable it again:
211
+
212
+ ```
213
+ HTTP.logger.disable!
214
+ ```
215
+
126
216
  ## Contributing
127
217
 
128
218
  1. Fork it
@@ -131,12 +221,37 @@ end
131
221
  4. Push to the branch (`git push origin my-new-feature`)
132
222
  5. Create new Pull Request
133
223
 
134
- ## MIT License
224
+ ## License
135
225
 
136
- Copyright 2018 Andrew Havens
226
+ Copyright 2018-2019 Andrew Havens
137
227
 
138
228
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
139
229
 
140
230
  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
141
231
 
142
232
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
233
+
234
+ Parts of the source are under the following license:
235
+
236
+ Copyright (c) 2015-2016, HipByte (info@hipbyte.com) and contributors.
237
+ All rights reserved.
238
+
239
+ Redistribution and use in source and binary forms, with or without
240
+ modification, are permitted provided that the following conditions are met:
241
+
242
+ 1. Redistributions of source code must retain the above copyright notice, this
243
+ list of conditions and the following disclaimer.
244
+ 2. Redistributions in binary form must reproduce the above copyright notice,
245
+ this list of conditions and the following disclaimer in the documentation
246
+ and/or other materials provided with the distribution.
247
+
248
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
249
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
250
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
251
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
252
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
253
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
254
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
255
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
256
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
257
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -1,58 +1,13 @@
1
1
  class Motion
2
2
  class HTTP
3
3
  class Adapter
4
- JSONMediaType = Okhttp3::MediaType.parse("application/json; charset=utf-8")
5
-
6
- def self.client
7
- @client ||= Okhttp3::OkHttpClient.new
8
- end
9
-
10
- def self.request(http_method, url, headers, params = nil, &callback)
11
- puts "starting #{http_method.to_s.upcase} #{url}"
12
- request = OkHttp3::Request::Builder.new
13
- request.url(url) # TODO: encode GET params and append to URL prior to calling this method
14
- headers.each do |key, value|
15
- if value.is_a? Array
16
- value.each {|val| request.addHeader(key, val) }
17
- else
18
- request.header(key, value)
19
- end
20
- end
21
- if http_method != :get
22
- puts "would have set body for #{http_method.to_s.upcase} #{url}"
23
- # body = OkHttp3::RequestBody.create(JSONMediaType, params) # TODO: allow other content types
24
- # request.method(http_method.to_s, body)
25
- end
26
- client.newCall(request.build).enqueue(OkhttpCallback.new(callback))
4
+ def self.perform(request, &callback)
5
+ volley_request = VolleyRequest.create(request, callback)
6
+ queue.add(volley_request)
27
7
  end
28
8
 
29
- class OkhttpCallback
30
- def initialize(callback)
31
- @callback = callback
32
- end
33
-
34
- def onFailure(call, e)
35
- puts "Error: #{e.getMessage}"
36
- @callback.call(Response.new(nil, Headers.new, e.getMessage))
37
- end
38
-
39
- def onResponse(call, response)
40
- @callback.call(parse_response(response))
41
- end
42
-
43
- def parse_response(response)
44
- headers = Headers.new
45
- i = 0
46
- while i < response.headers.size
47
- key = response.headers.name(i)
48
- value = response.headers.value(i)
49
- headers.add(key, value)
50
- i += 1
51
- end
52
- body_string = response.body.string
53
- json = JSON.load(body_string) if headers['content-type'] =~ /application\/json/
54
- Response.new(response.code, headers, body_string, json)
55
- end
9
+ def self.queue
10
+ @queue ||= Com::Android::Volley::Toolbox::Volley.newRequestQueue(Motion::HTTP.application_context)
56
11
  end
57
12
  end
58
13
  end
@@ -0,0 +1,36 @@
1
+ # Copyright (c) 2015-2016, HipByte (info@hipbyte.com) and contributors.
2
+ # All rights reserved.
3
+
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions are met:
6
+
7
+ # 1. Redistributions of source code must retain the above copyright notice, this
8
+ # list of conditions and the following disclaimer.
9
+ # 2. Redistributions in binary form must reproduce the above copyright notice,
10
+ # this list of conditions and the following disclaimer in the documentation
11
+ # and/or other materials provided with the distribution.
12
+
13
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
14
+ # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
17
+ # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18
+ # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19
+ # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20
+ # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23
+
24
+ # Copied from https://github.com/HipByte/Flow/blob/44283b31a63bc826d2c068557b6357dc1195680b/flow/base64/android/base64.rb
25
+ class Base64
26
+ def self.encode(string)
27
+ bytes = Java::Lang::String.new(string).getBytes("UTF-8")
28
+ Android::Util::Base64.encodeToString(bytes, Android::Util::Base64::NO_WRAP)
29
+ end
30
+
31
+ def self.decode(string)
32
+ java_string = Java::Lang::String.new(string)
33
+ bytes = Android::Util::Base64.decode(java_string, Android::Util::Base64::NO_WRAP)
34
+ Java::Lang::String.new(bytes, "UTF-8")
35
+ end
36
+ end
data/lib/android/json.rb CHANGED
@@ -1,6 +1,29 @@
1
+ # Copyright (c) 2015-2016, HipByte (info@hipbyte.com) and contributors.
2
+ # All rights reserved.
3
+
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions are met:
6
+
7
+ # 1. Redistributions of source code must retain the above copyright notice, this
8
+ # list of conditions and the following disclaimer.
9
+ # 2. Redistributions in binary form must reproduce the above copyright notice,
10
+ # this list of conditions and the following disclaimer in the documentation
11
+ # and/or other materials provided with the distribution.
12
+
13
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
14
+ # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
17
+ # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18
+ # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19
+ # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20
+ # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23
+
1
24
  # NOTE: Copied from https://github.com/HipByte/Flow/blob/master/flow/json/android/json.rb
2
25
  class JSON
3
- def self.load(str)
26
+ def self.parse(str)
4
27
  tok = Org::JSON::JSONTokener.new(str)
5
28
  obj = tok.nextValue
6
29
  if obj == nil
@@ -34,3 +57,34 @@ class JSON
34
57
  end
35
58
  end
36
59
  end
60
+
61
+ class Object
62
+ def to_json
63
+ # The Android JSON API expects real Java String objects.
64
+ @@fix_string ||= (lambda do |obj|
65
+ case obj
66
+ when String, Symbol
67
+ obj = obj.toString
68
+ when Hash
69
+ map = Hash.new
70
+ obj.each do |key, value|
71
+ key = key.toString if key.is_a?(String) || key.is_a?(Symbol)
72
+ value = @@fix_string.call(value)
73
+ map[key] = value
74
+ end
75
+ obj = map
76
+ when Array
77
+ obj = obj.map do |item|
78
+ (item.is_a?(String) || item.is_a?(Symbol)) ? item.toString : @@fix_string.call(item)
79
+ end
80
+ end
81
+ obj
82
+ end)
83
+
84
+ obj = Org::JSON::JSONObject.wrap(@@fix_string.call(self))
85
+ if obj == nil
86
+ raise "Can't serialize object to JSON"
87
+ end
88
+ obj.toString.to_s
89
+ end
90
+ end
@@ -0,0 +1,5 @@
1
+ class ParamsEncoder
2
+ def self.encode(arg)
3
+ Java::Net::URLEncoder.encode(arg, 'UTF-8')
4
+ end
5
+ end
@@ -0,0 +1,52 @@
1
+ class VolleyRequest < Com::Android::Volley::Request
2
+ attr_accessor :original_request, :callback
3
+
4
+ METHOD_CODES = {
5
+ get: 0,
6
+ post: 1,
7
+ put: 2,
8
+ delete: 3,
9
+ head: 4,
10
+ options: 5,
11
+ trace: 6,
12
+ patch: 7,
13
+ }
14
+
15
+ def self.create(request, callback)
16
+ volley_request = new(METHOD_CODES[request.http_method], request.url, nil)
17
+ volley_request.original_request = request
18
+ volley_request.headers = request.headers.to_hash
19
+ volley_request.body = request.body
20
+ volley_request.callback = callback
21
+ volley_request
22
+ end
23
+
24
+ def parseNetworkResponse(networkResponse)
25
+ response = build_response(networkResponse)
26
+ Com::Android::Volley::Response.success(response, Com::Android::Volley::Toolbox::HttpHeaderParser.parseCacheHeaders(networkResponse))
27
+ end
28
+
29
+ def deliverResponse(response)
30
+ Motion::HTTP.logger.log_response(response)
31
+ callback.call(response) if callback
32
+ end
33
+
34
+ def deliverError(error)
35
+ if error.networkResponse
36
+ response = build_response(error.networkResponse)
37
+ deliverResponse(response)
38
+ else
39
+ Motion::HTTP.logger.error("Error while requesting #{original_request.url}: #{error.getMessage}")
40
+ error.getStackTrace.each do |line|
41
+ puts line.toString
42
+ end
43
+ response = Motion::HTTP::Response.new(original_request, nil, nil, error.getMessage)
44
+ callback.call(response) if callback
45
+ end
46
+ end
47
+
48
+ def build_response(networkResponse)
49
+ body = parse_body_from_response(networkResponse)
50
+ Motion::HTTP::Response.new(original_request, networkResponse.statusCode, Motion::HTTP::Headers.new(networkResponse.headers), body)
51
+ end
52
+ end
data/lib/cocoa/adapter.rb CHANGED
@@ -1,44 +1,61 @@
1
1
  class Motion
2
2
  class HTTP
3
3
  class Adapter
4
- def self.manager
5
- @manager ||= AFHTTPSessionManager.manager
4
+ def self.perform(request, &callback)
5
+ Motion::HTTP::Adapter::Request.new(request).perform(&callback)
6
6
  end
7
7
 
8
- def self.request(http_method, url, headers, params = nil, &callback)
9
- progress = nil
10
- on_success = lambda do |task, response_object|
11
- response = task.response
12
- callback.call(Response.new(response.statusCode, Headers.new(response.allHeaderFields), nil, response_object))
8
+ class Request
9
+ def initialize(request)
10
+ @request = request
11
+ @session = NSURLSession.sessionWithConfiguration(NSURLSessionConfiguration.defaultSessionConfiguration, delegate: self, delegateQueue: nil)
13
12
  end
14
- on_error = lambda do |operation, error|
15
- NSLog("Error: %@", error)
16
- response = operation.response
17
- status_code = response.statusCode if response
18
- response_headers = response.allHeaderFields if response
19
- error_message = error.localizedDescription
20
- error_message += error.userInfo[NSLocalizedDescriptionKey] if error.userInfo[NSLocalizedDescriptionKey]
21
- callback.call(
22
- Response.new(status_code, Headers.new(response_headers), error_message)
23
- )
13
+
14
+ def perform(&callback)
15
+ # TODO: dataTask is good for general HTTP requests but not for file downloads
16
+ ns_url_request = build_ns_url_request
17
+ task = @session.dataTaskWithRequest(ns_url_request, completionHandler: -> (data, response, error) {
18
+ if error
19
+ error_message = "#{error.localizedDescription} #{error.userInfo['NSLocalizedDescriptionKey']}"
20
+ Motion::HTTP.logger.error("Error while requesting #{@request.url}: #{error_message}")
21
+ response = Response.new(@request, response&.statusCode, Headers.new(response&.allHeaderFields), error_message)
22
+ else
23
+ response = Response.new(@request, response.statusCode, Headers.new(response.allHeaderFields), data.to_s)
24
+ Motion::HTTP.logger.log_response(response)
25
+ end
26
+ callback.call(response) if callback
27
+ })
28
+ task.resume
24
29
  end
25
30
 
26
- case http_method
27
- when :get
28
- manager.GET url, parameters: params, progress: progress, success: on_success, failure: on_error
29
- when :post
30
- manager.POST url, parameters: params, progress: progress, success: on_success, failure: on_error
31
- when :put
32
- manager.PUT url, parameters: params, progress: progress, success: on_success, failure: on_error
33
- when :patch
34
- manager.PATCH url, parameters: params, progress: progress, success: on_success, failure: on_error
35
- when :delete
36
- manager.DELETE url, parameters: params, progress: progress, success: on_success, failure: on_error
31
+ def build_ns_url_request
32
+ ns_url_request = NSMutableURLRequest.alloc.initWithURL(NSURL.URLWithString(@request.url))
33
+ ns_url_request.HTTPMethod = @request.http_method.to_s.upcase
34
+ @request.headers.each do |key, value|
35
+ if value.is_a? Array
36
+ value.each {|v2| ns_url_request.addValue(v2, forHTTPHeaderField: key) }
37
+ else
38
+ ns_url_request.setValue(value, forHTTPHeaderField: key)
39
+ end
40
+ end
41
+
42
+ if @request.body
43
+ ns_url_request.HTTPBody = NSString.alloc.initWithString(@request.body).dataUsingEncoding(NSUTF8StringEncoding)
44
+ end
45
+
46
+ # TODO: add other headers
47
+ ns_url_request
37
48
  end
38
49
 
39
- # FIXME: dynamically calling the method using send results in a crash
40
- # method_signature = "#{http_method.to_s.upcase}:parameters:progress:success:failure:"
41
- # # manager.send(method_signature, url, params, nil, on_success, on_error)
50
+ # NSURLSessionTaskDelegate methods
51
+
52
+ def URLSession(session, task: task, willPerformHTTPRedirection: response, newRequest: request, completionHandler: completion_handler)
53
+ if @request.options[:follow_redirects] == false
54
+ completion_handler.call(nil)
55
+ else
56
+ completion_handler.call(request)
57
+ end
58
+ end
42
59
  end
43
60
  end
44
61
  end
@@ -0,0 +1,35 @@
1
+ # Copyright (c) 2015-2016, HipByte (info@hipbyte.com) and contributors.
2
+ # All rights reserved.
3
+
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions are met:
6
+
7
+ # 1. Redistributions of source code must retain the above copyright notice, this
8
+ # list of conditions and the following disclaimer.
9
+ # 2. Redistributions in binary form must reproduce the above copyright notice,
10
+ # this list of conditions and the following disclaimer in the documentation
11
+ # and/or other materials provided with the distribution.
12
+
13
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
14
+ # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
17
+ # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18
+ # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19
+ # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20
+ # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23
+
24
+ # Copied from https://github.com/HipByte/Flow/blob/44283b31a63bc826d2c068557b6357dc1195680b/flow/base64/cocoa/base64.rb
25
+ class Base64
26
+ def self.encode(string)
27
+ data = string.dataUsingEncoding(NSUTF8StringEncoding)
28
+ data.base64EncodedStringWithOptions(0)
29
+ end
30
+
31
+ def self.decode(string)
32
+ data = NSData.alloc.initWithBase64EncodedString(string, options: 0)
33
+ NSString.alloc.initWithData(data, encoding: NSUTF8StringEncoding)
34
+ end
35
+ end
data/lib/cocoa/json.rb ADDED
@@ -0,0 +1,50 @@
1
+ # Copyright (c) 2015-2016, HipByte (info@hipbyte.com) and contributors.
2
+ # All rights reserved.
3
+
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions are met:
6
+
7
+ # 1. Redistributions of source code must retain the above copyright notice, this
8
+ # list of conditions and the following disclaimer.
9
+ # 2. Redistributions in binary form must reproduce the above copyright notice,
10
+ # this list of conditions and the following disclaimer in the documentation
11
+ # and/or other materials provided with the distribution.
12
+
13
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
14
+ # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
17
+ # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18
+ # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19
+ # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20
+ # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23
+
24
+ # Copied from https://github.com/HipByte/Flow/blob/44283b31a63bc826d2c068557b6357dc1195680b/flow/json/cocoa/json.rb
25
+ class JSON
26
+ def self.parse(json_string)
27
+ error_ptr = Pointer.new(:id)
28
+ object = NSJSONSerialization.JSONObjectWithData(json_string.dataUsingEncoding(NSUTF8StringEncoding), options: 0, error: error_ptr)
29
+ unless object
30
+ raise error_ptr[0].description
31
+ end
32
+ object
33
+ end
34
+
35
+ def self.generate(object)
36
+ raise "Invalid JSON object" unless NSJSONSerialization.isValidJSONObject(object)
37
+ error_ptr = Pointer.new(:id)
38
+ data = NSJSONSerialization.dataWithJSONObject(object, options: 0, error: error_ptr)
39
+ unless data
40
+ raise error_ptr[0].description
41
+ end
42
+ data.to_s
43
+ end
44
+ end
45
+
46
+ class Object
47
+ def to_json
48
+ JSON.generate(self)
49
+ end
50
+ end
@@ -0,0 +1,8 @@
1
+ class ParamsEncoder
2
+ # TODO: check if iOS implements anything more performant/reliable that we should be using.
3
+ def self.encode(arg)
4
+ arg.to_s.gsub(/([^ a-zA-Z0-9_.-]+)/) do |m|
5
+ '%' + m.unpack('H2' * m.bytesize).join('%').upcase
6
+ end.tr(' ', '+')
7
+ end
8
+ end
@@ -3,9 +3,10 @@ class Motion
3
3
  class Client
4
4
  attr_reader :base_url
5
5
 
6
- def initialize(base_url = nil)
7
- @base_url = base_url || ""
8
- @headers = Headers.new
6
+ def initialize(base_url = nil, options = nil)
7
+ @base_url = base_url || ''
8
+ options ||= {}
9
+ @headers = Headers.new(options.delete(:headers))
9
10
  end
10
11
 
11
12
  def header(key, value)
@@ -25,19 +26,57 @@ class Motion
25
26
  @headers
26
27
  end
27
28
 
28
- # FIXME: doesn't work on Android
29
- # [:get, :post, :put, :patch, :delete].each do |method|
30
- # define_method "#{method}", do |path, params = nil, &callback|
31
- # Request.new(method, base_url + path, headers, params, &callback).call
32
- # end
33
- # end
29
+ def basic_auth(username, password)
30
+ header_value = 'Basic ' + Base64.encode("#{username}:#{password}")
31
+ auth(header_value)
32
+ self
33
+ end
34
+
35
+ def auth(header_value)
36
+ @headers.set 'Authorization', header_value
37
+ self
38
+ end
39
+
40
+ def get(path, options = nil, &callback)
41
+ request(:get, path, options, &callback)
42
+ end
43
+
44
+ def post(path, options = nil, &callback)
45
+ request(:post, path, options, &callback)
46
+ end
47
+
48
+ def put(path, options = nil, &callback)
49
+ request(:put, path, options, &callback)
50
+ end
34
51
 
35
- def get(path, params = nil, &callback)
36
- Request.new(:get, base_url + path, @headers, params, &callback).call
52
+ def patch(path, options = nil, &callback)
53
+ request(:patch, path, options, &callback)
37
54
  end
38
55
 
39
- def post(path, params = nil, &callback)
40
- Request.new(:post, base_url + path, @headers, params, &callback).call
56
+ def delete(path, options = nil, &callback)
57
+ request(:delete, path, options, &callback)
58
+ end
59
+
60
+ def head(path, options = nil, &callback)
61
+ request(:head, path, options, &callback)
62
+ end
63
+
64
+ def options(path, options = nil, &callback)
65
+ request(:options, path, options, &callback)
66
+ end
67
+
68
+ def trace(path, options = nil, &callback)
69
+ request(:trace, path, options, &callback)
70
+ end
71
+
72
+ def request(http_method, path, options = nil, &callback)
73
+ options ||= {}
74
+ headers_dup = headers.dup
75
+ if options[:headers]
76
+ options.delete(:headers).each {|key, value| headers_dup.set(key, value) }
77
+ end
78
+ options[:headers] = headers_dup
79
+ Request.new(http_method, base_url + path, options).perform(&callback)
41
80
  end
42
81
  end
43
82
  end
@@ -2,12 +2,27 @@ class Motion
2
2
  class HTTP
3
3
  class Headers
4
4
  def initialize(headers = {})
5
- @headers = headers
5
+ @headers = {}
6
+ if headers
7
+ headers.each {|key, value| set(key, value) }
8
+ end
9
+ end
10
+
11
+ def get(key)
12
+ @headers[key.downcase]
13
+ end
14
+ # alias :[] :get # FIXME: doesn't work in Android
15
+ def [](key)
16
+ get(key)
6
17
  end
7
18
 
8
19
  def set(key, value)
9
20
  @headers[key.downcase] = value
10
21
  end
22
+ # alias :[]= :set # FIXME: doesn't work in Android
23
+ def []=(key, value)
24
+ set(key, value)
25
+ end
11
26
 
12
27
  def add(key, value)
13
28
  key = key.downcase
@@ -17,13 +32,22 @@ class Motion
17
32
  end
18
33
  @headers[key] << value
19
34
  end
35
+ # alias :<< :add # FIXME: doesn't work in Android
36
+ def <<(key, value)
37
+ add(key, value)
38
+ end
20
39
 
21
40
  def each(&block)
22
41
  @headers.each(&block)
23
42
  end
24
43
 
25
- def [](key)
26
- @headers[key.downcase]
44
+ def to_hash
45
+ @headers # TODO: flatten array values
46
+ end
47
+
48
+ # FIXME: Android doesn't support dup (Java exception raised: java.lang.CloneNotSupportedException: Class com.yourcompany.motion_http.Headers doesn't implement Cloneable)
49
+ def dup
50
+ Headers.new(@headers)
27
51
  end
28
52
  end
29
53
  end
@@ -0,0 +1,56 @@
1
+ class Motion
2
+ class HTTP
3
+ class Logger
4
+ attr_reader :enabled
5
+
6
+ def initialize
7
+ @enabled = false # logging is disabled by default
8
+ end
9
+
10
+ def enable!
11
+ @enabled = true
12
+ end
13
+
14
+ def disable!
15
+ @enabled = false
16
+ end
17
+
18
+ def _logger
19
+ @_logger ||= Motion::Lager.new
20
+ end
21
+
22
+ def debug(message, color = :gray)
23
+ _logger.debug(message, color) if enabled
24
+ end
25
+
26
+ def log(message, color = :white)
27
+ _logger.log(message, color) if enabled
28
+ end
29
+
30
+ def error(message, color = :red)
31
+ _logger.error(message, color) # always log even if logging is disabled
32
+ end
33
+
34
+ def log_request(request)
35
+ debug "\nRequest:\n#{request.http_method.to_s.upcase} #{request.url}"
36
+ request.headers.each do |k,v|
37
+ debug "#{k}: #{v}"
38
+ end
39
+ debug(request.body) if request.body
40
+ end
41
+
42
+ def log_response(response)
43
+ debug "\nResponse:"
44
+ if response.original_request
45
+ debug "URL: #{response.original_request.url}"
46
+ end
47
+ debug "Status: #{response.status_code}"
48
+ response.headers.each do |k,v|
49
+ debug "#{k}: #{v}"
50
+ end
51
+ debug("\n#{response.body}")
52
+ end
53
+
54
+ end
55
+ end
56
+ end
@@ -1,19 +1,60 @@
1
1
  class Motion
2
2
  class HTTP
3
3
  class Request
4
- attr_reader :method, :url, :headers, :body, :callback
4
+ attr_reader :http_method, :url, :headers, :body, :options
5
5
 
6
- def initialize(method, url, headers = nil, params = nil, &callback)
7
- @method = method
6
+ def initialize(http_method, url, options = nil)
7
+ @http_method = http_method
8
8
  @url = url
9
- @headers = headers || Headers.new
10
- @body = params # TODO: turn params into body and set content-type?
11
- @callback = callback || ->(response) {}
9
+ @options = options ||= {}
10
+ @headers = @options.delete(:headers) || Headers.new
11
+ @body = @options.delete(:body)
12
+
13
+ if @options[:params]
14
+ @params = @options.delete(:params)
15
+ flatten_params!
16
+ encode_params!
17
+ @url = "#{url}?#{@params.map{|k,v|"#{k}=#{v}"}.join('&')}"
18
+
19
+ elsif @options[:form]
20
+ @headers['Content-Type'] ||= 'application/x-www-form-urlencoded'
21
+ @params = @options.delete(:form)
22
+ flatten_params!
23
+ encode_params!
24
+ @body = @params.map{|k,v|"#{k}=#{v}"}.join('&')
25
+
26
+ elsif @options[:json]
27
+ @headers['Content-Type'] ||= 'application/json; charset=utf-8'
28
+ @body = @options.delete(:json).to_json
29
+ end
30
+ end
31
+
32
+ def flatten_params!
33
+ new_params = {}
34
+ @params.each do |k,v|
35
+ if v.is_a? Hash
36
+ v.each do |nested_k, nested_v|
37
+ new_params["#{k}[#{nested_k}]"] = nested_v
38
+ end
39
+ else
40
+ new_params[k] = v
41
+ end
42
+ end
43
+ @params = new_params
44
+ flatten_params! if @params.any? {|k,v| v.is_a? Hash }
45
+ end
46
+
47
+ def encode_params!
48
+ new_params = {}
49
+ @params.each do |k,v|
50
+ new_params[ParamsEncoder.encode(k)] = ParamsEncoder.encode(v)
51
+ end
52
+ @params = new_params
12
53
  end
13
54
 
14
- def call
15
- # TODO: maybe pass self instead of args
16
- Adapter.request(method, url, headers, body, &callback)
55
+ def perform(&callback)
56
+ Motion::HTTP.logger.log_request(self)
57
+ Adapter.perform(self, &callback)
17
58
  end
18
59
  end
19
60
  end
@@ -1,22 +1,42 @@
1
1
  class Motion
2
2
  class HTTP
3
3
  class Response
4
- attr_reader :status_code, :headers, :body, :object
4
+ attr_reader :original_request, :status_code, :headers, :body
5
5
 
6
- def initialize(status_code, headers, body_string, body_object = nil)
6
+ def initialize(original_request, status_code, headers, body)
7
+ @original_request = original_request
7
8
  @status_code = status_code
8
9
  @headers = headers
9
- @body = body_string
10
- @object = body_object
10
+ @body = body
11
11
  end
12
12
 
13
13
  def success?
14
- return false unless status_code
15
- status_code >= 200 && status_code < 300
14
+ status_code && (200..299) === status_code
15
+ end
16
+
17
+ def redirect?
18
+ status_code && (300..399) === status_code
19
+ end
20
+
21
+ def client_error?
22
+ status_code && (400..499) === status_code
23
+ end
24
+
25
+ def server_error?
26
+ status_code && (500..599) === status_code
27
+ end
28
+
29
+ def object
30
+ @object ||= case headers['Content-Type']
31
+ when /^application\/json/, /^application\/vnd.api\+json/
32
+ JSON.parse(body)
33
+ else
34
+ body
35
+ end
16
36
  end
17
37
 
18
38
  def inspect
19
- "<Motion::HTTP::Response status_code:#{status_code} headers:<#{headers.class}> body:<#{body.class}>>"
39
+ "<Motion::HTTP::Response status_code:#{status_code} headers:#{headers.inspect} body:#{body.inspect}>"
20
40
  end
21
41
  end
22
42
  end
data/lib/common/http.rb CHANGED
@@ -1,36 +1,57 @@
1
1
  class Motion
2
2
  class HTTP
3
3
  class << self
4
- def client
5
- @client ||= Client.new
4
+ attr_accessor :application_context # Android
5
+
6
+ def logger
7
+ @logger ||= Logger.new
8
+ end
9
+
10
+ def client(*args)
11
+ Client.new(*args)
6
12
  end
7
13
 
8
- # FIXME: doesn't work on Android
9
- # [:get, :post, :put, :patch, :delete].each do |method|
10
- # define_method "#{method}", do |url, params = nil, &callback|
11
- # client.send(method, url, params, &callback)
12
- # end
13
- # end
14
+ def basic_auth(username, password)
15
+ client.basic_auth(username, password)
16
+ end
14
17
 
15
- def get(url, params = nil, &callback)
16
- client.get(url, params, &callback)
18
+ def auth(header_value)
19
+ client.auth(header_value)
17
20
  end
18
21
 
19
- def post(url, params = nil, &callback)
20
- client.post(url, params, &callback)
22
+ def get(url, options = nil, &callback)
23
+ client.get(url, options, &callback)
21
24
  end
22
25
 
23
- def put(url, params = nil, &callback)
24
- client.put(url, params, &callback)
26
+ def post(url, options = nil, &callback)
27
+ client.post(url, options, &callback)
25
28
  end
26
29
 
27
- def patch(url, params = nil, &callback)
28
- client.patch(url, params, &callback)
30
+ def put(url, options = nil, &callback)
31
+ client.put(url, options, &callback)
29
32
  end
30
33
 
31
- def delete(url, params = nil, &callback)
32
- client.delete(url, params, &callback)
34
+ def patch(url, options = nil, &callback)
35
+ client.patch(url, options, &callback)
36
+ end
37
+
38
+ def delete(url, options = nil, &callback)
39
+ client.delete(url, options, &callback)
40
+ end
41
+
42
+ def head(url, options = nil, &callback)
43
+ client.head(url, options, &callback)
44
+ end
45
+
46
+ def options(url, options = nil, &callback)
47
+ client.options(url, options, &callback)
48
+ end
49
+
50
+ def trace(url, options = nil, &callback)
51
+ client.trace(url, options, &callback)
33
52
  end
34
53
  end
35
54
  end
36
55
  end
56
+
57
+ HTTP = Motion::HTTP # alias as simply HTTP
data/lib/motion-http.rb CHANGED
@@ -4,6 +4,8 @@ unless defined?(Motion::Project::Config)
4
4
  raise "This gem is only intended to be used in a RubyMotion project."
5
5
  end
6
6
 
7
+ require 'motion-lager'
8
+
7
9
  lib_dir_path = File.dirname(File.expand_path(__FILE__))
8
10
  Motion::Project::App.setup do |app|
9
11
  app.files.unshift(*Dir.glob(File.join(lib_dir_path, "common/**/*.rb")))
@@ -12,15 +14,10 @@ Motion::Project::App.setup do |app|
12
14
  when :android
13
15
  require "motion-gradle"
14
16
  app.files.unshift(*Dir.glob(File.join(lib_dir_path, "android/**/*.rb")))
15
- app.gradle do
16
- dependency "com.squareup.okhttp3:okhttp:3.9.0"
17
- end
17
+ app.permissions << :internet
18
+ app.gradle { dependency 'com.android.volley:volley:1.1.1' }
18
19
  when :ios, :tvos, :osx, :watchos, :'ios-extension'
19
- require "motion-cocoapods"
20
20
  app.files.unshift(*Dir.glob(File.join(lib_dir_path, "cocoa/**/*.rb")))
21
- app.pods do
22
- pod "AFNetworking", "~> 3.1"
23
- end
24
21
  else
25
22
  raise "Project template #{Motion::Project::App.template} not supported by motion-http"
26
23
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: motion-http
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Havens
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-03-26 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2021-10-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: motion-lager
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'
13
27
  description: A cross-platform HTTP client for RubyMotion that's quick and easy to
14
28
  use.
15
29
  email:
@@ -20,19 +34,26 @@ extra_rdoc_files: []
20
34
  files:
21
35
  - README.md
22
36
  - lib/android/adapter.rb
37
+ - lib/android/base64.rb
23
38
  - lib/android/json.rb
39
+ - lib/android/params_encoder.rb
40
+ - lib/android/volley_request.rb
24
41
  - lib/cocoa/adapter.rb
42
+ - lib/cocoa/base64.rb
43
+ - lib/cocoa/json.rb
44
+ - lib/cocoa/params_encoder.rb
25
45
  - lib/common/http.rb
26
46
  - lib/common/http/client.rb
27
47
  - lib/common/http/headers.rb
48
+ - lib/common/http/logger.rb
28
49
  - lib/common/http/request.rb
29
50
  - lib/common/http/response.rb
30
51
  - lib/motion-http.rb
31
- homepage: https://github.com/andrewhavens/motion-http
52
+ homepage: https://github.com/rubymotion-community/motion-http
32
53
  licenses:
33
54
  - MIT
34
55
  metadata: {}
35
- post_install_message:
56
+ post_install_message:
36
57
  rdoc_options: []
37
58
  require_paths:
38
59
  - lib
@@ -47,9 +68,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
47
68
  - !ruby/object:Gem::Version
48
69
  version: '0'
49
70
  requirements: []
50
- rubyforge_project:
51
- rubygems_version: 2.6.13
52
- signing_key:
71
+ rubygems_version: 3.2.15
72
+ signing_key:
53
73
  specification_version: 4
54
74
  summary: A cross-platform HTTP client for RubyMotion that's quick and easy to use.
55
75
  test_files: []