-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Code extracted from snoo and rewritten to be platform agnostic
- Loading branch information
0 parents
commit eeed330
Showing
18 changed files
with
414 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
/.bundle/ | ||
/.yardoc | ||
/Gemfile.lock | ||
/_yardoc/ | ||
/coverage/ | ||
/doc/ | ||
/pkg/ | ||
/spec/reports/ | ||
/tmp/ | ||
vendor |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
--format documentation | ||
--color |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
AllCops: | ||
TargetRubyVersion: 2.2 | ||
Metrics/LineLength: | ||
Enabled: false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
language: ruby | ||
rvm: | ||
- 2.3.0 | ||
before_install: gem install bundler -v 1.11.2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
source 'https://rubygems.org' | ||
|
||
# Specify your gem's dependencies in http_api_builder.gemspec | ||
gemspec |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
The MIT License (MIT) | ||
|
||
Copyright (c) 2016 Jeff Sandberg | ||
|
||
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: | ||
|
||
The above copyright notice and this permission notice shall be included in | ||
all copies or substantial portions of the Software. | ||
|
||
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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
# HttpApiBuilder | ||
A simple tool for building API clients that use HTTP. | ||
|
||
This is for **clients** as in *consumers*, not for servers. Look into things like Rails-api or Grape for those. | ||
|
||
[![Code Climate](https://codeclimate.com/github/paradox460/http_api_builder/badges/gpa.svg)](https://codeclimate.com/github/paradox460/http_api_builder) | ||
|
||
## Installation | ||
|
||
Add this line to your application's Gemfile: | ||
|
||
```ruby | ||
gem 'http_api_builder' | ||
``` | ||
|
||
And then execute: | ||
|
||
$ bundle | ||
|
||
Or install it yourself as: | ||
|
||
$ gem install http_api_builder | ||
|
||
## Usage | ||
|
||
```ruby | ||
require 'http_api_builder/client/http_rb' | ||
|
||
class ElGoog < HttpApiBuilder::BaseClient | ||
include HttpApiBuilder::Client::HttpRb | ||
|
||
base_url 'https://google.com' | ||
|
||
get '/', as: :search, params: {required: :q} | ||
end | ||
``` | ||
|
||
You can then use the API as such: | ||
|
||
```ruby | ||
g = ElGoog.new | ||
|
||
g.search(q: 'ruby') | ||
``` | ||
|
||
See the wiki for more details. | ||
|
||
## License | ||
|
||
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT). | ||
|
||
|
||
``` | ||
The MIT License (MIT) | ||
Copyright (c) 2016 Jeff Sandberg | ||
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: | ||
The above copyright notice and this permission notice shall be included in | ||
all copies or substantial portions of the Software. | ||
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. | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
require 'bundler/gem_tasks' | ||
require 'rspec/core/rake_task' | ||
|
||
RSpec::Core::RakeTask.new(:spec) | ||
|
||
task default: :spec |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
#!/usr/bin/env ruby | ||
|
||
require 'bundler/setup' | ||
require 'http_api_builder' | ||
|
||
# You can add fixtures and/or initialization code here to make experimenting | ||
# with your gem easier. You can also use a different console, if you like. | ||
|
||
# (If you use this, don't forget to add pry to your Gemfile!) | ||
# require "pry" | ||
# Pry.start | ||
|
||
require 'pry' | ||
Pry.start |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
#!/usr/bin/env bash | ||
set -euo pipefail | ||
IFS=$'\n\t' | ||
set -vx | ||
|
||
bundle install | ||
|
||
# Do any other automated setup that you need to do here |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# coding: utf-8 | ||
lib = File.expand_path('../lib', __FILE__) | ||
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) | ||
require 'http_api_builder/version' | ||
|
||
Gem::Specification.new do |spec| | ||
spec.name = 'http_api_builder' | ||
spec.version = HttpApiBuilder::VERSION | ||
spec.authors = ['Jeff Sandberg'] | ||
spec.email = ['[email protected]'] | ||
|
||
spec.summary = 'A utility gem providing a DSL for building HTTP api wrappers.' | ||
spec.description = 'A gem providing a nice DSL for building HTTP api wrappers.' | ||
spec.homepage = 'https://github.com/paradox460/http_api_builder' | ||
spec.license = 'MIT' | ||
|
||
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } | ||
spec.bindir = 'exe' | ||
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } | ||
spec.require_paths = ['lib'] | ||
|
||
spec.required_ruby_version = ">= 2.2" | ||
|
||
spec.add_development_dependency 'bundler', '~> 1.11' | ||
spec.add_development_dependency 'rake', '~> 10.0' | ||
spec.add_development_dependency 'rspec', '~> 3.0' | ||
spec.add_development_dependency 'pry' | ||
spec.add_development_dependency 'pry-stack_explorer' | ||
spec.add_development_dependency 'pry-byebug' | ||
spec.add_development_dependency 'http' | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
require 'http_api_builder/version' | ||
require 'http_api_builder/dsl' | ||
require 'http_api_builder/helpers' | ||
|
||
module HttpApiBuilder | ||
# A basic HTTP client. Meant to be extended from. | ||
class BaseClient | ||
extend Dsl | ||
include Helpers | ||
|
||
def initialize(); end | ||
|
||
# Perform the request, post processors, and return the result | ||
def perform(method, path, form: nil, query: nil, body: nil, json: nil, &_block) # rubocop:disable Metrics/ParameterLists | ||
response = request(method, path, form: form, query: query, body: body, json: json) | ||
status = response.status | ||
resource = response.body | ||
block_given? ? yield(resource, status, response) : resource | ||
end | ||
|
||
# Placeholder for your request method. | ||
# Accepts these params, for you to do whatever you like with. See the HTTPrb_client implementation | ||
# | ||
# @param [Symbol] method The HTTP VERB to use | ||
# @param [String, URI] path The path, excluding base_url, which should be prepended inside your implementation | ||
# @param [Hash] form: nil Form data, for encoding into HTTP form encoding | ||
# @param [Hash] query: nil Query key/value pairs | ||
# @param [String] body: nil A raw body | ||
# @param [Hash, Array] json: nil Hash/Array data to be encoded as JSON. | ||
def request(*) | ||
raise 'HttpApiBuilder::BaseClient#request must be implemented, see documentation' | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
require 'http' | ||
|
||
module HttpApiBuilder | ||
module Client | ||
# A demonstration implementation, using HTTP.rb | ||
# This is functional and pretty much production ready, but you can | ||
# easily rewrite it to use curb or typhoeus or anything else really | ||
module HttpRb | ||
def request(verb, path, form:, query:, body:, json:) # rubocop:disable Metrics/ParameterLists | ||
url = URI.join(self.class.base_url || '', path) | ||
HTTP.send(verb, url, form: form, params: query, body: body, json: json) | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
require 'forwardable' | ||
|
||
module HttpApiBuilder | ||
# Module for restful api dsl commands | ||
module Dsl | ||
VERBS = | ||
%i(get head post put delete trace options connect) + # HTTP 1.1 | ||
%i(propfind proppatch mkcol copy move lock unlock) + # WebDAV | ||
%i(orderpatch) + # WebDAV Ordered Collections protocol | ||
%i(acl) + # WebDAV Access Control protocol | ||
%i(patch) + # PATCH method for HTTP | ||
%i(search) # WebDAV search | ||
|
||
# Set the initial URL used by the gem | ||
def base_url(value = nil) | ||
value.nil? ? @base_url : (@base_url = value) | ||
end | ||
|
||
protected | ||
|
||
# Generate whiny and quiet API consumer methods. | ||
# | ||
# Whiny methods have a bang suffix and raise errors if they fail | ||
# Quiet methods do not have the bang suffix and return nil if they fail | ||
# | ||
# eg: | ||
# endpoint '/path', as: :mymethod | ||
# results in: | ||
# mymethod! <-- whiny | ||
# mymethod <-- quiet | ||
def endpoint(path, as:, using: :get, params: nil, form: nil, body: nil, processors: nil, json: nil) # rubocop:disable Metrics/ParameterLists | ||
def_whiny_method as, path, using, processors, params, form, body, json | ||
def_quiet_method as | ||
end | ||
|
||
VERBS.each do |v| | ||
define_method v do |path, **opts| | ||
consume path, using: v, **opts | ||
end | ||
end | ||
|
||
private | ||
|
||
# Generate a consumer method that raises exceptions when requests raise an error | ||
# | ||
def def_whiny_method(name, path, using, processors, params, form, body, json) # rubocop:disable Metrics/ParameterLists, Metrics/AbcSize, Metrics/MethodLength | ||
required, optional = requirements(path, params) | ||
|
||
define_method :"#{name}!" do |opts = {}| | ||
validate_args! opts.keys, required, optional | ||
|
||
reqpath = interpolate_path(path, opts) | ||
query = query_params(path, opts, required, optional) | ||
|
||
form = Hash(form).merge(Hash(opts[:form])) | ||
json = opts[:json] || json | ||
body = opts[:body] || body | ||
perform(using, reqpath, form: form, query: query, body: body, json: json) do |resource, *_| | ||
run_processors resource, processors | ||
end | ||
end | ||
end | ||
|
||
# Generate a consumer method that returns nil when requests raise errors | ||
# | ||
def def_quiet_method(name) | ||
define_method name do |opts = {}| | ||
begin | ||
send(:"#{name}!", opts) | ||
rescue StandardError | ||
nil | ||
end | ||
end | ||
end | ||
|
||
# Extract param segments from a path, paperclip style. Returns an array of symbols matching the names of the param segments. | ||
# | ||
# Param segments are sections of the path that begin with `:`, and run to the next / | ||
def interpolated_params(path) | ||
path.split('/').reject { |i| i.length.zero? || i !~ /^:/ }.uniq.map { |i| i[1..-1].to_sym } | ||
end | ||
|
||
# Parse out and return the required and optional arguments | ||
# | ||
# Required are any that are in the URL or in the required hash | ||
# Optional are any other arguments. | ||
def requirements(path, params) | ||
required, optional = Hash(params).values_at(*%i(required optional)).map { |list| Array(list) } | ||
|
||
required += interpolated_params(path) | ||
|
||
[required, optional] | ||
end | ||
end | ||
end |
Oops, something went wrong.