By now, you know that most of the features from this library are added as plugins.
Plugins are activated for a single session, once you call .plugin
, and calls can be concatenated in order for load multiple plugins:
# enabling follow redirects plugin
session = HTTPX.plugin(:follow_redirects)
# enabling new session with cookies plugin
session_with_cookies = session.plugin(:cookies)
Plugins are a pattern following a convention for “controlled patching”. In order for you to create a plugin you can follow the following steps:
This part is straightforward
# The simplest plugin which does nothing
module MyPlugin
end
custom_session = HTTPX.plugin(MyPlugin)
1.1 (Optionally) register it
Plugins can be called via a symbol (like the :cookies
example from above). For that to happen, you have to register them. There a few rules for that, described in the gist below:
# 1. Create your plugin module under lib/httpx/plugins
#
# for this example: lib/httpx/plugins/custom.rb
#
module HTTPX::Plugins
module Custom
end
register :custom, Custom
end
# now you can:
custom_session = HTTPX.plugin(:custom)
That’s it, your “minimal viable product”.
Methods can be added to some of the internal components, by defining certain modules within your plugin:
InstanceMethods
: methods will be added to the session.HeadersMethods
: methods will be added to the headers of the above.RequestMethods
: methods will be added to the session requests.ResponseMethods
: methods will be added to the session responses.RequestBodyMethods
: methods will be added to the session Request Body.ResponseBodyMethods
: methods will be added to the session Response Body.ConnectionMethods
: methods will be added to the session connectionsOptionsMethods
: methods will be added to the session optionsmodule HTTPX::Plugins
module Custom
module InstanceMethods
def foo
"foo"
end
end
end
# ...
end
HTTPX.plugin(:custom).foo #=> "foo"
Options can be passed through all layers, and reused inside of your plugins. You have to define them first:
session = HTTPX.plugin(:custom, bar: 1) #=> "unknown option: bar"
In order for you to do that, you have to define the “transformer” method on the OptionsMethods
, which you do by creating a method with the “option_” prefix, followed by the option:
module HTTPX::Plugins
module Custom
module OptionsMethods
# creates :bar option
def option_bar(value)
# must be an integer
Integer(value)
end
end
module InstanceMethods
def foo
@options.bar
end
end
end
# ...
end
HTTPX.plugin(:custom).foo #=> nil
HTTPX.plugin(:custom, bar: 2).foo #=> 2
HTTPX.plugin(:custom).with(bar: 1).foo #=> 1
HTTPX.plugin(:custom).with(bar: "a").foo #=> invalid value for Integer(): "a" (ArgumentError)
In case you want to provide a sensible default for an option, you can use the “hook” method extra_options
:
# same example from above
module HTTPX::Plugins
module Custom
def self.extra_options(options)
options.merge(bar: 2)
end
# ...
end
end
HTTPX.plugin(:custom).foo #=> 2
Your custom plugin might depend on external libraries. For example, you might want to integrate with some internal token generation gem, and assign those tokens on each request. The plugin system provides two “hooks” one can use for this goal:
load_dependencies(session_class)
: called at the beginning of the loading process, can be used, p.ex. to require dependencies, or some other form of pre-processing;configure(session_class)
: called at the end of the loading process, can do some post-processing; also used to load other plugins implicitly;For our example, you then use a combination of all above methods to load the gem, load the :auth
plugin for convenience auth helpers, and off we go:
module HTTPX::Plugins
module Custom
class << self
def load_dependencies(*)
require "internal_auth"
end
def configure(klass)
klass.plugin(:auth)
end
end
module InstanceMethods
def authenticate
token = InternalAuth.generate
bearer_auth(token)
end
end
end
# ...
end
HTTPX.plugin(:custom).authenticate.get("https://internal-smth/action") #=> "..Authorization: Bearer custom-token..."
You’re kindly invited to look at the existing plugins to understand the possibilities of what could be done.
Next: Integrations