ruby_http_client 1.0.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: 962d8241ec81889b1f89348c24fd6cc490a9aa98
4
+ data.tar.gz: 4cceab98eddf6359e7e8173e511b1018b803f882
5
+ SHA512:
6
+ metadata.gz: 9c75159dfae79c5f06a7b1590aaa0d985e389099c87e258c381371993d524e2114eaabe9f7055eda1caa12c5a7cbace192fd22960cdbb93b168b96ffb7d02681
7
+ data.tar.gz: b13713f036cdd34a1054b6aa0cb046261c4787a9252575d0cbf335003d002477c77e49391458c75fec8b795d31ba931c1d4e2b2c3da9a133f2c79f57a8019d3a
data/.env_sample ADDED
@@ -0,0 +1,4 @@
1
+ HOST=<base_url_for_live_api_host>
2
+ MOCK_HOST=<base_url_for_remote_mocked_api_host>
3
+ LOCAL_HOST=<base_url_for_local_mocked_api_host>
4
+ SENDGRID_API_KEY=<your_sendgrid_api_key>
@@ -0,0 +1,17 @@
1
+ #### Issue Summary
2
+
3
+ A summary of the issue and the environment in which it occurs. If suitable, include the steps required to reproduce the bug. Please feel free to include screenshots, screencasts, code examples.
4
+
5
+
6
+ #### Steps to Reproduce
7
+
8
+ 1. This is the first step
9
+ 2. This is the second step
10
+ 3. Further steps, etc.
11
+
12
+ Any other information you want to share that is relevant to the issue being reported. Especially, why do you consider this to be a bug? What do you expect to happen instead?
13
+
14
+ #### Technical details:
15
+
16
+ * ruby-http-client Version: master (latest commit: [commit number])
17
+ * Ruby Version: 2.2
data/.gitignore ADDED
@@ -0,0 +1,37 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /spec/examples.txt
9
+ /test/tmp/
10
+ /test/version_tmp/
11
+ /tmp/
12
+
13
+ ## Specific to RubyMotion:
14
+ .dat*
15
+ .repl_history
16
+ build/
17
+
18
+ ## Documentation cache and generated files:
19
+ /.yardoc/
20
+ /_yardoc/
21
+ /doc/
22
+ /rdoc/
23
+
24
+ ## Environment normalization:
25
+ /.bundle/
26
+ /vendor/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
37
+ .env
data/.travis.yml ADDED
@@ -0,0 +1,15 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2
4
+ notifications:
5
+ hipchat:
6
+ rooms:
7
+ secure: gYBEwOGBTxHE2nrxsHQqp2UdjRtCX04wVLYEimeT9RG/0LClS4nzJF7DaXLWlAwgLPmk+KV2+nXuLO5oausBr9ODmWhho8G0F90RPR47NupcvT1RM+I2ZbxSjHCUICL22mdnZd8ye/mrk/YtFWYmgmH7ILRK3BuYovXFoKoRnLg=
8
+ template:
9
+ - '<a href="https://travis-ci.org/%{repository}/builds/%{build_id}">%{repository}
10
+ Build %{build_number}</a> on branch <i>%{branch}</i> by %{author}: <strong>%{message}</strong>
11
+ <a href="https://github.com/sendgrid/%{repository}/commits/%{commit}">View on GitHub</a>'
12
+ format: html
13
+ notify: false
14
+ script:
15
+ - rake
data/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ # Change Log
2
+ All notable changes to this project will be documented in this file.
3
+ This project adheres to [Semantic Versioning](http://semver.org/).
4
+
5
+ ## [1.0.0] - 2016-03-17
6
+ ### Added
7
+ - We are live!
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,194 @@
1
+ Hello! Thank you for choosing to help contribute to the ruby-http-client. There are many ways you can contribute and help is always welcome.
2
+
3
+ We use [Milestones](https://github.com/sendgrid/ruby-http-client/milestones) to help define current roadmaps, please feel free to grab an issue from the current milestone. Please indicate that you have begun work on it to avoid collisions. Once a PR is made, community review, comments, suggestions and additional PRs are welcomed and encouraged.
4
+
5
+ * [Feature Request](#feature_request)
6
+ * [Submit a Bug Report](#submit_a_bug_report)
7
+ * [Improvements to the Codebase](#improvements_to_the_codebase)
8
+ * [Understanding the Code Base](#understanding_the_codebase)
9
+ * [Testing](#testing)
10
+ * [Style Guidelines & Naming Conventions](#style_guidelines_and_naming_conventions)
11
+ * [Creating a Pull Request](#creating_a_pull_request)
12
+
13
+ There are a few ways to contribute, which we'll enumerate below:
14
+
15
+ <a name="feature_request"></a>
16
+ ## Feature Request
17
+
18
+ If you'd like to make a feature request, please read this section.
19
+
20
+ The GitHub issue tracker is the preferred channel for library feature requests, but please respect the following restrictions:
21
+
22
+ - Please **search for existing issues** in order to ensure we don't have duplicate bugs/feature requests.
23
+ - Please be respectful and considerate of others when commenting on issues
24
+
25
+ <a name="submit_a_bug_report"></a>
26
+ ## Submit a Bug Report
27
+
28
+ Note: DO NOT include your credentials in ANY code examples, descriptions, or media you make public.
29
+
30
+ A software bug is a demonstrable issue in the code base. In order for us to diagnose the issue and respond as quickly as possible, please add as much detail as possible into your bug report.
31
+
32
+ Before you decide to create a new issue, please try the following:
33
+
34
+ 1. Check the Github issues tab if the identified issue has already been reported, if so, please add a +1 to the existing post.
35
+ 2. Update to the latest version of this code and check if issue has already been fixed
36
+ 3. Copy and fill in the Bug Report Template we have provided below
37
+
38
+ ### Please use our Bug Report Template
39
+
40
+ In order to make the process easier, we've included a sample bug report template (borrowed from [Ghost](https://github.com/TryGhost/Ghost/)). The template uses [GitHub flavored markdown](https://help.github.com/articles/github-flavored-markdown/) for formatting.
41
+
42
+ ```
43
+ Short and descriptive example bug report title
44
+
45
+ #### Issue Summary
46
+
47
+ A summary of the issue and the environment in which it occurs. If suitable, include the steps required to reproduce the bug. Please feel free to include screenshots, screencasts, code examples.
48
+
49
+
50
+ #### Steps to Reproduce
51
+
52
+ 1. This is the first step
53
+ 2. This is the second step
54
+ 3. Further steps, etc.
55
+
56
+ Any other information you want to share that is relevant to the issue being reported. Especially, why do you consider this to be a bug? What do you expect to happen instead?
57
+
58
+ #### Technical details:
59
+
60
+ * ruby-http-client Version: master (latest commit: 2cb34372ef0f31352f7c90015a45e1200cb849da)
61
+ * Ruby Version: 2.2
62
+ ```
63
+
64
+ <a name="improvements_to_the_codebase"></a>
65
+ ## Improvements to the Codebase
66
+
67
+ We welcome direct contributions to the python-http-client code base. Thank you!
68
+
69
+ ### Development Environment ###
70
+
71
+ #### Install and run locally ####
72
+
73
+ ##### Prerequisites #####
74
+
75
+ * Ruby 2.2
76
+ * There are no external dependencies
77
+
78
+ ##### Initial setup: #####
79
+
80
+ ```
81
+ git clone https://github.com/sendgrid/ruby-http-client.git
82
+ cd ruby-http-client
83
+ cp .env_sample .env
84
+ ```
85
+
86
+ Update your settings in `.env`
87
+
88
+ ##### Execute: #####
89
+
90
+ See the [examples folder](https://github.com/sendgrid/ruby-http-client/tree/master/examples) to get started quickly.
91
+
92
+ <a name="understanding_the_codebase"></a>
93
+ ## Understanding the Code Base
94
+
95
+ **/examples**
96
+
97
+ Working examples that demonstrate usage.
98
+
99
+ **ruby_http_client.rb**
100
+
101
+ An HTTP client with a fluent interface using method chaining and reflection. By returning self on [method_missing](https://github.com/sendgrid/ruby-http-client/blob/master/lib/ruby_http_client.rb#L209) and [_()](https://github.com/sendgrid/ruby-http-client/blob/master/lib/ruby_http_client.rb#L194), we can dynamically build the URL using method chaining and [method_missing](https://github.com/sendgrid/ruby-http-client/blob/master/lib/ruby_http_client.rb#L209) allows us to dynamically receive the method calls to achieve reflection.
102
+
103
+ This allows for the following mapping from a URL to a method chain:
104
+
105
+ `/api_client/{api_key_id}/version` maps to `client.api_client._(api_key_id).version.<method>()` where <method> is a [HTTP verb](https://github.com/sendgrid/ruby-http-client/blob/master/lib/ruby_http_client.rb#L38).
106
+
107
+ **congfig.rb**
108
+
109
+ Loads the environment variables.
110
+
111
+ <a name="testing"></a>
112
+ ## Testing
113
+
114
+ All PRs require passing tests before the PR will be reviewed.
115
+
116
+ All test files are in the `[test](https://github.com/sendgrid/ruby-http-client/tree/master/test)` directory.
117
+
118
+ For the purposes of contributing to this repo, please update the [`test_ruby_http_client.rb`](https://github.com/sendgrid/ruby-http-client/blob/master/test/test_ruby_http_client.rb) file with unit tests as you modify the code.
119
+
120
+ To run the tests:
121
+
122
+ `rake`
123
+
124
+ All PRs require passing tests before the PR will be reviewed.
125
+
126
+ <a name="style_guidelines_and_naming_conventions"></a>
127
+ ## Style Guidelines & Naming Conventions
128
+
129
+ Generally, we follow the style guidelines as suggested by the official language. However, we ask that you conform to the styles that already exist in the library. If you wish to deviate, please explain your reasoning.
130
+
131
+ * [Community Driven Style Guide](https://github.com/bbatsov/ruby-style-guide)
132
+
133
+ Please run your code through [rubocop](https://github.com/bbatsov/rubocop).
134
+
135
+ ### Directory Structure
136
+
137
+ * `examples` for example calls
138
+ * `test`, for all tests
139
+ * `libs`, for the client library
140
+
141
+ ## Creating a Pull Request<a name="creating_a_pull_request"></a>
142
+
143
+ 1. [Fork](https://help.github.com/fork-a-repo/) the project, clone your fork,
144
+ and configure the remotes:
145
+
146
+ ```bash
147
+ # Clone your fork of the repo into the current directory
148
+ git clone https://github.com/sendgrid/ruby-http-client
149
+ # Navigate to the newly cloned directory
150
+ cd ruby-http-client
151
+ # Assign the original repo to a remote called "upstream"
152
+ git remote add upstream https://github.com/sendgrid/ruby-http-client
153
+ ```
154
+
155
+ 2. If you cloned a while ago, get the latest changes from upstream:
156
+
157
+ ```bash
158
+ git checkout <dev-branch>
159
+ git pull upstream <dev-branch>
160
+ ```
161
+
162
+ 3. Create a new topic branch (off the main project development branch) to
163
+ contain your feature, change, or fix:
164
+
165
+ ```bash
166
+ git checkout -b <topic-branch-name>
167
+ ```
168
+
169
+ 4. Commit your changes in logical chunks. Please adhere to these [git commit
170
+ message guidelines](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html)
171
+ or your code is unlikely be merged into the main project. Use Git's
172
+ [interactive rebase](https://help.github.com/articles/interactive-rebase)
173
+ feature to tidy up your commits before making them public.
174
+
175
+ 4a. Create tests.
176
+
177
+ 4b. Create or update the example code that demonstrates the functionality of this change to the code.
178
+
179
+ 5. Locally merge (or rebase) the upstream development branch into your topic branch:
180
+
181
+ ```bash
182
+ git pull [--rebase] upstream master
183
+ ```
184
+
185
+ 6. Push your topic branch up to your fork:
186
+
187
+ ```bash
188
+ git push origin <topic-branch-name>
189
+ ```
190
+
191
+ 7. [Open a Pull Request](https://help.github.com/articles/using-pull-requests/)
192
+ with a clear title and description against the `master` branch. All tests must be passing before we will review the PR.
193
+
194
+ If you have any additional questions, please feel free to [email](mailto:dx@sendgrid.com) us or create an issue in this repo.
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 SendGrid
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 all
13
+ 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 THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,133 @@
1
+ [![Travis Badge](https://travis-ci.org/sendgrid/python-http-client.svg?branch=master)](https://travis-ci.org/sendgrid/ruby-http-client)
2
+
3
+ **Quickly and easily access any REST or REST-like API.**
4
+
5
+ Here is a quick example:
6
+
7
+ `GET /your/api/{param}/call`
8
+
9
+ ```ruby
10
+ require ruby_http_client
11
+ global_headers = {'Authorization' => 'Basic XXXXXXX' }
12
+ client = SendGrid::Client(host: 'base_url', request_headers: global_headers)
13
+ client.your.api._(param).call.get
14
+ puts response.status_code
15
+ puts response.response_body
16
+ puts response.response_headers
17
+ ```
18
+
19
+ `POST /your/api/{param}/call` with headers, query parameters and a request body with versioning.
20
+
21
+ ```ruby
22
+ import ruby_http_client
23
+ global_headers = {'Authorization' => 'Basic XXXXXXX' }
24
+ client = SendGrid::Client(host: 'base_url', request_headers: global_headers)
25
+ query_params = { 'hello' => 0, 'world' => 1 }
26
+ request_headers = { 'X-Test' => 'test' }
27
+ data = { 'some' => 1, 'awesome' => 2, 'data' => 3}
28
+ response = client.your.api._(param).call.post(request_body: data,
29
+ query_params: query_params,
30
+ request_headers: request_headers)
31
+ puts response.status_code
32
+ puts response.response_body
33
+ puts response.response_headers
34
+ ```
35
+
36
+ # Installation
37
+
38
+ `gem install ruby_http_client`
39
+
40
+ ## Usage ##
41
+
42
+ Following is an example using SendGrid. You can get your free account [here](https://sendgrid.com/free?source=python-http-client).
43
+
44
+ First, update your .env with your [SENDGRID_API_KEY](https://app.sendgrid.com/settings/api_keys) and HOST. For this example HOST=https://api.sendgrid.com.
45
+
46
+ Following is an abridged example, here is the [full working code](https://github.com/sendgrid/ruby-http-client/tree/master/examples).
47
+
48
+ ```ruby
49
+ require ruby_http_client
50
+
51
+ Config.new
52
+ headers = JSON.parse('
53
+ {
54
+ "Authorization": "Bearer ' + ENV['SENDGRID_API_KEY'] + '",
55
+ "Content-Type": "application/json"
56
+ }
57
+ ')
58
+ host = ENV['LOCAL_HOST']
59
+ client = SendGrid::Client.new(host: host, request_headers: headers)
60
+
61
+ # GET Collection
62
+ query_params = { 'limit' => 100, 'offset' => 0 }
63
+ response = client.version('v3').api_keys.get(query_params: query_params)
64
+
65
+ # POST
66
+ request_body = JSON.parse('
67
+ {
68
+ "name": "My API Key Ruby Test",
69
+ "scopes": [
70
+ "mail.send",
71
+ "alerts.create",
72
+ "alerts.read"
73
+ ]
74
+ }
75
+ ')
76
+ response = client.version('v3').api_keys.post(request_body: request_body)
77
+ api_key_id = JSON.parse(response.response_body)['api_key_id']
78
+
79
+ # GET Single
80
+ response = client.version('v3').api_keys._(api_key_id).get
81
+
82
+ # PATCH
83
+ request_body = JSON.parse('
84
+ {
85
+ "name": "A New Hope"
86
+ }
87
+ ')
88
+ response = client.api_keys._(api_key_id).patch(request_body: request_body)
89
+
90
+ # PUT
91
+ request_body = JSON.parse('
92
+ {
93
+ "name": "A New Hope",
94
+ "scopes": [
95
+ "user.profile.read",
96
+ "user.profile.update"
97
+ ]
98
+ }
99
+ ')
100
+ response = client.api_keys._(api_key_id).put(request_body: request_body)
101
+
102
+ # DELETE
103
+ response = client.api_keys._(api_key_id).delete
104
+ ```
105
+
106
+ # Announcements
107
+
108
+ [2016.03.17] - We hit version 1!
109
+
110
+ # Roadmap
111
+
112
+ [Milestones](https://github.com/sendgrid/ruby-http-client/milestones)
113
+
114
+ # How to Contribute
115
+
116
+ We encourage contribution to our libraries, please see our [CONTRIBUTING](https://github.com/sendgrid/ruby-http-client/blob/master/CONTRIBUTING.md) guide for details.
117
+
118
+ * [Feature Request](https://github.com/sendgrid/ruby-http-client/blob/master/CONTRIBUTING.md#feature_request)
119
+ * [Bug Reports](https://github.com/sendgrid/ruby-http-client/blob/master/CONTRIBUTING.md#submit_a_bug_report)
120
+ * [Improvements to the Codebase](https://github.com/sendgrid/ruby-http-client/blob/master/CONTRIBUTING.md#improvements_to_the_codebase)
121
+
122
+ # Thanks
123
+
124
+ We were inspired by the work done on [birdy](https://github.com/inueni/birdy) and [universalclient](https://github.com/dgreisen/universalclient).
125
+
126
+ # About
127
+
128
+ ![SendGrid Logo]
129
+ (https://assets3.sendgrid.com/mkt/assets/logos_brands/small/sglogo_2015_blue-9c87423c2ff2ff393ebce1ab3bd018a4.png)
130
+
131
+ ruby-http-client is guided and supported by the SendGrid [Developer Experience Team](mailto:dx@sendgrid.com).
132
+
133
+ ruby-http-client is maintained and funded by SendGrid, Inc. The names and logos for ruby-http-client are trademarks of SendGrid, Inc.
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require 'rake/testtask'
2
+
3
+ Rake::TestTask.new do |t|
4
+ t.libs << 'test'
5
+ end
6
+
7
+ desc "Run tests"
8
+ task :default => :test
@@ -0,0 +1,73 @@
1
+ require_relative '../lib/config'
2
+ require_relative '../lib/ruby_http_client'
3
+
4
+ Config.new
5
+ headers = JSON.parse('
6
+ {
7
+ "Authorization": "Bearer ' + ENV['SENDGRID_API_KEY'] + '",
8
+ "Content-Type": "application/json"
9
+ }
10
+ ')
11
+ host = ENV['LOCAL_HOST']
12
+ client = SendGrid::Client.new(host: host, request_headers: headers)
13
+
14
+ # GET Collection
15
+ query_params = { 'limit' => 100, 'offset' => 0 }
16
+ response = client.version('v3').api_keys.get(query_params: query_params)
17
+ puts response.status_code
18
+ puts response.response_body
19
+ puts response.response_headers
20
+
21
+ # POST
22
+ request_body = JSON.parse('
23
+ {
24
+ "name": "My API Key Ruby Test",
25
+ "scopes": [
26
+ "mail.send",
27
+ "alerts.create",
28
+ "alerts.read"
29
+ ]
30
+ }
31
+ ')
32
+ response = client.version('v3').api_keys.post(request_body: request_body)
33
+ puts response.status_code
34
+ puts response.response_body
35
+ puts response.response_headers
36
+ api_key_id = JSON.parse(response.response_body)['api_key_id']
37
+
38
+ # GET Single
39
+ response = client.version('v3').api_keys._(api_key_id).get
40
+ puts response.status_code
41
+ puts response.response_body
42
+ puts response.response_headers
43
+
44
+ # PATCH
45
+ request_body = JSON.parse('
46
+ {
47
+ "name": "A New Hope"
48
+ }
49
+ ')
50
+ response = client.api_keys._(api_key_id).patch(request_body: request_body)
51
+ puts response.status_code
52
+ puts response.response_body
53
+ puts response.response_headers
54
+
55
+ # PUT
56
+ request_body = JSON.parse('
57
+ {
58
+ "name": "A New Hope",
59
+ "scopes": [
60
+ "user.profile.read",
61
+ "user.profile.update"
62
+ ]
63
+ }
64
+ ')
65
+ response = client.api_keys._(api_key_id).put(request_body: request_body)
66
+ puts response.status_code
67
+ puts response.response_body
68
+ puts response.response_headers
69
+
70
+ # DELETE
71
+ response = client.api_keys._(api_key_id).delete
72
+ puts response.status_code
73
+ puts response.response_headers
data/lib/config.rb ADDED
@@ -0,0 +1,10 @@
1
+ # Loads environment variables from a .env file.
2
+ class Config
3
+ def initialize
4
+ File.open('./.env').readlines.each do |line|
5
+ key, value = line.split '='
6
+ ENV[key] = value.chomp
7
+ end
8
+ ENV
9
+ end
10
+ end
@@ -0,0 +1,221 @@
1
+ # Quickly and easily access any REST or REST-like API.
2
+ module SendGrid
3
+ require 'json'
4
+ require 'net/http'
5
+ require 'net/https'
6
+
7
+ # Holds the response from an API call.
8
+ class Response
9
+ # * *Args* :
10
+ # - +response+ -> A NET::HTTP response object
11
+ #
12
+ attr_reader :status_code, :response_body, :response_headers
13
+ def initialize(response)
14
+ @status_code = response.code
15
+ @response_body = response.body
16
+ @response_headers = response.to_hash.inspect
17
+ end
18
+ end
19
+
20
+ # A simple REST client.
21
+ class Client
22
+ attr_reader :host, :request_headers, :url_path
23
+ # * *Args* :
24
+ # - +host+ -> Base URL for the api. (e.g. https://api.sendgrid.com)
25
+ # - +request_headers+ -> A hash of the headers you want applied on
26
+ # all calls
27
+ # - +version+ -> The version number of the API.
28
+ # Subclass add_version for custom behavior.
29
+ # Or just pass the version as part of the URL
30
+ # (e.g. client._("/v3"))
31
+ # - +url_path+ -> A list of the url path segments
32
+ #
33
+ def initialize(host: nil, request_headers: nil, version: nil, url_path: nil)
34
+ @host = host
35
+ @request_headers = request_headers ? request_headers : {}
36
+ @version = version
37
+ @url_path = url_path ? url_path : []
38
+ @methods = %w(delete get patch post put)
39
+ @query_params = nil
40
+ @request_body = nil
41
+ end
42
+
43
+ # Update the headers for the request
44
+ #
45
+ # * *Args* :
46
+ # - +request_headers+ -> Hash of request header key/values
47
+ #
48
+ def update_headers(request_headers)
49
+ @request_headers = @request_headers.merge(request_headers)
50
+ end
51
+
52
+ # Build the final request headers
53
+ #
54
+ # * *Args* :
55
+ # - +request+ -> HTTP::NET request object
56
+ # * *Returns* :
57
+ # - HTTP::NET request object
58
+ #
59
+ def build_request_headers(request)
60
+ @request_headers.each do |key, value|
61
+ request[key] = value
62
+ end
63
+ request
64
+ end
65
+
66
+ # Add the API version, subclass this function to customize
67
+ #
68
+ # * *Args* :
69
+ # - +url+ -> An empty url string
70
+ # * *Returns* :
71
+ # - The url string with the version pre-pended
72
+ #
73
+ def add_version(url)
74
+ url.concat("/#{@version}")
75
+ url
76
+ end
77
+
78
+ # Add query parameters to the url
79
+ #
80
+ # * *Args* :
81
+ # - +url+ -> path to endpoint
82
+ # - +query_params+ -> hash of query parameters
83
+ # * *Returns* :
84
+ # - The url string with the query parameters appended
85
+ #
86
+ def build_query_params(url, query_params)
87
+ url.concat('?')
88
+ count = 0
89
+ query_params.each do |key, value|
90
+ url.concat('&') if count > 0
91
+ url.concat("#{key}=#{value}")
92
+ count += 1
93
+ end
94
+ url
95
+ end
96
+
97
+ # Set the query params, request headers and request body
98
+ #
99
+ # * *Args* :
100
+ # - +args+ -> array of args obtained from method_missing
101
+ #
102
+ def build_args(args)
103
+ args.each do |arg|
104
+ arg.each do |key, value|
105
+ case key.to_s
106
+ when 'query_params'
107
+ @query_params = value
108
+ when 'request_headers'
109
+ update_headers(value)
110
+ when 'request_body'
111
+ @request_body = value
112
+ end
113
+ end
114
+ end
115
+ end
116
+
117
+ # Build the final url
118
+ #
119
+ # * *Args* :
120
+ # - +query_params+ -> A hash of query parameters
121
+ # * *Returns* :
122
+ # - The final url string
123
+ #
124
+ def build_url(query_params: nil)
125
+ url = ''
126
+ url = add_version(url) if @version
127
+ @url_path.each do |x|
128
+ url.concat("/#{x}")
129
+ end
130
+ url = build_query_params(url, query_params) if query_params
131
+ URI.parse("#{@host}#{url}")
132
+ end
133
+
134
+ # Build the API request for HTTP::NET
135
+ #
136
+ # * *Args* :
137
+ # - +name+ -> method name, received from method_missing
138
+ # - +args+ -> args passed to the method
139
+ # * *Returns* :
140
+ # - A Response object from make_request
141
+ #
142
+ def build_request(name, args)
143
+ build_args(args) if args
144
+ uri = build_url(query_params: @query_params)
145
+ http = Net::HTTP.new(uri.host, uri.port)
146
+ http = add_ssl(http)
147
+ net_http = Kernel.const_get('Net::HTTP::' + name.to_s.capitalize)
148
+ request = net_http.new(uri.request_uri)
149
+ request = build_request_headers(request)
150
+ request.body = @request_body.to_json if @request_body
151
+ make_request(http, request)
152
+ end
153
+
154
+ # Make the API call and return the response. This is separated into
155
+ # it's own function, so we can mock it easily for testing.
156
+ #
157
+ # * *Args* :
158
+ # - +http+ -> NET:HTTP request object
159
+ # - +request+ -> NET::HTTP request object
160
+ # * *Returns* :
161
+ # - Response object
162
+ #
163
+ def make_request(http, request)
164
+ response = http.request(request)
165
+ Response.new(response)
166
+ end
167
+
168
+ # Allow for https calls
169
+ #
170
+ # * *Args* :
171
+ # - +http+ -> HTTP::NET object
172
+ # * *Returns* :
173
+ # - HTTP::NET object
174
+ #
175
+ def add_ssl(http)
176
+ protocol = host.split(':')[0]
177
+ if protocol == 'https'
178
+ http.use_ssl = true
179
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
180
+ end
181
+ http
182
+ end
183
+
184
+ # Add variable values to the url.
185
+ # (e.g. /your/api/{variable_value}/call)
186
+ # Another example: if you have a ruby reserved word, such as true,
187
+ # in your url, you must use this method.
188
+ #
189
+ # * *Args* :
190
+ # - +name+ -> Name of the url segment
191
+ # * *Returns* :
192
+ # - Client object
193
+ #
194
+ def _(name = nil)
195
+ url_path = name ? @url_path.push(name) : @url_path
196
+ @url_path = []
197
+ Client.new(host: @host, request_headers: @request_headers,
198
+ version: @version, url_path: url_path)
199
+ end
200
+
201
+ # Dynamically add segments to the url, then call a method.
202
+ # (e.g. client.name.name.get())
203
+ #
204
+ # * *Args* :
205
+ # - The args are autmoatically passed in
206
+ # * *Returns* :
207
+ # - Client object or Response object
208
+ #
209
+ def method_missing(name, *args, &_block)
210
+ # Capture the version
211
+ if name.to_s == 'version'
212
+ @version = args[0]
213
+ return _
214
+ end
215
+ # We have reached the end of the method chain, make the API call
216
+ return build_request(name, args) if @methods.include?(name.to_s)
217
+ # Add a segment to the URL
218
+ _(name)
219
+ end
220
+ end
221
+ end
@@ -0,0 +1,22 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'ruby_http_client'
7
+ spec.version = '1.0.0'
8
+ spec.authors = ['Elmer Thomas']
9
+ spec.email = 'dx@sendgrid.com'
10
+ spec.summary = 'A simple REST client'
11
+ spec.description = 'Quickly and easily access any REST or REST-like API.'
12
+ spec.homepage = 'http://github.com/sendgrid/ruby-http-client'
13
+ spec.license = 'MIT'
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(/^bin/) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(/^(test|spec|features)/)
18
+ spec.require_paths = ['lib']
19
+
20
+ spec.add_development_dependency 'rake', '~> 0'
21
+ spec.add_development_dependency 'bundler', '~> 1.6'
22
+ end
@@ -0,0 +1,117 @@
1
+ require_relative '../lib/ruby_http_client'
2
+ require 'minitest/autorun'
3
+
4
+ class MockResponse
5
+ attr_reader :status_code, :response_body, :response_headers
6
+
7
+ def initialize(response)
8
+ @status_code = response['code']
9
+ @response_body = response['body']
10
+ @response_headers = response['headers']
11
+ end
12
+ end
13
+
14
+ class MockRequest < SendGrid::Client
15
+ def make_request(_http, _request)
16
+ response = {}
17
+ response['code'] = 200
18
+ response['body'] = { 'message' => 'success' }
19
+ response['headers'] = { 'headers' => 'test' }
20
+ MockResponse.new(response)
21
+ end
22
+ end
23
+
24
+ class TestClient < Minitest::Test
25
+ def setup
26
+ @headers = JSON.parse('
27
+ {
28
+ "Authorization": "Bearer XXXXXXX",
29
+ "Content-Type": "application/json"
30
+ }
31
+ ')
32
+ @host = 'http://localhost:4010'
33
+ @version = 'v3'
34
+ @client = MockRequest.new(host: @host,
35
+ request_headers: @headers,
36
+ version: @version)
37
+ end
38
+
39
+ def test_init
40
+ assert_equal(@host, @client.host)
41
+ assert_equal(@headers, @client.request_headers)
42
+ end
43
+
44
+ def test_update_headers
45
+ request_headers = { 'X-Test' => 'test' }
46
+ @client.update_headers(request_headers)
47
+ assert_equal(@headers.merge(request_headers), @client.request_headers)
48
+ end
49
+
50
+ def test_build_request_headers
51
+ request = {}
52
+ request = @client.build_request_headers(request)
53
+ assert_equal(@client.request_headers, request)
54
+ end
55
+
56
+ def test_add_version
57
+ url = ''
58
+ @client.add_version(url)
59
+ assert_equal(url, "/#{@version}")
60
+ end
61
+
62
+ def test_build_query_params
63
+ url = ''
64
+ query_params = { 'limit' => 100, 'offset' => 0 }
65
+ url = @client.build_query_params(url, query_params)
66
+ assert_equal(url, '?limit=100&offset=0')
67
+ end
68
+
69
+ def test_build_url
70
+ url1 = @client.my.path.to.the.endpoint
71
+ params = { 'limit' => 100, 'offset' => 0 }
72
+ url = URI.parse(@host + '/' + @version +
73
+ '/my/path/to/the/endpoint?limit=100&offset=0')
74
+ assert_equal(url1.build_url(query_params: params), url)
75
+
76
+ url1 = url1.one_more
77
+ params = { 'limit' => 100, 'offset' => 0 }
78
+ url = URI.parse(@host + '/' + @version +
79
+ '/my/path/to/the/endpoint/one_more?limit=100&offset=0')
80
+ assert_equal(url1.build_url(query_params: params), url)
81
+
82
+ url2 = @client.my.path._('to').the.endpoint
83
+ params = { 'limit' => 100, 'offset' => 0 }
84
+ url = URI.parse(@host + '/' + @version +
85
+ '/my/path/to/the/endpoint?limit=100&offset=0')
86
+ assert_equal(url2.build_url(query_params: params), url)
87
+ end
88
+
89
+ def test_build_request
90
+ name = 'get'
91
+ args = nil
92
+ response = @client.build_request(name, args)
93
+ assert_equal(response.status_code, 200)
94
+ assert_equal(response.response_body, 'message' => 'success')
95
+ assert_equal(response.response_headers, 'headers' => 'test')
96
+ end
97
+
98
+ def add_ssl
99
+ uri = URI.parse('https://localhost:4010')
100
+ http = Net::HTTP.new(uri.host, uri.port)
101
+ http = @client.add_ssl(http)
102
+ assert_equal(http.use_ssl, true)
103
+ assert_equal(http.verify_mode, OpenSSL::SSL::VERIFY_NONE)
104
+ end
105
+
106
+ def test__
107
+ url1 = @client._('test')
108
+ assert_equal(url1.url_path, ['test'])
109
+ end
110
+
111
+ def test_method_missing
112
+ response = @client.get
113
+ assert_equal(response.status_code, 200)
114
+ assert_equal(response.response_body, 'message' => 'success')
115
+ assert_equal(response.response_headers, 'headers' => 'test')
116
+ end
117
+ end
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby_http_client
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Elmer Thomas
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-03-18 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
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.6'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.6'
41
+ description: Quickly and easily access any REST or REST-like API.
42
+ email: dx@sendgrid.com
43
+ executables: []
44
+ extensions: []
45
+ extra_rdoc_files: []
46
+ files:
47
+ - ".env_sample"
48
+ - ".github/ISSUE_TEMPLATE"
49
+ - ".gitignore"
50
+ - ".travis.yml"
51
+ - CHANGELOG.md
52
+ - CONTRIBUTING.md
53
+ - LICENSE
54
+ - README.md
55
+ - Rakefile
56
+ - examples/example.rb
57
+ - lib/config.rb
58
+ - lib/ruby_http_client.rb
59
+ - ruby_http_client.gemspec
60
+ - test/test_ruby_http_client.rb
61
+ homepage: http://github.com/sendgrid/ruby-http-client
62
+ licenses:
63
+ - MIT
64
+ metadata: {}
65
+ post_install_message:
66
+ rdoc_options: []
67
+ require_paths:
68
+ - lib
69
+ required_ruby_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ required_rubygems_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ requirements: []
80
+ rubyforge_project:
81
+ rubygems_version: 2.4.8
82
+ signing_key:
83
+ specification_version: 4
84
+ summary: A simple REST client
85
+ test_files:
86
+ - test/test_ruby_http_client.rb