xsr 1.0.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 1ee83ab8ac671bbbc63a6e1dd9fe9e1094617265
4
+ data.tar.gz: e33c6b188b742d4ceb395e3b14beba659579c3fb
5
+ SHA512:
6
+ metadata.gz: 240808f43cef65593b98b4ada88f7970201929586c9485e2ea5d60a45dc06700413117f689295923d610f7cf99f3389a67a0c3433e6d2b8a5407a1f1e72701d9
7
+ data.tar.gz: a2398e4e935dad8f11c70f3203797ba292392312f084300e02351ce94c130fcfd944d8b7df8c7d2584feb5280a9cbd473cd1719e0960745104de5b586e07f8fc
data/.gitignore ADDED
@@ -0,0 +1,36 @@
1
+ .gitignore
2
+ *.gem
3
+ *.gs
4
+ *.rbc
5
+ /.config
6
+ /coverage/
7
+ /InstalledFiles
8
+ /pkg/
9
+ /spec/reports/
10
+ /test/tmp/
11
+ /test/version_tmp/
12
+ /tmp/
13
+
14
+ ## Specific to RubyMotion:
15
+ .dat*
16
+ .repl_history
17
+ build/
18
+
19
+ ## Documentation cache and generated files:
20
+ /.yardoc/
21
+ /_yardoc/
22
+ /doc/
23
+ /rdoc/
24
+
25
+ ## Environment normalisation:
26
+ /.bundle/
27
+ /lib/bundler/man/
28
+
29
+ # for a library or gem, you might want to ignore these files since the code is
30
+ # intended to run in multiple environments; otherwise, check them in:
31
+ # Gemfile.lock
32
+ # .ruby-version
33
+ # .ruby-gemset
34
+
35
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
36
+ .rvmrc
data/README.md ADDED
@@ -0,0 +1,104 @@
1
+ # XSR - eXtremely Simple REST client
2
+
3
+ XSR is an extremely simple REST client aimed to use against JSON/REST APIs.
4
+
5
+ ## Installation
6
+
7
+ Simply run
8
+
9
+ ``` console
10
+ $ gem install xsr
11
+ ```
12
+
13
+ ### Using Rails?
14
+
15
+ Add the following line to your Gemfile:
16
+
17
+ ``` ruby
18
+ gem 'xsr'
19
+ ```
20
+
21
+ ## Usage
22
+
23
+ Create a new instance of XSR client specifying the base_url for wich you will be requesting further paths:
24
+
25
+ ``` ruby
26
+ require 'xsr'
27
+ client = XSR::Client.new
28
+ ```
29
+
30
+ And then invoke a service:
31
+
32
+ ``` ruby
33
+ resp = client.get('http://api.something.io')
34
+ resp.success?
35
+ #=> true
36
+ resp.body
37
+ #=> JSON response as a Ruby Hash Object
38
+ ```
39
+ ###Supported HTTP verbs
40
+ Implemented verbs are GET, POST, PUT and DELETE. To change the verb simply invoke the corresponding method:
41
+ ####HTTP GET
42
+ This will make a HTTP GET request to http://api.something.io
43
+ ``` ruby
44
+ client.get('http://api.something.io')
45
+ ```
46
+ ####HTTP POST
47
+ This will make a HTTP POST request to http://api.something.io
48
+ ``` ruby
49
+ client.post('http://api.something.io')
50
+ ```
51
+ ####HTTP PUT
52
+ This will make a HTTP PUT request to http://api.something.io
53
+ ``` ruby
54
+ client.put('http://api.something.io')
55
+ ```
56
+ ####HTTP DELETE
57
+ This will make a HTTP DELETE request to http://api.something.io
58
+ ``` ruby
59
+ client.delete('http://api.something.io')
60
+ ```
61
+
62
+ ###Using query string arguments
63
+ This will make a HTTP GET request to http://api.somthing.io?arg1=a&arg2=b
64
+ ``` ruby
65
+ client.get('http://api.something.io', args: {arg1: 'a', arg2: 'b'})
66
+ ```
67
+
68
+ ###Passing JSON arguments in request body
69
+ ``` ruby
70
+ req = { some_key: some_value, other_key: [1,2,3] }
71
+ client.post('http://api.something.io', body: req)
72
+ ```
73
+
74
+ ###Using HTTP headers
75
+ This will make a HTTP GET request to http://api.somthing.io passing 'Some-Header: Some-Value' in the HTTP headers
76
+ ``` ruby
77
+ resp = client.get('http://api.something.io', header: {some_header: 'some_value'})
78
+ ```
79
+
80
+ ###Response object
81
+ HTTP response comes in the form of a ```XSR::Response``` object:
82
+ ``` ruby
83
+ resp = client.post('http://api.something.io')
84
+
85
+ resp.success?
86
+ #=> Response status code is 2xx
87
+
88
+ resp.bad_request?
89
+ #=> Response status code is 403
90
+
91
+ resp.not_found?
92
+ #=> Response status code is 404
93
+
94
+ resp.server_error?
95
+ #=> Response status code is 500
96
+
97
+ resp.body
98
+ #=> JSON response as a Ruby Hash object
99
+ ```
100
+
101
+ ##What's next?
102
+ I'm not planning to add more features right now, but feel free to fork this repo and add any extra functionality you consider that should be included. Please, submit a PR with proposed changes or fixes.
103
+ Just keep in mind a minimalist paradigm (https://youtu.be/tXVr2E1vfmk).
104
+
data/lib/xsr.rb ADDED
@@ -0,0 +1,7 @@
1
+ require 'open-uri'
2
+ require 'net/http'
3
+ require 'multi_json'
4
+ require 'openssl'
5
+
6
+ require 'xsr/client'
7
+ require 'xsr/response'
data/lib/xsr/client.rb ADDED
@@ -0,0 +1,52 @@
1
+ module XSR
2
+ class Client
3
+ attr_accessor :base_url
4
+ attr_accessor :default_header
5
+
6
+ def initialize(options = {})
7
+ @base_url = options[:base_url]
8
+ @base_header = options[:header]
9
+ end
10
+
11
+ def post(path, options = {})
12
+ request_with_data(path, options) { |uri| Net::HTTP::Post.new(uri.to_s) }
13
+ end
14
+
15
+ def delete(path, options = {})
16
+ request_with_data(path, options) { |uri| Net::HTTP::Delete.new(uri.to_s) }
17
+ end
18
+
19
+ def put(path, options = {})
20
+ request_with_data(path, options) { |uri| Net::HTTP::Put.new(uri.to_s) }
21
+ end
22
+
23
+ def get(path, options = {})
24
+ request_with_data(path, options) { |uri| Net::HTTP::Get.new(uri.to_s) }
25
+ end
26
+
27
+ private
28
+ def request_with_data(path, options = {})
29
+ args = options[:args] && URI::encode( options[:args].map{|k,v| "#{k}=#{v}"}.join('&').to_s )
30
+ uri = URI( @base_url.to_s + path.to_s + '?' + args.to_s )
31
+
32
+ req = yield(uri)
33
+
34
+ # Set headers
35
+ req['Content-Type'] = 'application/json'
36
+ @base_header && @base_header.each{ |k,v| req[k] = v }
37
+ options[:header] && options[:header].each{ |k,v| req[k] = v }
38
+
39
+ # Set body
40
+ req.body = options[:body] && MultiJson.dump( options[:body] )
41
+
42
+ http_session = Net::HTTP.new(uri.host, uri.port)
43
+
44
+ if uri.scheme == 'https' # Requires SSL?
45
+ http_session.use_ssl = true
46
+ http_session.verify_mode = OpenSSL::SSL::VERIFY_NONE
47
+ end
48
+
49
+ XSR::Response.new( http_session.start{ |http| http.request(req) } )
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,31 @@
1
+ module XSR
2
+ class Response
3
+ attr_reader :http_response
4
+
5
+ def initialize(http_response)
6
+ @http_response = http_response
7
+ end
8
+
9
+ def success?
10
+ @http_response.is_a? Net::HTTPSuccess
11
+ end
12
+
13
+ def bad_request?
14
+ @http_response.is_a? Net::HTTPBadRequest
15
+ end
16
+
17
+ def not_found?
18
+ @http_response.is_a? Net::HTTPNotFound
19
+ end
20
+
21
+ def server_error?
22
+ @http_response.is_a? Net::HTTPServerError
23
+ end
24
+
25
+ def body
26
+ if self.success?
27
+ @http_response.body && MultiJson.load( @http_response.body, symbolize_keys: true )
28
+ end
29
+ end
30
+ end
31
+ end
data/makefile ADDED
@@ -0,0 +1,5 @@
1
+ .PHONY: test
2
+
3
+ test:
4
+ @echo Running tests... && \
5
+ RUBYLIB=./lib cutest test/*_test.rb
@@ -0,0 +1,68 @@
1
+ require 'xsr'
2
+ require_relative 'helper'
3
+
4
+ module ClientTest
5
+ prepare do
6
+ @client = XSR::Client.new( base_url: 'http://httpbin.org' )
7
+ end
8
+
9
+ test "get request" do
10
+ resp = @client.get('/get')
11
+
12
+ assert resp.http_response.instance_of?(Net::HTTPOK)
13
+ end
14
+
15
+ test "post request" do
16
+ req = {some_key: 'some_value'}
17
+ resp = @client.post( '/post', {body: req} )
18
+
19
+ assert resp.http_response.instance_of?(Net::HTTPOK)
20
+ assert_equal MultiJson.load(resp.http_response.body, symbolize_keys: true)[:json], req
21
+ end
22
+
23
+ test 'put request' do
24
+ req = {some_key: 'some_value'}
25
+ resp = @client.put( '/put', {body: req} )
26
+
27
+ assert resp.http_response.instance_of?(Net::HTTPOK)
28
+ assert_equal MultiJson.load(resp.http_response.body, symbolize_keys: true)[:json], req
29
+ end
30
+
31
+ test 'delete request' do
32
+ req = {some_key: 'some_value'}
33
+ resp = @client.delete( '/delete', {body: req} )
34
+
35
+ assert resp.http_response.instance_of?(Net::HTTPOK)
36
+ assert_equal MultiJson.load(resp.http_response.body, symbolize_keys: true)[:json], req
37
+ end
38
+
39
+ test 'headers are passed to request' do
40
+ h = { 'Some-Header' => 'some_value'}
41
+ resp = @client.get( '/headers', {header: h} )
42
+
43
+ assert resp.http_response.instance_of?(Net::HTTPOK)
44
+ assert_equal MultiJson.load(resp.http_response.body)['headers']['Some-Header'], 'some_value'
45
+ end
46
+
47
+ test 'default headers are passed to request' do
48
+ h = { 'Some-Header' => 'some_value'}
49
+ resp = XSR::Client.new(header: h).get( 'https://httpbin.org/headers' )
50
+
51
+ assert resp.http_response.instance_of?(Net::HTTPOK)
52
+ assert_equal MultiJson.load(resp.http_response.body)['headers']['Some-Header'], 'some_value'
53
+ end
54
+
55
+ test 'query string arguments are passed to request' do
56
+ p = {some_arg: 'some_value'}
57
+ resp = @client.get( '/get', {args: p} )
58
+ assert resp.http_response.instance_of?(Net::HTTPOK)
59
+
60
+ assert_equal MultiJson.load(resp.http_response.body)['args']['some_arg'], 'some_value'
61
+ end
62
+
63
+ test 'https request' do
64
+ resp = XSR::Client.new.get('https://httpbin.org/get')
65
+
66
+ assert resp.http_response.instance_of?(Net::HTTPOK)
67
+ end
68
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,6 @@
1
+ require 'securerandom'
2
+
3
+ def random_hash
4
+ {SecureRandom.hex => SecureRandom.hex}
5
+ end
6
+
@@ -0,0 +1,57 @@
1
+ require 'xsr'
2
+ require_relative 'helper'
3
+
4
+ module ResponseTest
5
+ prepare do
6
+ @client = XSR::Client.new( base_url: 'http://httpbin.org' )
7
+ end
8
+
9
+ test "status 200 is a successful response" do
10
+ resp = @client.get('/status/200')
11
+ assert resp.success?
12
+ end
13
+
14
+ test "status 201 is a successful response" do
15
+ resp = @client.get('/status/201')
16
+ assert resp.success?
17
+ end
18
+
19
+ test "status 202 is a successful response" do
20
+ resp = @client.get('/status/202')
21
+ assert resp.success?
22
+ end
23
+
24
+ test "status 400 is a successful response" do
25
+ resp = @client.get('/status/400')
26
+ assert !resp.success?
27
+ assert resp.bad_request?
28
+ end
29
+
30
+ test "status 404 is a successful response" do
31
+ resp = @client.get('/status/404')
32
+ assert !resp.success?
33
+ assert resp.not_found?
34
+ end
35
+
36
+ test "status 500 is a successful response" do
37
+ resp = @client.get('/status/500')
38
+ assert !resp.success?
39
+ assert resp.server_error?
40
+ end
41
+
42
+ test "simple body" do
43
+ req = {some_attrib: 'some_value'}
44
+ resp = @client.post('/post', body: req)
45
+
46
+ assert resp.success?
47
+ assert_equal resp.body[:json], req
48
+ end
49
+
50
+ test "body with nested attributes" do
51
+ req = {something: {some_attrib: 'some_value'}}
52
+ resp = @client.post('/post', body: req)
53
+
54
+ assert resp.success?
55
+ assert_equal resp.body[:json], req
56
+ end
57
+ end
data/xsr.gemspec ADDED
@@ -0,0 +1,15 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'xsr'
3
+ s.version = '1.0.0'
4
+ s.summary = "XSR: eXtremely Simple REST Client"
5
+ s.description = "A very simple library to talk to a REST/JSON API"
6
+ s.authors = ["Matias Owsianik"]
7
+ s.email = ['matiasow@gmail.com']
8
+ s.homepage = 'http://github.com/matiasow/xsr'
9
+ s.license = 'MIT'
10
+
11
+ s.files = `git ls-files`.split("\n")
12
+
13
+ s.add_dependency "multi_json"
14
+ s.add_development_dependency "cutest"
15
+ end
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: xsr
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Matias Owsianik
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-03-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: multi_json
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: cutest
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: A very simple library to talk to a REST/JSON API
42
+ email:
43
+ - matiasow@gmail.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ".gitignore"
49
+ - README.md
50
+ - lib/xsr.rb
51
+ - lib/xsr/client.rb
52
+ - lib/xsr/response.rb
53
+ - makefile
54
+ - test/client_test.rb
55
+ - test/helper.rb
56
+ - test/response_test.rb
57
+ - xsr.gemspec
58
+ homepage: http://github.com/matiasow/xsr
59
+ licenses:
60
+ - MIT
61
+ metadata: {}
62
+ post_install_message:
63
+ rdoc_options: []
64
+ require_paths:
65
+ - lib
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ required_rubygems_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ requirements: []
77
+ rubyforge_project:
78
+ rubygems_version: 2.4.5
79
+ signing_key:
80
+ specification_version: 4
81
+ summary: 'XSR: eXtremely Simple REST Client'
82
+ test_files: []