Skip to content

addPostParam adds POST parameters backwards #1846

@jezen

Description

@jezen

Web browsers submit POST parameters from forms encoded with application/x-www-form-urlencoded in tree-order.

Here's a form containing two fields sharing the same name.

<form enctype="application/x-www-form-urlencoded" method="post">
  <input type="text" name="money" value="USD">
  <input type="text" name="money" value="100">
</form>

When this is submitted, the order of the values should be preserved, and matching on the order of those values should work (and indeed, in a web browser, it does).

moneyField :: YesodMoneyField app => Field (HandlerFor app) Money.SomeDense
moneyField = Field parse view UrlEncoded
  where
  parse [currency, amount] _fileVals =
    case readMay amount of
      Nothing -> pure $ Right Nothing
      Just n  -> pure $ Right $ Money.mkSomeDense currency (toRational n)
  parse _ _ = pure $ Right Nothing

  view theId name attrs _eVal isReq = do
    -- not relevant…

However, if you were to write a test for this…

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}

module MoneyFieldSpec where

import TestImport

spec :: Spec
spec = withApp $ do

  it "Fails with bad input" $ do
    get HomeR
    request $ do
      addToken
      setUrl HomeR
      setMethod "POST"
      addPostParam "money" "XXX"
      addPostParam "money" "XXX"
    statusIs 400

  it "Supports USD" $ do
    get HomeR
    request $ do
      addToken
      setUrl HomeR
      setMethod "POST"
      -- These two lines are in the wrong order, but that's because yesod-test
      -- adds POST parameters in the wrong order — instead of appending each
      -- parameter to the list of parameters, it conses them, which is not what
      -- web browers do.
      addPostParam "money" "100"
      addPostParam "money" "USD"
    location <- followRedirect
    liftIO $ location `shouldBe` Right "/"
    bodyContains "Amount is USD 100"

The test will fail because — as written in the comment — addPostParam conses params rather than appending them.

I expect fixing this is simply a case of appending each param instead of consing.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions