yesod-test: have request not default to the form-urlencoded Content-Type

* Only set the Content-Type to "application/x-www-form-urlencoded" if key-value pairs are added
* Previously the "application/x-www-form-urlencoded" Content-Type would be added even if you set a binary request body.
	* You could add your own Content-Type with addRequestHeader, but this resulted in multiple Content-Type headers.
* Closes #1063
This commit is contained in:
Maximilian Tagher 2015-08-23 11:47:22 -07:00
parent ad7326aaaa
commit 479a19e65a
4 changed files with 50 additions and 3 deletions

View File

@ -1,3 +1,9 @@
## 1.5.0.1
* Fixed the `application/x-www-form-urlencoded` header being added to all requests, even those sending a binary POST body [#1064](https://github.com/yesodweb/yesod/pull/1064/files)
* The `application/x-www-form-urlencoded` Content-Type header is now only added if key-value POST parameters are added
* If no key-values pairs are added, or the request body is set with `setRequestBody`, no default Content-Type header is set
## 1.5 ## 1.5
* remove deprecated addNonce functions * remove deprecated addNonce functions

View File

@ -876,8 +876,7 @@ request reqBuilder = do
SRequest simpleRequest' (simpleRequestBody' rbdPostData) SRequest simpleRequest' (simpleRequestBody' rbdPostData)
where where
simpleRequest' = (mkRequest simpleRequest' = (mkRequest
[ ("Cookie", cookieValue) ([ ("Cookie", cookieValue) ] ++ headersForPostData rbdPostData)
, ("Content-Type", "application/x-www-form-urlencoded")]
method extraHeaders urlPath urlQuery) method extraHeaders urlPath urlQuery)
simpleRequestBody' (MultipleItemsPostData x) = simpleRequestBody' (MultipleItemsPostData x) =
BSL8.fromChunks $ return $ TE.encodeUtf8 $ T.intercalate "&" BSL8.fromChunks $ return $ TE.encodeUtf8 $ T.intercalate "&"
@ -889,6 +888,13 @@ request reqBuilder = do
singlepartPart (ReqFilePart _ _ _ _) = "" singlepartPart (ReqFilePart _ _ _ _) = ""
singlepartPart (ReqKvPart k v) = T.concat [k,"=",v] singlepartPart (ReqKvPart k v) = T.concat [k,"=",v]
-- If the request appears to be submitting a form (has key-value pairs) give it the form-urlencoded Content-Type.
-- The previous behavior was to always use the form-urlencoded Content-Type https://github.com/yesodweb/yesod/issues/1063
headersForPostData (MultipleItemsPostData []) = []
headersForPostData (MultipleItemsPostData _ ) = [("Content-Type", "application/x-www-form-urlencoded")]
headersForPostData (BinaryPostData _ ) = []
-- General request making -- General request making
mkRequest headers method extraHeaders urlPath urlQuery = defaultRequest mkRequest headers method extraHeaders urlPath urlQuery = defaultRequest
{ requestMethod = method { requestMethod = method

View File

@ -18,12 +18,13 @@ import Text.XML
import Data.Text (Text, pack) import Data.Text (Text, pack)
import Data.Monoid ((<>)) import Data.Monoid ((<>))
import Control.Applicative import Control.Applicative
import Network.Wai (pathInfo) import Network.Wai (pathInfo, requestHeaders)
import Data.Maybe (fromMaybe) import Data.Maybe (fromMaybe)
import Data.ByteString.Lazy.Char8 () import Data.ByteString.Lazy.Char8 ()
import qualified Data.Map as Map import qualified Data.Map as Map
import qualified Text.HTML.DOM as HD import qualified Text.HTML.DOM as HD
import Network.HTTP.Types.Status (unsupportedMediaType415)
parseQuery_ = either error id . parseQuery parseQuery_ = either error id . parseQuery
findBySelector_ x = either error id . findBySelector x findBySelector_ x = either error id . findBySelector x
@ -160,6 +161,30 @@ main = hspec $ do
setMethod "POST" setMethod "POST"
setUrl ("/labels" :: Text) setUrl ("/labels" :: Text)
byLabel "Foo Bar" "yes" byLabel "Foo Bar" "yes"
ydescribe "Content-Type handling" $ do
yit "can set a content-type" $ do
request $ do
setUrl ("/checkContentType" :: Text)
addRequestHeader ("Expected-Content-Type","text/plain")
addRequestHeader ("Content-Type","text/plain")
statusIs 200
yit "adds the form-urlencoded Content-Type if you add parameters" $ do
request $ do
setUrl ("/checkContentType" :: Text)
addRequestHeader ("Expected-Content-Type","application/x-www-form-urlencoded")
addPostParam "foo" "foobarbaz"
statusIs 200
yit "defaults to no Content-Type" $ do
get ("/checkContentType" :: Text)
statusIs 200
yit "returns a 415 for the wrong Content-Type" $ do
-- Tests that the test handler is functioning
request $ do
setUrl ("/checkContentType" :: Text)
addRequestHeader ("Expected-Content-Type","application/x-www-form-urlencoded")
addRequestHeader ("Content-Type","text/plain")
statusIs 415
describe "cookies" $ yesodSpec cookieApp $ do describe "cookies" $ yesodSpec cookieApp $ do
yit "should send the cookie #730" $ do yit "should send the cookie #730" $ do
get ("/" :: Text) get ("/" :: Text)
@ -225,6 +250,15 @@ app = liteApp $ do
onStatic "labels" $ dispatchTo $ onStatic "labels" $ dispatchTo $
return ("<html><label><input type='checkbox' name='fooname' id='foobar'>Foo Bar</label></html>" :: Text) return ("<html><label><input type='checkbox' name='fooname' id='foobar'>Foo Bar</label></html>" :: Text)
onStatic "checkContentType" $ dispatchTo $ do
headers <- requestHeaders <$> waiRequest
let actual = lookup "Content-Type" headers
expected = lookup "Expected-Content-Type" headers
if actual == expected
then return ()
else sendResponseStatus unsupportedMediaType415 ()
cookieApp :: LiteApp cookieApp :: LiteApp
cookieApp = liteApp $ do cookieApp = liteApp $ do

View File

@ -60,6 +60,7 @@ test-suite test
, yesod-form , yesod-form
, text , text
, wai , wai
, http-types
source-repository head source-repository head
type: git type: git