Skip to content

Instantly share code, notes, and snippets.

@maxhoffmann
Last active February 8, 2018 23:57
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save maxhoffmann/129d72fd2f87090af864c63e30098a6d to your computer and use it in GitHub Desktop.
Save maxhoffmann/129d72fd2f87090af864c63e30098a6d to your computer and use it in GitHub Desktop.
Token HTTP Authentication in Elm
import Html.App as Html
import Html exposing (..)
import Html.Events exposing (..)
import Task
import Http
import Json.Decode as Json exposing ((:=))
-- Model
type alias Model =
{ token : Token
, pendingRequests : List (String -> Task.Task Never Msg)
, ip : String
}
type Token
= Valid String
| Invalid
| Refreshing
init : ( Model, Cmd Msg )
init =
( Model (Valid "expired") [] "no ip", Cmd.none )
-- Update
type Msg
= Fetch
| FetchFailure Http.Error
| SaveIp String
| SaveRequest (String -> Task.Task Never Msg)
| RefreshTokenFailed Never
| UpdateToken String
| SendPendingRequests ()
attemptWithToken : Token -> (x -> msg) -> (a -> msg) -> (String -> Task.Task x a) -> Cmd msg
attemptWithToken token failureMsg successMsg requestWithoutToken =
case token of
Invalid ->
Cmd.none
Refreshing ->
Cmd.none
Valid token ->
Task.perform failureMsg successMsg (requestWithoutToken token)
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
Fetch ->
( model, attemptWithToken model.token FetchFailure SaveIp fetchIp )
FetchFailure error ->
( { model | token = Refreshing }, Task.perform RefreshTokenFailed UpdateToken (Task.succeed "valid") )
SaveIp ip ->
( { model | ip = ip }, Cmd.none )
-- Token Logic
SaveRequest request ->
( { model | pendingRequests = request :: model.pendingRequests }, Cmd.none )
RefreshTokenFailed error ->
( model, Cmd.none )
UpdateToken newToken ->
( { model | token = Valid newToken }, Task.perform SendPendingRequests SendPendingRequests (Task.succeed ()) )
SendPendingRequests _ ->
( model, Cmd.none )
-- View
view : Model -> Html Msg
view model =
div []
[ button [ onClick Fetch ] [ text "send request" ]
, text model.ip
]
-- Request
fetchIp : String -> Task.Task Http.Error String
fetchIp token =
if token == "expired" then
Http.get ("ip" := Json.string) ("http://thisfails" ++ token)
else
Http.get ("ip" := Json.string) ("http://jsonip.com?token=" ++ token)
-- Main
main : Program Never
main =
Html.program
{ init = init
, update = update
, view = view
, subscriptions = \_ -> Sub.none
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment