Search code examples
httphttp-headersjwtelm

How to get Response Headers upon HTTP Request?


I have the following code where I make a post request and I have set Authorization header with JWToken in my server. I wish to extract the JWToken from the response header and save it in local storage using port. How to get hold of the Response? I see Metadata which has Headers in the Response type. ref - https://package.elm-lang.org/packages/elm/http/latest/Http#Response

type Msg
  = EnteredEmail String
  | EnteredPassword String
  | SubmittedForm
  | RegistrationSuccess (Result Http.Error ())


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
  case msg of

    EnteredEmail email ->
      updateForm (\form -> { form | email = email }) model

    EnteredPassword password ->
      updateForm (\form -> { form | password = password }) model

    RegistrationSuccess _->
      -- TODO save JWT in local storage on successful registration
      (model, Cmd.none)

    SubmittedForm ->
      -- TODO validate the form
      (model, postCall model)


postCall : Model -> Cmd Msg
postCall model = Http.post {
          url = "http://localhost:9000/register",
          body = Http.jsonBody (
            Json.Encode.object[
              ("age", Json.Encode.int 30),
              ("email", Json.Encode.string model.form.email),
              ("password", Json.Encode.string model.form.password)
            ]
          ),
          expect = Http.expectWhatever RegistrationSuccess
        }

Solution

  • You can get to the Response and headers by using Http.expectStringResponse or Http.expectBytesResponse instead of Http.expectWhatever.

    Here's an example that defines a convenience function expectJWT which will retrieve and return the Authorization header, or if it does not exist returns BadStatus 403. In postCall all that's changed is that Http.expectWhatever has been replaced with expectJWT:

    expectJWT : (Result Http.Error String -> msg) -> Http.Expect msg
    expectJWT toMsg =
        Http.expectStringResponse toMsg <|
            \response ->
                case response of
                    Http.BadUrl_ url ->
                        Err (Http.BadUrl url)
    
                    Http.Timeout_ ->
                        Err Http.Timeout
    
                    Http.NetworkError_ ->
                        Err Http.NetworkError
    
                    Http.BadStatus_ metadata body ->
                        Err (Http.BadStatus metadata.statusCode)
    
                    Http.GoodStatus_ metadata body ->
                        metadata.headers
                            |> Dict.get "Authorization"
                            |> Result.fromMaybe (Http.BadStatus 403)
    
    postCall : Model -> Cmd Msg
    postCall model = Http.post {
              url = "http://localhost:9000/register",
              body = Http.jsonBody (
                Json.Encode.object[
                  ("age", Json.Encode.int 30),
                  ("email", Json.Encode.string model.form.email),
                  ("password", Json.Encode.string model.form.password)
                ]
              ),
              expect =  expectJWT RegistrationSuccess
            }