Customization
The Request
type is a opaque type that describes how to make an HTTP request.
Each Request
can be customized using the update functions in Api.elm
, e.g. for adding headers, changing the base path or setting a timeout. Using the send
function and a Msg
the request can be converted to a Cmd Msg
which allows Elm to make the actual call.
The customization also allows you to set-up your own generic solution for making HTTP requests.
Let's say you need to add an authentication header to each request and your base path is loaded from your program's flags.
You capture this data and store it in a Server
record.
The customization enables you to define your own send
function like this:
type alias Server =
{ basePath : String
, accessToken : String
}
send : Server -> (Result Http.Error a -> msg) -> Request a -> Cmd msg
send { basePath, accessToken } toMsg request =
request
|> Api.withBasePath basePath
|> Api.withHeader "ACCESS_TOKEN" accessToken
|> Api.send toMsg
Now throughout your program you can use this function instead of the default Api.send
.
The following sub-sections explain the possible customizations.
map
Api.map
allows you to change the return type of a Request
by mapping a Request a
to a Request b
.
This may be useful when the OpenAPI specification returns a different type from what you would like to use.
As an example let's assume we generated the following function:
updateUser : Api.Data.User -> Api.Request Api.Data.User
updateUser
takes and gives us a Api.Data.User
. If we rather work with our
own CustomUser
instead we can map both the input and the output types using
composition and Api.map
:
toCustomUser : Api.Data.User -> CustomUser
fromCustomUser : CustomUser -> Api.Data.User
updateCustomUser : CustomUser -> Api.Request CustomUser
updateCustomUser = Api.map toCustomUser << updateUser << fromCustomUser
We now should use updateCustomUser
instead of updateUser
.
withBasePath
You can override the base path as defined in the OpenAPI specification.
You can do this per request or you can fully customize the Api.send
.
An example:
sendWithBasePath : (Result Http.Error a -> msg) -> Request a -> Cmd msg
sendWithBasePath toMsg request =
request
|> Api.withBasePath "http://elm-lang.org"
|> Api.send toMsg
withTimeout
By default, Elm HTTP requests have no timeout.
You can set one per request or you can fully customise the Api.send
.
The timeout is defined in milliseconds.
An example:
sendWithTimeout : (Result Http.Error a -> msg) -> Request a -> Cmd msg
sendWithTimeout toMsg request =
request
|> Api.withTimeout 30000
|> Api.send toMsg
withTracker
Elm HTTP allows you to track requests.
Setting the same tracker for each request probably does not make much sense, but you can set one per requests or fully customize the Api.send
to accept one.
An example:
sendAndTrack : String -> (Result Http.Error a -> msg) -> Request a -> Cmd msg
sendAndTrack tracker toMsg request =
request
|> Api.withTracker tracker
|> Api.send toMsg
withBearerToken
OpenAPI allows you to specify what security scheme your API uses. When using bearer authorization a header with the token is added using this function.
An example:
sendAuthenticated : String -> (Result Http.Error a -> msg) -> Request a -> Cmd msg
sendAuthenticated token toMsg request =
request
|> Api.withBearerToken token
|> Api.send toMsg
withHeader
and withHeaders
OpenAPI allows you to specify what headers need to be send. On top of that you can define your own additional (set of) header(s) on each request.
An example:
sendWithHeader : (Result Http.Error a -> msg) -> Request a -> Cmd msg
sendWithHeader toMsg request =
request
|> Api.withHeader "Max-Forwards" "10"
|> Api.send toMsg
send
and sendWithCustomError
The basic send
function takes a Request a
and eventually results in a message of Result Http.Error a
once the Cmd
is handled by the Elm runtime.
sendWithCustomError
allows you to map the Http.Error
before making the actual request.
This allows you to add custom error handling for all your requests.
An example:
type ApiError
= Unauthorized
| Forbidden
| NotFound
| ApiError String
sendWithCustomError : (Result ApiError a -> msg) -> Request a -> Cmd msg
sendWithCustomError =
Api.sendWithCustomError (\result ->
case result of
Ok v ->
Ok v
Err (BadUrl _) ->
ApiError "Oops, we messed up!"
Err Timeout ->
ApiError "Server timeout. Please try again later."
Err NetworkError ->
ApiError "Network error."
Err (BadStatus code) ->
case code of
401 ->
Unauthorized
403 ->
Forbidden
404 ->
NotFound
_ ->
ApiError "Oops, the request failed."
Err (BadBody _) ->
ApiError "Oops, we messed up!"
)
task
Just like Elm's Http library, the generator also supports both commands and tasks.
You can use task
to create a Task
from a Request
.
If you simply need a Cmd msg
then send
is the better option here.
Note: tracking requests is not supported when using tasks as it is also not supported in the native library.