Sometimes it is useful to read header values when processing a request. In this article we will see how to achieve this in a Servant application.
Why and where do we need this? In my case, I wanted to read the User-Agent string to decide if I redirect the request to a different location. Since my Currency Converter Chrome Extension only makes sense with a Chrome Browser, I wanted to redirect users with a Chrome Browser directly to the extension page. Otherwise I would provide a simple web version of the Currency Converter NEO.
As usual, let's see how it would be done in a very popular Web-Framework like Symfony:
public function getMyAction(Request $request)
{
$userAgent = $request->headers->get('User-Agent');
return new RedirectResponse('...'); }
As expected, we get the Request as an object from the action parameters. On this object we can access all headers we are interested in (i.e. User-Agent).
Servant on the other hand works a bit different. We can define the header access directly in our server path types:
type CurrencyConverterAPI = "currency-converter-neo" :> Header "User-Agent" Text :> Get '[HTML] (CurrencyConverterPage)
As you can see, we match on the static string "currency-converter-neo" by a following Header definition. As well, we define a type that we expect, Text in this case. With this server route type we can access our header directly in out function:
currencyConverterPage :: (MonadIO m) => Maybe Text -> AppT m CurrencyConverterPage
= do
currencyConverterPage mUserAgent -- TODO: Imlementation
Consequently our function expect a Maybe Text, since we can not be sure that the requested header is really set. Servant forces us a bit to check for both cases!
Thank you for reading this far! Let’s connect. You can @ me on X (@debilofant) with comments, or feel free to follow. Please like/share this article so that it reaches others as well.