mirror of
https://github.com/HoneyryderChuck/httpx.git
synced 2025-09-14 00:00:44 -04:00
added registry module, where one can register by a tag; introducing transcoder, modules which can encode and decode; using them for the body/form/json bodies
This commit is contained in:
parent
e7b943ba39
commit
fbdd7e2dd8
@ -1,8 +1,11 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
|
||||
require "httpx/version"
|
||||
|
||||
require "httpx/errors"
|
||||
require "httpx/callbacks"
|
||||
require "httpx/registry"
|
||||
require "httpx/transcoder"
|
||||
require "httpx/options"
|
||||
require "httpx/timeout"
|
||||
require "httpx/connection"
|
||||
|
84
lib/httpx/registry.rb
Normal file
84
lib/httpx/registry.rb
Normal file
@ -0,0 +1,84 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module HTTPX
|
||||
# Adds a general-purpose registry API to a class. It is designed to be a
|
||||
# configuration-level API, i.e. the registry is global to the class and
|
||||
# should be set on **boot time**.
|
||||
#
|
||||
# It is used internally to associate tags with handlers.
|
||||
#
|
||||
# ## Register/Fetch
|
||||
#
|
||||
# One is strongly advised to register handlers when creating the class.
|
||||
#
|
||||
# There is an instance-level method to retrieve from the registry based
|
||||
# on the tag:
|
||||
#
|
||||
# class Server
|
||||
# include HTTPX::Registry
|
||||
#
|
||||
# register "tcp", TCPHandler
|
||||
# register "ssl", SSLHandlers
|
||||
# ...
|
||||
#
|
||||
#
|
||||
# def handle(uri)
|
||||
# scheme = uri.scheme
|
||||
# handler = registry(scheme) #=> TCPHandler
|
||||
# handler.handle
|
||||
# end
|
||||
# end
|
||||
#
|
||||
module Registry
|
||||
# Base Registry Error
|
||||
Error = Class.new(Error)
|
||||
|
||||
def self.extended(klass)
|
||||
super
|
||||
klass.extend(ClassMethods)
|
||||
end
|
||||
|
||||
def self.included(klass)
|
||||
super
|
||||
klass.extend(ClassMethods)
|
||||
klass.__send__(:include, InstanceMethods)
|
||||
end
|
||||
|
||||
# Class Methods
|
||||
module ClassMethods
|
||||
# @param [Object] tag the handler identifier in the registry
|
||||
# @return [Symbol, String, Object] the corresponding handler (if Symbol or String,
|
||||
# will assume it referes to an autoloaded module, and will load-and-return it).
|
||||
#
|
||||
def registry(tag = nil)
|
||||
@registry ||= {}
|
||||
return @registry if tag.nil?
|
||||
handler = @registry.fetch(tag)
|
||||
raise(Error, "#{tag} is not registered in #{self}") unless handler
|
||||
case handler
|
||||
when Symbol, String
|
||||
const_get(handler)
|
||||
else
|
||||
handler
|
||||
end
|
||||
end
|
||||
|
||||
# @param [Object] tag the identifier for the handler in the registry
|
||||
# @return [Symbol, String, Object] the handler (if Symbol or String, it is
|
||||
# assumed to be an autoloaded module, to be loaded later)
|
||||
#
|
||||
def register(tag, handler)
|
||||
registry[tag] = handler
|
||||
end
|
||||
end
|
||||
|
||||
# Instance Methods
|
||||
module InstanceMethods
|
||||
# delegates to HTTPX::Registry#registry
|
||||
def registry(tag)
|
||||
self.class.registry(tag)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,8 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "http/form_data"
|
||||
require "json"
|
||||
|
||||
module HTTPX
|
||||
class Request
|
||||
METHODS = [
|
||||
@ -72,18 +69,14 @@ module HTTPX
|
||||
@headers = headers
|
||||
@body = case
|
||||
when options.body
|
||||
options.body
|
||||
Transcoder.registry("body").encode(options.body)
|
||||
when options.form
|
||||
form = HTTP::FormData.create(options.form)
|
||||
@headers["content-type"] = form.content_type
|
||||
@headers["content-length"] = form.content_length
|
||||
form
|
||||
Transcoder.registry("form").encode(options.form)
|
||||
when options.json
|
||||
body = JSON.dump(options.json)
|
||||
@headers["content-type"] = "application/json; charset=#{body.encoding.name.downcase}"
|
||||
@headers["content-length"] = body.bytesize
|
||||
body
|
||||
Transcoder.registry("json").encode(options.json)
|
||||
end
|
||||
@headers["content-type"] ||= @body.content_type
|
||||
@headers["content-length"] ||= @body.content_length
|
||||
end
|
||||
|
||||
def each(&block)
|
||||
|
11
lib/httpx/transcoder.rb
Normal file
11
lib/httpx/transcoder.rb
Normal file
@ -0,0 +1,11 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module HTTPX
|
||||
module Transcoder
|
||||
extend Registry
|
||||
end
|
||||
end
|
||||
|
||||
require "httpx/transcoder/body"
|
||||
require "httpx/transcoder/form"
|
||||
require "httpx/transcoder/json"
|
36
lib/httpx/transcoder/body.rb
Normal file
36
lib/httpx/transcoder/body.rb
Normal file
@ -0,0 +1,36 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module HTTPX::Transcoder
|
||||
module Body
|
||||
module_function
|
||||
|
||||
class Encoder
|
||||
def initialize(body)
|
||||
@raw = body
|
||||
end
|
||||
|
||||
def to_str
|
||||
@raw
|
||||
end
|
||||
|
||||
def content_length
|
||||
if @raw.respond_to?(:bytesize)
|
||||
@raw.bytesize
|
||||
elsif @raw.respond_to?(:size)
|
||||
@raw.size
|
||||
else
|
||||
raise Error, "cannot determine size of body: #{@raw.inspect}"
|
||||
end
|
||||
end
|
||||
|
||||
def content_type
|
||||
"application/octet-stream"
|
||||
end
|
||||
end
|
||||
|
||||
def encode(body)
|
||||
Encoder.new(body)
|
||||
end
|
||||
end
|
||||
register "body", Body
|
||||
end
|
14
lib/httpx/transcoder/form.rb
Normal file
14
lib/httpx/transcoder/form.rb
Normal file
@ -0,0 +1,14 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "http/form_data"
|
||||
|
||||
module HTTPX::Transcoder
|
||||
module Form
|
||||
module_function
|
||||
|
||||
def encode(form)
|
||||
HTTP::FormData.create(form)
|
||||
end
|
||||
end
|
||||
register "form", Form
|
||||
end
|
33
lib/httpx/transcoder/json.rb
Normal file
33
lib/httpx/transcoder/json.rb
Normal file
@ -0,0 +1,33 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "json"
|
||||
|
||||
module HTTPX::Transcoder
|
||||
module JSON
|
||||
module_function
|
||||
|
||||
class Encoder
|
||||
def initialize(json)
|
||||
@raw = ::JSON.dump(json)
|
||||
@charset = @raw.encoding.name.downcase
|
||||
end
|
||||
|
||||
def content_type
|
||||
"application/json; charset=#{@charset}"
|
||||
end
|
||||
|
||||
def content_length
|
||||
@raw.bytesize
|
||||
end
|
||||
|
||||
def to_str
|
||||
@raw
|
||||
end
|
||||
end
|
||||
|
||||
def encode(json)
|
||||
Encoder.new(json)
|
||||
end
|
||||
end
|
||||
register "json", JSON
|
||||
end
|
Loading…
x
Reference in New Issue
Block a user