bubbles-rest-client 0.2.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/FUNDING.yml +1 -0
- data/.gitignore +3 -0
- data/.travis.yml +7 -0
- data/CODE_OF_CONDUCT.md +77 -0
- data/CONTRIBUTING.md +31 -0
- data/README.md +7 -112
- data/Rakefile +2 -7
- data/bubbles.gemspec +5 -4
- data/lib/bubbles.rb +3 -6
- data/lib/bubbles/config.rb +128 -106
- data/lib/bubbles/endpoint.rb +17 -3
- data/lib/bubbles/rest_client_resources.rb +258 -106
- data/lib/bubbles/rest_environment.rb +45 -3
- data/lib/bubbles/version.rb +1 -1
- data/lib/tasks/coverage.rake +22 -0
- data/lib/tasks/spec.rake +5 -0
- metadata +31 -13
- data/Gemfile.lock +0 -85
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 7f077a290f6996a9d6b17eaed8ad1cb4218dc63d1303ac98dd3ac7100e77a03a
|
4
|
+
data.tar.gz: b6737cdf8435852167b508fe3a3b231ab2c98cb0f87489c1111c498d1eac2af1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a899787ccb3ebcca5fc4bc6407e33d9c9fb96c478864f7eaf1b64c75b8d4bfd96ee638c3da6125f30bd1c81cbfd360a14962cbde03b2fd4f9f73c1f51eccb206
|
7
|
+
data.tar.gz: 70e5a4dbf61c052fb0a0af1a6cf8590132aeaea66aee30f30b99d66a968d34a02606c490782d6cdcf0b0fa14f98d3dfaf15ed88b15f00350638a9b8dca810d89
|
data/.github/FUNDING.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
github: jwir3
|
data/.gitignore
CHANGED
data/.travis.yml
ADDED
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
2
|
+
|
3
|
+
## Our Pledge
|
4
|
+
|
5
|
+
In the interest of fostering an open and welcoming environment, we as
|
6
|
+
contributors and maintainers of Bubbles pledge to making participation in our
|
7
|
+
project and our community a harassment-free experience for everyone,
|
8
|
+
regardless of age, body size, disability, ethnicity, sex characteristics,
|
9
|
+
gender identity and expression, level of experience, education,
|
10
|
+
socio-economic status, nationality, personal appearance, race, religion,
|
11
|
+
or sexual identity and orientation.
|
12
|
+
|
13
|
+
## Our Standards
|
14
|
+
|
15
|
+
Examples of behavior that contributes to creating a positive environment
|
16
|
+
include:
|
17
|
+
|
18
|
+
* Using welcoming and inclusive language
|
19
|
+
* Being respectful of differing viewpoints and experiences
|
20
|
+
* Gracefully accepting constructive criticism
|
21
|
+
* Focusing on what is best for the community and users
|
22
|
+
* Showing empathy towards other community members
|
23
|
+
|
24
|
+
Examples of unacceptable behavior by participants include:
|
25
|
+
|
26
|
+
* The use of sexualized language or imagery and unwelcome sexual attention or
|
27
|
+
advances
|
28
|
+
* Trolling, insulting/derogatory comments, and personal or political attacks
|
29
|
+
* Public or private harassment
|
30
|
+
* Publishing others' private information, such as a physical or electronic
|
31
|
+
address, without explicit permission
|
32
|
+
* Other conduct which could reasonably be considered inappropriate in a
|
33
|
+
professional setting
|
34
|
+
|
35
|
+
## Our Responsibilities
|
36
|
+
|
37
|
+
Project maintainers are responsible for clarifying the standards of acceptable
|
38
|
+
behavior and are expected to take appropriate and fair corrective action in
|
39
|
+
response to any instances of unacceptable behavior.
|
40
|
+
|
41
|
+
Project maintainers have the right and responsibility to remove, edit, or
|
42
|
+
reject comments, commits, code, wiki edits, issues, and other contributions
|
43
|
+
that are not aligned to this Code of Conduct, or to ban temporarily or
|
44
|
+
permanently any contributor for other behaviors that they deem inappropriate,
|
45
|
+
threatening, offensive, or harmful.
|
46
|
+
|
47
|
+
## Scope
|
48
|
+
|
49
|
+
This Code of Conduct applies both within project spaces and in public spaces
|
50
|
+
when an individual is representing the project or its community. Examples of
|
51
|
+
representing a project or community include using an official project e-mail
|
52
|
+
address, posting via an official social media account, or acting as an appointed
|
53
|
+
representative at an online or offline event. Representation of a project may be
|
54
|
+
further defined and clarified by project maintainers.
|
55
|
+
|
56
|
+
## Enforcement
|
57
|
+
|
58
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
59
|
+
reported by contacting Scott Johnson, our project lead, at jaywir3@gmail.com. All
|
60
|
+
complaints will be reviewed and investigated and will result in a response that
|
61
|
+
is deemed necessary and appropriate to the circumstances. The project leadership
|
62
|
+
team is obligated to maintain confidentiality with regard to the reporter of an
|
63
|
+
incident. Further details of specific enforcement policies may be posted separately.
|
64
|
+
|
65
|
+
Project maintainers who do not follow or enforce the Code of Conduct in good
|
66
|
+
faith may face temporary or permanent repercussions as determined by other
|
67
|
+
members of the project's leadership.
|
68
|
+
|
69
|
+
## Attribution
|
70
|
+
|
71
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
72
|
+
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
|
73
|
+
|
74
|
+
[homepage]: https://www.contributor-covenant.org
|
75
|
+
|
76
|
+
For answers to common questions about this code of conduct, see
|
77
|
+
https://www.contributor-covenant.org/faq
|
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# Contributing to Bubbles
|
2
|
+
|
3
|
+
## Introduction
|
4
|
+
First off, thanks for looking to contribute to Bubbles! We need people like you
|
5
|
+
to help us make the best quality product we possibly can. Regardless of whether
|
6
|
+
you're a developer, a designer, a technical writer, a student, or even someone
|
7
|
+
just interested in learning more about open source and how to contribute, you're
|
8
|
+
welcome here.
|
9
|
+
|
10
|
+
## Code of Conduct
|
11
|
+
Please take a look at our contributor [Code of Conduct](CODE_OF_CONDUCT.md). We
|
12
|
+
take harassment and non-inclusive behavior very seriously and will not tolerate
|
13
|
+
bullying in any form.
|
14
|
+
|
15
|
+
## Development Process
|
16
|
+
Our development process works as follows:
|
17
|
+
|
18
|
+
1. Fork this repository to your own local Github account.
|
19
|
+
2. Clone your local version of the repository: `git clone git@github.com:<username>/bubbles`.
|
20
|
+
3. Create a branch on your local repository: `git checkout -b <username>/#<issue>-<short-description>`.
|
21
|
+
4. Make any changes you see fit to fix the issue or add your work.
|
22
|
+
5. Verify that tests pass: `bundle install && rake spec`.
|
23
|
+
6. If you're adding a new feature, make sure to add tests for the feature.
|
24
|
+
7. Commit your changes and push to your fork of the repository.
|
25
|
+
8. Submit a pull request to the `master` branch of the original repository.
|
26
|
+
9. You will receive a review within 7 days, at which time, you may need to make
|
27
|
+
modifications to your code, or your contribution might be accepted as-is.
|
28
|
+
|
29
|
+
## Good First Issues
|
30
|
+
You can take a look at our [good first issues](https://github.com/FoamFactory/bubbles/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22)
|
31
|
+
to check out some issues that might be a good starting point for you.
|
data/README.md
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
# bubbles
|
2
|
+
[![Build Status](https://travis-ci.org/FoamFactory/bubbles.svg?branch=master)](https://travis-ci.org/FoamFactory/bubbles)
|
3
|
+
|
2
4
|
A gem for easily defining client REST interfaces in ruby
|
3
5
|
|
4
6
|
## Project Goals
|
@@ -23,18 +25,6 @@ What this does is allow you to focus on your _handling_ of the REST responses, r
|
|
23
25
|
|
24
26
|
_bubbles_ is a Gem that seeks to provide this same behavior.
|
25
27
|
|
26
|
-
## :warning: Limitations
|
27
|
-
**Please read this section before using!**
|
28
|
-
|
29
|
-
Currently, bubbles has a number of limitations that make it likely not suitable for use in a production environment. Each of these is tracked by an issue on our [issues page](https://github.com/FoamFactory/bubbles/issues).
|
30
|
-
|
31
|
-
- Passing an API key with a request is restricted to using `X-Api-Key` as a header key (#10).
|
32
|
-
- Some request methods (`PATCH`, `PUT`, `DELETE`) do not currently allow unauthenticated access. In other words, it is not possible to perform a `DELETE` request on your API without passing an authorization token. (#9)
|
33
|
-
- Only three types of environment are currently allowed. Only `local`, `staging` and `production` are recognized as possible environments to connect to for the purposes of using bubbles. You can add any scheme, host, and port to any of these, but the names are currently hardcoded, as is the number of possible hosts. (#4)
|
34
|
-
- Not all possible combinations of `has_uri_params`, `authenticated`, and `api_key_required` are tested. In some cases, such as with `GET` requests, there aren't any tests for possible configuration cases that might cause issues when combined. (#12)
|
35
|
-
|
36
|
-
If you're interested in working on any of the issues above, please feel free to submit a pull request and a member of our team will review that pull request within a couple of days.
|
37
|
-
|
38
28
|
## Usage
|
39
29
|
If you're using Rails, it's suggested to have a `config/initializers/bubbles.rb` configuration file where you can easily configure your endpoints and environments. If you're not using Rails, then you can put this configuration just about anywhere, provided it's executed before where you want to use it.
|
40
30
|
|
@@ -53,20 +43,19 @@ Bubbles.configure do |config|
|
|
53
43
|
}
|
54
44
|
]
|
55
45
|
|
56
|
-
config.
|
46
|
+
config.environments = [{
|
57
47
|
:scheme => 'http',
|
58
48
|
:host => '0.0.0.0',
|
59
49
|
:port => '1234'
|
60
|
-
}
|
50
|
+
}]
|
61
51
|
end
|
62
52
|
```
|
63
53
|
|
64
|
-
The `config.endpoints` section is where you configure which endpoints you want to support. The `config.
|
54
|
+
The `config.endpoints` section is where you configure which endpoints you want to support. The `config.environments` defines the environments, or remote configurations, for accessing the endpoint on specific remote destinations.
|
65
55
|
|
66
56
|
Now, you can use this endpoint with:
|
67
57
|
```ruby
|
68
58
|
require 'bubbles'
|
69
|
-
|
70
59
|
...
|
71
60
|
|
72
61
|
def version
|
@@ -74,105 +63,11 @@ def version
|
|
74
63
|
|
75
64
|
# The following will make a GET request to
|
76
65
|
# http://0.0.0.0:1234/version and return the result.
|
77
|
-
result = resources.
|
66
|
+
result = resources.environment.version
|
78
67
|
|
79
68
|
puts(result)
|
80
69
|
end
|
81
70
|
```
|
82
71
|
|
83
72
|
## Detailed Documentation
|
84
|
-
|
85
|
-
```ruby
|
86
|
-
Bubbles.configure do |config|
|
87
|
-
...
|
88
|
-
end
|
89
|
-
```
|
90
|
-
|
91
|
-
This configuration block can be run at any time, but is typically set up in the initializer section of an app's startup. If desired, configuration can happen separately. That is, you can initialize environments within your initializer file and then initialize endpoints within another section of the application. Just note that when endpoints are defined, it overwrites _all_ endpoints of a configuration, not just the ones you choose to change.
|
92
|
-
|
93
|
-
### Environments
|
94
|
-
Three environments are currently available to be set up within bubbles. These are:
|
95
|
-
- `local_environment` : Designed to be used for a local API for development testing.
|
96
|
-
- `staging_environment` : Designed to be used for a remote API for second-stage testing or production-like deployment.
|
97
|
-
- `production_environment` : Designed to be used for a production environment.
|
98
|
-
|
99
|
-
While the names are hardcoded, the environments can be used for anything - you could easily use a `local_environment` to store the information for one of your production servers.
|
100
|
-
|
101
|
-
#### Configuration of Environments
|
102
|
-
Environments are configured as part of the _bubbles configuration block_ and can have the following parameters:
|
103
|
-
|
104
|
-
- `scheme`: The scheme for accessing endpoints on this host. Should be one of `http` or `https`. Defaults to `http`.
|
105
|
-
- `host`: A domain name or IP address for the remote host to access for the environment. Defaults to `127.0.0.1`.
|
106
|
-
- `port`: The port to use to access the remote host. Defaults to `1234`.
|
107
|
-
- `api_key`: The API key to send along with requests for a given environment, if an API key is required. This is optional, and defaults to `nil`.
|
108
|
-
|
109
|
-
You can configure all three environments at once in the _bubbles configuration block_:
|
110
|
-
```ruby
|
111
|
-
Bubbles.configure do |config|
|
112
|
-
config.local_environment = {
|
113
|
-
:scheme => 'http',
|
114
|
-
:host => '0.0.0.0',
|
115
|
-
:port => '1234'
|
116
|
-
}
|
117
|
-
|
118
|
-
config.staging_environment = {
|
119
|
-
:scheme => 'http',
|
120
|
-
:host => 'stage.api.foamfactory.com',
|
121
|
-
:port => '80'
|
122
|
-
}
|
123
|
-
|
124
|
-
config.production_environment = {
|
125
|
-
:scheme => 'https',
|
126
|
-
:host => 'api.foamfactory.com',
|
127
|
-
:port => '443'
|
128
|
-
}
|
129
|
-
end
|
130
|
-
```
|
131
|
-
|
132
|
-
If you choose a scheme of `http` and leave off the `port` configuration variable, it will default to `80`. Similarly, `https` will default to a port of `443`.
|
133
|
-
|
134
|
-
#### Configuration of Endpoints
|
135
|
-
Endpoints are the meat and potatoes of REST interaction. By indicating a _method_, _uri_, _body_, and _headers_, you are effectively making a function call on a remote server.
|
136
|
-
|
137
|
-
_Endpoints_ are specified as an array of objects within the _bubbles configuration block_:
|
138
|
-
|
139
|
-
```ruby
|
140
|
-
config.endpoints = [
|
141
|
-
# Individual endpoint definitions go here
|
142
|
-
]
|
143
|
-
```
|
144
|
-
|
145
|
-
When processing each of these endpoint definitions, a method is created on instances of `RestEnvironment` that allows you to call the method in question. For example, an endpoint defined as:
|
146
|
-
```ruby
|
147
|
-
{
|
148
|
-
:method => :get,
|
149
|
-
:location => :version,
|
150
|
-
:authenticated => false,
|
151
|
-
:api_key_required => false
|
152
|
-
}
|
153
|
-
```
|
154
|
-
|
155
|
-
will create a method on instances of `RestEnvironment` called `version`, which will execute the appropriate REST call (via `RestClient`) and return a `RestClient::Response` object.
|
156
|
-
|
157
|
-
Each _endpoint_ object can have the following attributes:
|
158
|
-
|
159
|
-
| Name | Description | Required? | Default |
|
160
|
-
| :--- | :------------------ | :-------: | :-----: |
|
161
|
-
| `method`| The HTTP method to use to access the API for this endpoint. Must be one of `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, or `HEAD`. | Yes | N/A |
|
162
|
-
| `location`| The path to access the endpoint. This is placed after the `host:port` section to build the URI. It may have URI parameters in the form of `{paramName}`. If a URI parameter is specified within the `location`, a `uri_params` hash will be expected to be passed to the calling method to replace the placeholder values. | Yes | N/A |
|
163
|
-
| `name` | The name to give the method created to make this REST call. | No | The value of the `location` parameter, with slashes (`/`) replaced with underscores (`_`). |
|
164
|
-
| `authorization` | Whether or not this endpoint requires authentication prior to executing the call. If true, then an `authorization_token` will be added to the method as a parameter to be passed when the method is called. This parameter will be placed in an `Authorization` header when the REST call is executed. | No | `false` |
|
165
|
-
| `api_key_required` | Whether or not an API key is required. If `true`, a parameter will be added to the method created to execute the REST API call named `api_key`. The value of this parameter will be set as the value of the `X-Api-Key` header when making the REST API call. | No | `false` |
|
166
|
-
| `return_type` | Must be one of: `[full_response, body_as_object, body_as_string]`. This specifies what type of response is expected from the `Endpoint`. A value of `full_response` will return the full `RestClient::Response` object to the client. A value of `body_as_string` will return the `RestClient::Response.body` value as a `String`. A value of `body_as_object` will take the `RestClient::Response.body` parameter and parse it as an `OpenStruct` object, and return the result of this parsing operation. | No | `body_as_string` |
|
167
|
-
| `encode_authorization` | Whether the `data` passed as part of the request should be re-encoded as an `Authorization: Basic` header (and Base64 encoded). Typically, this is only used for initial username/password authentication. | No | `false` |
|
168
|
-
|
169
|
-
### Examples
|
170
|
-
#### GET the version of the software (unauthenticated, no API key required)
|
171
|
-
|
172
|
-
#### GET a specific user by id (authentication required)
|
173
|
-
|
174
|
-
#### POST a login (i.e. retrieve an authorization token)
|
175
|
-
|
176
|
-
#### DELETE a user by id
|
177
|
-
|
178
|
-
#### PATCH a user's information by providing a body containing information to update
|
73
|
+
For more examples and detailed documentation, please see [the Bubbles GitHub page](http://foamfactory.github.io/bubbles).
|
data/Rakefile
CHANGED
@@ -1,10 +1,5 @@
|
|
1
1
|
require "bundler/gem_tasks"
|
2
|
-
require "rake/testtask"
|
3
2
|
|
4
|
-
|
5
|
-
t.libs << "test"
|
6
|
-
t.libs << "lib"
|
7
|
-
t.test_files = FileList['test/**/*_test.rb']
|
8
|
-
end
|
3
|
+
Dir.glob('lib/tasks/*.rake').each { |r| load r}
|
9
4
|
|
10
|
-
task :default => :
|
5
|
+
task :default => :build
|
data/bubbles.gemspec
CHANGED
@@ -32,14 +32,15 @@ Gem::Specification.new do |spec|
|
|
32
32
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
33
33
|
spec.require_paths = ["lib"]
|
34
34
|
|
35
|
-
spec.add_development_dependency "bundler", "~> 2.
|
36
|
-
spec.add_development_dependency "rake", "
|
35
|
+
spec.add_development_dependency "bundler", "~> 2.1.4"
|
36
|
+
spec.add_development_dependency "rake", ">= 12.3.3"
|
37
37
|
spec.add_development_dependency "minitest", "~> 5.0"
|
38
38
|
spec.add_development_dependency "minitest-reporters", "~> 1.1"
|
39
39
|
spec.add_development_dependency "simplecov", "~> 0.16"
|
40
|
-
spec.add_development_dependency "webmock", "~> 3.
|
40
|
+
spec.add_development_dependency "webmock", "~> 3.5"
|
41
41
|
spec.add_development_dependency "vcr", "~> 3.0"
|
42
42
|
spec.add_development_dependency "rspec", "~> 3.8"
|
43
|
+
spec.add_development_dependency "os"
|
43
44
|
spec.add_dependency "addressable", "~> 2.5"
|
44
45
|
spec.add_dependency "rest-client", "~> 2.0"
|
45
|
-
end
|
46
|
+
end
|
data/lib/bubbles.rb
CHANGED
@@ -10,11 +10,9 @@ require 'json'
|
|
10
10
|
|
11
11
|
module Bubbles
|
12
12
|
class Resources < RestClientResources
|
13
|
-
def initialize
|
14
|
-
|
15
|
-
|
16
|
-
# @api_key = api_key
|
17
|
-
# @auth_token = nil
|
13
|
+
def initialize(api_key='')
|
14
|
+
super
|
15
|
+
|
18
16
|
@packageName = Bubbles::VersionInformation.package_name
|
19
17
|
@versionName = Bubbles::VersionInformation.version_name
|
20
18
|
@versionCode = Bubbles::VersionInformation.version_code
|
@@ -29,4 +27,3 @@ module Bubbles
|
|
29
27
|
end
|
30
28
|
end
|
31
29
|
end
|
32
|
-
|
data/lib/bubbles/config.rb
CHANGED
@@ -10,7 +10,7 @@ module Bubbles
|
|
10
10
|
##
|
11
11
|
# Configure the Bubbles instance.
|
12
12
|
#
|
13
|
-
# Use this method if you want to configure the Bubbles instance, typically during
|
13
|
+
# Use this method if you want to configure the Bubbles instance, typically during initialization of your Gem or
|
14
14
|
# application.
|
15
15
|
#
|
16
16
|
# @example In app/config/initializers/bubbles.rb
|
@@ -39,42 +39,85 @@ module Bubbles
|
|
39
39
|
#
|
40
40
|
class Configuration
|
41
41
|
def initialize
|
42
|
-
@
|
43
|
-
@environment_host = '127.0.0.1'
|
44
|
-
@environment_port = '1234'
|
45
|
-
@environment_api_key = nil
|
46
|
-
|
42
|
+
@environments = Hash.new
|
47
43
|
@endpoints = Hash.new
|
48
44
|
end
|
49
45
|
|
50
46
|
##
|
51
|
-
# Retrieve the {RestEnvironment} object defined as part of this Configuration.
|
47
|
+
# Retrieve the {RestEnvironment} object defined as part of this Configuration having a specified name.
|
48
|
+
#
|
49
|
+
# @param [String] environment_name The name of the {RestEnvironment} to retrieve.
|
52
50
|
#
|
53
|
-
#
|
51
|
+
# The +environment_name+ is +nil+ by default, which will return the default configuration, if only one exists.
|
54
52
|
#
|
55
|
-
|
56
|
-
|
53
|
+
# @return [RestEnvironment] A new +RestEnvironment+ having the configuration that was created with key
|
54
|
+
# +environment_name+. Note that +RestEnvironment+s are essentially immutable once they are created, so
|
55
|
+
# an existing object will _never_ be returned.
|
56
|
+
#
|
57
|
+
def environment(environment_name = nil)
|
58
|
+
if environment_name.nil?
|
59
|
+
if @environments.length > 1
|
60
|
+
raise 'You must specify an environment_name parameter because more than one environment is defined'
|
61
|
+
end
|
62
|
+
|
63
|
+
env_hash = @environments[nil]
|
64
|
+
else
|
65
|
+
env_hash = @environments[environment_name]
|
66
|
+
end
|
67
|
+
|
68
|
+
if env_hash.nil?
|
69
|
+
if environment_name.nil?
|
70
|
+
raise 'No default environment specified'
|
71
|
+
end
|
72
|
+
|
73
|
+
raise 'No environment specified having name {}', environment_name
|
74
|
+
end
|
75
|
+
|
76
|
+
RestEnvironment.new(env_hash[:scheme], env_hash[:host], env_hash[:port], env_hash[:api_key],
|
77
|
+
env_hash[:api_key_name])
|
57
78
|
end
|
58
79
|
|
59
80
|
##
|
60
|
-
# Set the
|
81
|
+
# Set the environments that can be used.
|
82
|
+
#
|
83
|
+
# @param [Array] environments The environments, as an array with each entry a +Hash+.
|
61
84
|
#
|
62
|
-
#
|
85
|
+
# One or more environments may be specified, but if more than one environment is specified, it is required that each
|
86
|
+
# environment have a +:environment_name:+ parameter to differentiate it from other environments.
|
63
87
|
#
|
64
88
|
# @example In app/config/environments/staging.rb:
|
65
89
|
# Bubbles.configure do |config|
|
66
|
-
# config.
|
90
|
+
# config.environments = [{
|
67
91
|
# :scheme => 'https',
|
68
92
|
# :host => 'stage.api.somehost.com',
|
69
|
-
# :port => '443'
|
70
|
-
#
|
93
|
+
# :port => '443',
|
94
|
+
# :api_key => 'something',
|
95
|
+
# :api_key_name => 'X-API-Key' # Optional
|
96
|
+
# }]
|
71
97
|
# end
|
72
98
|
#
|
73
|
-
def
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
99
|
+
def environments=(environments)
|
100
|
+
default = nil
|
101
|
+
environments.each do |environment|
|
102
|
+
if environments.length > 1 && environment[:environment_name].nil?
|
103
|
+
message = 'More than one environment was specified and at least one of the environments does not have an ' \
|
104
|
+
':environment_name field. Verify all environments have an :environment_name.'
|
105
|
+
|
106
|
+
raise message
|
107
|
+
end
|
108
|
+
|
109
|
+
@environments = {}
|
110
|
+
env_api_key = 'X-API-Key'
|
111
|
+
env_api_key = environment[:api_key_name] if environment.key? :api_key_name
|
112
|
+
|
113
|
+
@environments[environment[:environment_name]] = {
|
114
|
+
scheme: environment[:scheme],
|
115
|
+
host: environment[:host],
|
116
|
+
port: environment[:port],
|
117
|
+
api_key: environment[:api_key],
|
118
|
+
api_key_name: env_api_key
|
119
|
+
}
|
120
|
+
end
|
78
121
|
end
|
79
122
|
|
80
123
|
##
|
@@ -103,7 +146,7 @@ module Bubbles
|
|
103
146
|
def endpoints=(endpoints)
|
104
147
|
new_endpoints = Hash.new
|
105
148
|
endpoints.each do |ep|
|
106
|
-
endpoint_object = Endpoint.new ep[:method], ep[:location].to_s, ep[:authenticated], ep[:api_key_required], ep[:name], ep[:return_type], ep[:encode_authorization]
|
149
|
+
endpoint_object = Endpoint.new ep[:method], ep[:location].to_s, ep[:authenticated], ep[:api_key_required], ep[:name], ep[:return_type], ep[:encode_authorization], ep[:headers]
|
107
150
|
|
108
151
|
new_endpoints[endpoint_object.get_key_string] = endpoint_object
|
109
152
|
end
|
@@ -129,18 +172,24 @@ module Bubbles
|
|
129
172
|
Bubbles::RestEnvironment.class_exec do
|
130
173
|
if endpoint.has_uri_params?
|
131
174
|
define_method(endpoint_name_as_sym) do |auth_token, uri_params|
|
132
|
-
RestClientResources.execute_get_authenticated self, endpoint, auth_token, uri_params
|
175
|
+
RestClientResources.execute_get_authenticated self, endpoint, auth_token, uri_params, endpoint.additional_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
|
133
176
|
end
|
134
177
|
else
|
135
178
|
define_method(endpoint_name_as_sym) do |auth_token|
|
136
|
-
RestClientResources.execute_get_authenticated self, endpoint, auth_token, {}
|
179
|
+
RestClientResources.execute_get_authenticated self, endpoint, auth_token, {}, endpoint.additional_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
|
137
180
|
end
|
138
181
|
end
|
139
182
|
end
|
140
183
|
else
|
141
184
|
Bubbles::RestEnvironment.class_exec do
|
142
|
-
|
143
|
-
|
185
|
+
if endpoint.has_uri_params?
|
186
|
+
define_method(endpoint_name_as_sym) do |uri_params|
|
187
|
+
RestClientResources.execute_get_unauthenticated self, endpoint, uri_params, endpoint.additional_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
|
188
|
+
end
|
189
|
+
else
|
190
|
+
define_method(endpoint_name_as_sym) do
|
191
|
+
RestClientResources.execute_get_unauthenticated self, endpoint, {}, endpoint.additional_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
|
192
|
+
end
|
144
193
|
end
|
145
194
|
end
|
146
195
|
end
|
@@ -148,135 +197,108 @@ module Bubbles
|
|
148
197
|
if endpoint.authenticated?
|
149
198
|
Bubbles::RestEnvironment.class_exec do
|
150
199
|
define_method(endpoint_name_as_sym) do |auth_token, data|
|
151
|
-
RestClientResources.execute_post_authenticated self, endpoint, auth_token, data
|
200
|
+
RestClientResources.execute_post_authenticated self, endpoint, auth_token, data, endpoint.additional_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
|
152
201
|
end
|
153
202
|
end
|
154
203
|
else
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
if data[auth_key]
|
164
|
-
if count > 0
|
165
|
-
auth_value = auth_value + ':' + data[auth_key]
|
166
|
-
else
|
167
|
-
auth_value = data[auth_key]
|
168
|
-
end
|
169
|
-
|
170
|
-
count = count + 1
|
171
|
-
|
172
|
-
data.delete(auth_key)
|
173
|
-
end
|
174
|
-
}
|
175
|
-
|
176
|
-
additional_headers[:Authorization] = 'Basic ' + Base64.strict_encode64(auth_value)
|
177
|
-
end
|
178
|
-
|
179
|
-
RestClientResources.execute_post_with_api_key self, endpoint, self.api_key, data, additional_headers
|
204
|
+
Bubbles::RestEnvironment.class_exec do
|
205
|
+
define_method(endpoint_name_as_sym) do |data|
|
206
|
+
composite_headers = endpoint.additional_headers
|
207
|
+
if endpoint.encode_authorization_header?
|
208
|
+
auth_value = RestClientResources.get_encoded_authorization(endpoint, data)
|
209
|
+
composite_headers = RestClientResources.build_composite_headers(endpoint.additional_headers, {
|
210
|
+
Authorization: 'Basic ' + Base64.strict_encode64(auth_value)
|
211
|
+
})
|
180
212
|
end
|
213
|
+
|
214
|
+
RestClientResources.execute_post_unauthenticated self, endpoint, data, composite_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
|
181
215
|
end
|
182
|
-
else
|
183
|
-
raise 'Unauthenticated POST requests without an API key are not allowed'
|
184
216
|
end
|
185
217
|
end
|
186
218
|
elsif endpoint.method == :delete
|
187
|
-
if endpoint.
|
188
|
-
|
189
|
-
|
219
|
+
if endpoint.has_uri_params?
|
220
|
+
if endpoint.authenticated?
|
221
|
+
Bubbles::RestEnvironment.class_exec do
|
190
222
|
define_method(endpoint_name_as_sym) do |auth_token, uri_params|
|
191
|
-
RestClientResources.execute_delete_authenticated self, endpoint, auth_token, uri_params
|
223
|
+
RestClientResources.execute_delete_authenticated self, endpoint, auth_token, uri_params, endpoint.additional_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
|
224
|
+
end
|
225
|
+
end
|
226
|
+
else
|
227
|
+
Bubbles::RestEnvironment.class_exec do
|
228
|
+
define_method(endpoint_name_as_sym) do |uri_params|
|
229
|
+
RestClientResources.execute_delete_unauthenticated self, endpoint, uri_params, endpoint.additional_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
|
192
230
|
end
|
193
|
-
else
|
194
|
-
# NOTE: While MDN states that DELETE requests with a body are allowed, it seems that a number of
|
195
|
-
# documentation sites discourage its use. Thus, it's possible that, depending on the server API
|
196
|
-
# framework, the DELETE request could be rejected. As such, we're disallowing it here, BUT if we
|
197
|
-
# get feedback from users that it should be supported, we can add support for it.
|
198
|
-
raise 'DELETE requests without URI parameters are not allowed'
|
199
|
-
# define_method(endpoint_name_as_sym) do |auth_token|
|
200
|
-
# RestClientResources.execute_delete_authenticated self, endpoint, auth_token, {}
|
201
|
-
# end
|
202
231
|
end
|
203
232
|
end
|
204
233
|
else
|
205
|
-
|
206
|
-
#
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
# end
|
234
|
+
# XXX_jwir3: While MDN states that DELETE requests with a body are allowed, it seems that a number of
|
235
|
+
# documentation sites discourage its use. Thus, it's possible that, depending on the server API
|
236
|
+
# framework, the DELETE request could be rejected. In addition, RestClient doesn't seem to support DELETE
|
237
|
+
# requests with a body, so we're a bit stuck on this one, even if we wanted to support it.
|
238
|
+
raise 'DELETE requests without URI parameters are not allowed'
|
211
239
|
end
|
212
240
|
elsif endpoint.method == :patch
|
213
241
|
if endpoint.authenticated?
|
214
242
|
Bubbles::RestEnvironment.class_exec do
|
215
243
|
if endpoint.has_uri_params?
|
216
244
|
define_method(endpoint_name_as_sym) do |auth_token, uri_params, data|
|
217
|
-
RestClientResources.execute_patch_authenticated self, endpoint, auth_token, uri_params, data
|
245
|
+
RestClientResources.execute_patch_authenticated self, endpoint, auth_token, uri_params, data, endpoint.additional_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
|
218
246
|
end
|
219
247
|
else
|
220
248
|
define_method(endpoint_name_as_sym) do |auth_token, data|
|
221
|
-
RestClientResources.execute_patch_authenticated self, endpoint, auth_token,
|
249
|
+
RestClientResources.execute_patch_authenticated self, endpoint, auth_token, {}, data, endpoint.additional_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
|
222
250
|
end
|
223
251
|
end
|
224
252
|
end
|
225
253
|
else
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
254
|
+
Bubbles::RestEnvironment.class_exec do
|
255
|
+
if endpoint.has_uri_params?
|
256
|
+
define_method(endpoint_name_as_sym) do |uri_params, data|
|
257
|
+
RestClientResources.execute_patch_unauthenticated self, endpoint, uri_params, data, endpoint.additional_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
|
258
|
+
end
|
259
|
+
else
|
260
|
+
define_method(endpoint_name_as_sym) do |data|
|
261
|
+
RestClientResources.execute_patch_unauthenticated self, endpoint, {}, data, endpoint.additional_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
232
265
|
end
|
233
266
|
elsif endpoint.method == :put
|
234
267
|
if endpoint.authenticated?
|
235
268
|
Bubbles::RestEnvironment.class_exec do
|
236
269
|
if endpoint.has_uri_params?
|
237
270
|
define_method(endpoint_name_as_sym) do |auth_token, uri_params, data|
|
238
|
-
RestClientResources.execute_put_authenticated self, endpoint, auth_token, uri_params, data
|
271
|
+
RestClientResources.execute_put_authenticated self, endpoint, auth_token, uri_params, data, endpoint.additional_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
|
239
272
|
end
|
240
273
|
else
|
241
274
|
define_method(endpoint_name_as_sym) do |auth_token, data|
|
242
|
-
RestClientResources.execute_put_authenticated self, endpoint, auth_token,
|
275
|
+
RestClientResources.execute_put_authenticated self, endpoint, auth_token, {}, data, endpoint.additional_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
|
243
276
|
end
|
244
277
|
end
|
245
278
|
end
|
246
279
|
else
|
247
|
-
raise 'Unauthenticated PUT requests are not implemented'
|
248
|
-
# Bubbles::RestEnvironment.class_exec do
|
249
|
-
# define_method(endpoint_name_as_sym) do
|
250
|
-
# RestClientResources.execute_delete_unauthenticated self, endpoint
|
251
|
-
# end
|
252
|
-
# end
|
253
|
-
end
|
254
|
-
elsif endpoint.method == :head
|
255
|
-
if endpoint.authenticated?
|
256
280
|
Bubbles::RestEnvironment.class_exec do
|
257
281
|
if endpoint.has_uri_params?
|
258
|
-
define_method(endpoint_name_as_sym) do |
|
259
|
-
RestClientResources.
|
282
|
+
define_method(endpoint_name_as_sym) do |uri_params, data|
|
283
|
+
RestClientResources.execute_put_unauthenticated self, endpoint, uri_params, data, endpoint.additional_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
|
260
284
|
end
|
261
285
|
else
|
262
|
-
define_method(endpoint_name_as_sym) do |
|
263
|
-
RestClientResources.
|
286
|
+
define_method(endpoint_name_as_sym) do |data|
|
287
|
+
RestClientResources.execute_put_unauthenticated self, endpoint, {}, data, endpoint.additional_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
|
264
288
|
end
|
265
289
|
end
|
266
290
|
end
|
267
|
-
|
291
|
+
end
|
292
|
+
elsif endpoint.method == :head
|
293
|
+
if endpoint.authenticated?
|
268
294
|
Bubbles::RestEnvironment.class_exec do
|
269
295
|
if endpoint.has_uri_params?
|
270
|
-
define_method(endpoint_name_as_sym) do |
|
271
|
-
additional_headers
|
272
|
-
additional_headers['X-Api-Key'] = api_key
|
273
|
-
RestClientResources.execute_head_unauthenticated self, endpoint, uri_params, additional_headers
|
296
|
+
define_method(endpoint_name_as_sym) do |auth_token, uri_params|
|
297
|
+
RestClientResources.execute_head_authenticated self, endpoint, auth_token, uri_params, endpoint.additional_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
|
274
298
|
end
|
275
299
|
else
|
276
|
-
define_method(endpoint_name_as_sym) do |
|
277
|
-
|
278
|
-
additional_headers['X-Api-Key'] = api_key
|
279
|
-
RestClientResources.execute_head_unauthenticated self, endpoint, {}, additional_headers
|
300
|
+
define_method(endpoint_name_as_sym) do |auth_token|
|
301
|
+
RestClientResources.execute_head_authenticated self, endpoint, auth_token, {}, endpoint.additional_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
|
280
302
|
end
|
281
303
|
end
|
282
304
|
end
|
@@ -284,11 +306,11 @@ module Bubbles
|
|
284
306
|
Bubbles::RestEnvironment.class_exec do
|
285
307
|
if endpoint.has_uri_params?
|
286
308
|
define_method(endpoint_name_as_sym) do |uri_params|
|
287
|
-
RestClientResources.execute_head_unauthenticated self, endpoint, uri_params,
|
309
|
+
RestClientResources.execute_head_unauthenticated self, endpoint, uri_params, endpoint.additional_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
|
288
310
|
end
|
289
311
|
else
|
290
312
|
define_method(endpoint_name_as_sym) do
|
291
|
-
RestClientResources.execute_head_unauthenticated self, endpoint, {},
|
313
|
+
RestClientResources.execute_head_unauthenticated self, endpoint, {}, endpoint.additional_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
|
292
314
|
end
|
293
315
|
end
|
294
316
|
end
|