Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
190 changes: 164 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,50 +1,188 @@
# Foobara::EmptyRubyProjectGenerator
# Foobara HTTP API Command

TODO: Delete this and the text below, and describe your gem
`foobara-http-api-command` is a gem that quickly encapsulates an external HTTP API call in a Foobara command.

Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library
into a gem. Put your Ruby code in the file `lib/foobara/empty_ruby_project_generator`. To experiment with that code,
run `bin/console` for an interactive prompt.
It supports GET requests with query parameters and POST requests with JSON bodies, and parses successful JSON responses.

## Installation

TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it
to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with
instructions to install your gem from git if you don't plan to release to RubyGems.org.
Install the gem directly in your terminal by running the command below:

Install the gem and add to the application's Gemfile by executing:
```sh
gem install foobara-http-api-command
```

Or add it to your application Gemfile:

$ bundle add UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG
```ruby
gem "foobara-http-api-command"
```

If bundler is not being used to manage dependencies, install the gem by executing:
Then run:

$ gem install UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG
```sh
bundle install
```

## Usage

TODO: Write usage instructions here
### Making a GET request

Include `Foobara::HttpApiCommand` in a command class. A GET command builds its request parameters in `build_request_body`. The concern puts them in the URL and returns the parsed JSON by default.

Save the code below in a file such as `search_example.rb`:

```ruby
require "foobara/http_api_command"

class Search < Foobara::Command
include Foobara::HttpApiCommand

inputs do
query :string, :required
end

result [Hash]

base_url "https://rubygems.org/api/v1"
path "/search.json"

def build_request_body
self.request_body = { query: }
end
end

results = Search.run!(query: "foobara")
results # => an Array of Hash results from the API
```

### What each part does

- `include Foobara::HttpApiCommand`: adds the HTTP abilities to the command
- `inputs do .. end`: block which lists the arguments of the command. In this case, a string `query` which is `required`.
- `result [Hash]` says the command should return an array of hashes as the expected output
- `base_url` and `path` together make the address: `https://rubygems.org/api/v1/search.json`
- `build_request_body` sets the request body to `{ query: }`. For a GET request this ends up in the URL as a query parameter.
- `Search.run!(query: "foobara")` runs the command and returns the parsed JSON.

In the above example, we make a real request to RubyGems.org.

### Running the example

The above example doesn't print anything on its own, so add this line at the end of the file:

```ruby
pp results.first
```

Then run it in the terminal:

```sh
bundle exec ruby search_example.rb
```

You should see a hash describing one search result from RubyGems.org as the output from running the example.

## Development
### Make a POST request

If using Foobara locally, then run the following (TODO: make this no-longer necessary.)
To send data instead of asking for it, set `http_method :post`. The request body will then be sent as JSON.

```bash
bundle config set disable_local_branch_check true
Your command's inputs are not sent automatically. You choose the payload by overriding `build_request_body`. This example uses an echo endpoint ( a service that sends your request back to you), taken from the project's recorded POST test or spec:

```ruby
require "foobara/http_api_command"

class PostExample < Foobara::Command
include Foobara::HttpApiCommand

inputs do
foo :string, :required
end

result Hash
url "https://httpbin.org/post"
http_method :post
http_timeout 120

def build_request_body
self.request_body = { foo: }
end
end

response = PostExample.run!(foo: "bar")
response.fetch("json") # => {"foo"=>"bar"}
```

After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can
also run `bin/console` for an interactive prompt that will allow you to experiment.
What is new compared with the GET example:

- `url "https://httpbin.org/post"` gives the complete address in one go, instead of `base_url` plus `path`.
- `http_method :post` makes it a POST request
- `http_timeout 120` waits up to 120 seconds for a reply
- `result Hash` says the command returns one hash(not an array of them)
- `response.fetch("json")` reads the `json` part of the reply. This echo service sends your JSON back under that name.

To see it, add `p response.fetch("json")` at the end of the file and run it with `bundle exec ruby` as before. You should see `{"foo"=>"bar"}`.

### Choosing where and how to send

| Setting | What it does |
| --- | --- |
| `url "https://..."` | The complete address. It can also be a block. |
| `base_url` and `path` | Two halves of the address. Each can also be a block, which runs inside the command instance |
| `http_method :post` | Sends a POST request. GET is the default, and only `:get` and `:post` are supported |
| `http_timeout` | Specifies how many seconds to wait for a reply. It sets only the read timeout |

### Things to watch out for

- You supply the slash. `base_url` and `path` are joined as-is, so make sure there's exactly one slash between them. In the GET example, the path starts with `/`
- HTTPS is handled for you. An `https://` address automatically uses TLS signifying an encrypted connection.
- For GET, a request body replaces the URL's query. If the request body is not empty, it replaces any query already in the URL, using `URI.encode_www_form` to encode it.

### Customization

To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the
version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version,
push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
#### Headers

The default `build_request_headers` sets `Content-Type: application/json`. To add a header, override it and call `super` first, which runs the default version, then add yours.

Place the method below inside the command class:

```ruby
def build_request_headers
super
request_headers["Accept"] = "application/json"
end
```

#### The result

You can override `build_result` to change parsed `response_body` into whatever your command should return.

### What happens with replies and errors

| What comes back | What you get |
| --- | --- |
| A successful (2xx) response | It's parsed as JSON |
| A response that isn't 2xx | A `RuntimeError` is raised with the response message |
| A successful response with an empty body, or a body that isn't JSON | `JSON::ParserError` is raised |
| A network problem such as a failed connection | The error is raised as is |

Redirects and typed HTTP errors(a seperate error class for each status code are not implemented).

## Contributing

Bug reports and pull requests are welcome on GitHub
at https://github.com/[USERNAME]/foobara-empty_ruby_project_generator.
Bug reports and pull requests are welcome at [foobara/http-api-command](https://github.com/foobara/http-api-command).

Contributions in the form of PRs and issues are always welcome.

To work on an existing issue or submit a PR:

1. Fork the repository and clone it to your local machine
2. Run `bundle install` to install dependencies
3. Run `rake` to ensure that everything works as expected before making any changes.
4. Implement your changes
5. Re-run `rake` to make sure that all tests and rubocop pass.
6. Commit your changes, push to GitHub and open a Pull Request for review

## License

This files in this project are licensed under the
Mozilla Public License Version 2.0. Please see LICENSE.txt for more info.
This project is licensed under the Mozilla Public License 2.0. For more information about licensing, please see [LICENSE.txt](LICENSE.txt).