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 nothing but a pattern following a known convention for “controlled patching”. In order for you to create a plugin you can follow the following steps:
This part is straightforward
# There you go 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
RequestMethods: methods will be added to the session Requests
ResponseMethods: methods will be added to the session Responses
HeadersMethods: methods will be added to the Headers of the above
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 Connections
0.16) methods will be added to the session Options
module 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 Options # 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
# same example from above module HTTPX::Plugins module Custom def self.extra_options(options) options.merge(bar: 2) 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
:authentication 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(:authentication) end end module InstanceMethods def authenticate token = InternalAuth.generate authentication(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.