-
Notifications
You must be signed in to change notification settings - Fork 61
HTTP Headers
Sometimes, you need to send custom HTTP headers.
For Twirp, HTTP headers are a transport implementation detail, you should not have to worry about headers, but maybe your HTTP middleware requires them.
All client methods can have options as an optional second parameter. Use the :headers option to send custom headers. For example:
client.hello({name: 'World'}, headers: {'X-My-Header' => 'foobar', 'Auth-Token' => 'fxdafxda'})Twirp client responses are objects that depend only on the Protobuf response. HTTP headers in the response can not be used by the Twirp client in any way.
However, the Twirp client can be configured with Faraday, that can have custom middleware to handle response headers (for example to manage a local cache).
In your service handler implementation, set the special env[:http_response_headers] value to set response headers. For example:
class HelloWorldHandler
def hello(req, env)
env[:http_response_headers]['Cache-Control'] = 'public, max-age=60'
{message: "Hello #{req.name}"}
end
endTwirp service handler methods are abstracted away from HTTP, therefore they don't have direct access to HTTP Headers. However, they receive an env argument with values that can be modified by before hooks. Service before hooks have access to the raw rack_env, where they can read headers and add values to the twirp env.
For example, to read the 'X-My-Header' HTTP header, the service before hook can be like this:
service = Example::HelloWorld::HelloWorldService.new(handler)
service.before do |rack_env, env|
env[:my_x_header] = rack_env['HTTP_MY_X_HEADER'] # << Rack HTTP header
endNow the handler implementation can access the custom property env[:my_x_header], for example:
class HelloWorldHandler
def hello(req, env)
puts env[:my_x_header] # << value from header
{message: "Hello #{req.name}"}
end
endWhile this approach requires more setup, it effectively separates HTTP details from the Twirp service implementation, which depends only on the protobuf request object and the Twirp environment. When testing this code, you only need to add the env[:my_x_header] value and forget about HTTP details (e.g. service.call_rpc(:Hello, {name: 'foo'}, env={my_x_header: 'foobar'}). See Unit Tests for more info on testing.