haskell-servant / servant-elm

Automatically derive Elm functions to query servant webservices
BSD 3-Clause "New" or "Revised" License
164 stars 48 forks source link

Uppercase header names result in invalid elm code #21

Closed Crote closed 7 years ago

Crote commented 7 years ago

Given an API like

type SecureApi =
  Header "Authentication" String :> "item" :> Get '[JSON] [Item]

servant-elm will generate

getItem : String -> Http.Request (List (Item))
getItem Authentication =
    Http.request
        { method =
            "GET"
        , headers =
            [ Http.header "Authentication" Authentication
            ]
        , url =
            String.join "/"
                [ ""
                , "item"
                ]
        , body =
            Http.emptyBody
        , expect =
            Http.expectJson (list decodeItem)
        , timeout =
            Nothing
        , withCredentials =
            False
        }

...

which will result in the compile error Cannot find pattern 'Authentication'.

A trivial fix would be to convert the header name to lowercase before generating the elm code, resulting in a valid variable name.

Note that, although

type SecureApi =
  Header "Authentication" String :> Header "authentication" String :> "item" :> Get '[JSON] [Item]

will compile into a valid servant API, it is not a valid definition: the relevant RFC states that header names are case-insensitive. If either variant is is set by the client, both variants will have that value in servant, with the uppercase one having precedence if both are set. Converting the header name to lowercase can therefore never result in a name clash with another header.

mattjbray commented 7 years ago

Hi @Crote, thanks for doing the research on this. Lower-casing the first letter of the header name seems like an acceptable solution.

I can see the same problem arising for captures and query params too though. Perhaps prefixing all of the arguments with cap_, query_ or header_ would be a more general solution.