Skip to content

Instantly share code, notes, and snippets.

@webuilder240
Last active March 20, 2020 12:17
Show Gist options
  • Save webuilder240/3b2213456731d74a637b95e48f682570 to your computer and use it in GitHub Desktop.
Save webuilder240/3b2213456731d74a637b95e48f682570 to your computer and use it in GitHub Desktop.
FaradayっぽいインターフェイスのHTTPクライアント
require './demo_http.rb'
client = DemoHttp::Client.new do |configure|
configure.open_timeout = 5
configure.read_timeout = 9
configure.max_attempts = 5
configure.url = "https://httpstat.us"
end
paths = %w(200 404 500)
paths.each do |path|
begin
response = client.get("/#{path}") do |request|
request.params = {body: "hello"}
end
rescue DemoHttp::HttpClientError => e
puts "client error"
puts e.response.to_h
rescue DemoHttp::HttpServerError => e
puts "server error"
puts e.response.to_h
rescue DemoHttp::ReadTimeout => e
puts "timeout"
puts e
end
puts response.to_h
end
begin
error_client = DemoHttp::Client.new do |configure|
configure.open_timeout = 5
configure.read_timeout = 9
configure.max_attempts = 5
end
rescue DemoHttp::ConfigureError => e
puts "set http url"
end
require "net/http"
require 'json'
module DemoHttp
class HttpClientError < StandardError
attr_accessor :response
end
class HttpServerError < StandardError
attr_accessor :response
end
class ReadTimeout < StandardError; end
class HttpNotFound < HttpClientError; end
class HttpTimeoutError < HttpClientError; end
class ConfigureError < StandardError; end
class Configure
attr_accessor :max_attempts, :url, :headers, :open_timeout, :read_timeout
def initialize
@max_attempts = 5
@headers = {}
@content_type = "json"
@open_timeout = 5
@read_timeout = 30
end
end
class Client
def initialize
yield configure if block_given?
end
def configure
@configure ||= Configure.new
end
def get (path = nil, &block)
invoke(method: __method__, path: path, &block)
end
def post(path = nil, &block)
invoke(method: __method__, path: path, &block)
end
def put(path = nil, &block)
invoke(method: __method__, path: path, &block)
end
def patch(path = nil, &block)
invoke(method: __method__, path: path, &block)
end
def delete(path = nil, &block)
invoke(method: __method__, path: path, &block)
end
def invoke(method:, path:, &block)
raise ConfigureError.new("Please set URL") if configure.url.nil? || configure.url.empty?
block.call request if block_given?
request.path = path unless path.nil?
begin
original_response = _invoke(method)
rescue Net::ReadTimeout => e
raise ReadTimeout
end
response = Response.new(request, original_response.code, original_response.body, original_response.header)
handling_raise_http_error(response)
end
private
def _invoke(method_name)
h = http_request(method_name)
h.content_type = "application/json"
http.use_ssl = target_uri.include?("https://")
http.request(h)
end
def uri
@uri = URI.parse(target_uri)
end
def http
@http ||= Net::HTTP.new(uri.hostname, uri.port).tap do |h|
h.open_timeout = configure.open_timeout
h.read_timeout = configure.read_timeout
end
end
def http_request(method_name)
case method_name
when :get
Net::HTTP::Get.new(uri.request_uri)
when :post
Net::HTTP::Post.new(uri.request_uri)
when :put
Net::HTTP::Put.new(uri.request_uri)
when :patch
Net::HTTP::Patch.new(uri.request_uri)
when :delete
Net::HTTP::Delete.new(uri.request_uri)
end
end
def request
@request ||= Request.new
end
def handling_raise_http_error(response)
case response.status
when 200...399
response
when 404
e = HttpNotFound.new
e.response = response
raise e
when 400...499
e = HttpClientError.new
e.response = response
raise e
when 500...599
e = HttpServerError.new
e.response = response
raise e
else
response
end
end
def target_uri()
"#{configure.url}#{request.path}"
end
end
class Request
attr_accessor :path, :params, :header
def initialize
@path = "/"
@params = {}
@header = {}
end
end
class Response
attr_reader :request, :status, :body, :header
def initialize(request, status, body, header)
@request = request
@status = status.to_i
@body = body
@header = header
end
def to_h
{
request: request,
status: status,
header: header,
}
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment