Sun Aug 8 14:49:48 IDT 2010 michael@snoyman.com * Query string support. New patches: [Query string support. michael@snoyman.com**20100808114948 Ignore-this: 42ea0111444e3852c9129af1c700650d ] { hunk ./web-routes/Web/Routes/Base.hs 243 \"%D7%A9%D7%9C%D7%95%D7%9D\" -} -encodePathInfo :: [String] -> String -encodePathInfo = - map encodeString `o` -- utf-8 encode the data characters in path components (we have not added any delimiters yet) - map (escapeURIString (\c -> isUnreserved c || c `elem` ":@&=+$,")) `o` -- percent encode the characters - map (\str -> case str of "." -> "%2E" ; ".." -> "%2E%2E" ; _ -> str) `o` -- encode . and .. - intercalate "/" -- add in the delimiters +encodePathInfo :: [String] -> [(String, String)] -> String +encodePathInfo pieces qs = + let x = map encodeString `o` -- utf-8 encode the data characters in path components (we have not added any delimiters yet) + map (escapeURIString (\c -> isUnreserved c || c `elem` ":@&=+$,")) `o` -- percent encode the characters + map (\str -> case str of "." -> "%2E" ; ".." -> "%2E%2E" ; _ -> str) `o` -- encode . and .. + intercalate "/" -- add in the delimiters + y = showParams qs + in x pieces ++ y where -- reverse composition o :: (a -> b) -> (b -> c) -> a -> c hunk ./web-routes/Web/Routes/Base.hs 300 where drop1Slash ('/':x) = x drop1Slash x = x + +showParams :: [(String, String)] -> String +showParams [] = "" +showParams z = + '?' : intercalate "&" (map go z) + where + go (x, y) = go' x ++ '=' : go' y + go' = concatMap encodeUrlChar + +-- | Taken straight from web-encodings; reimplemented here to avoid extra +-- dependencies. +encodeUrlChar :: Char -> String +encodeUrlChar c + -- List of unreserved characters per RFC 3986 + -- Gleaned from http://en.wikipedia.org/wiki/Percent-encoding + | 'A' <= c && c <= 'Z' = [c] + | 'a' <= c && c <= 'z' = [c] + | '0' <= c && c <= '9' = [c] +encodeUrlChar c@'-' = [c] +encodeUrlChar c@'_' = [c] +encodeUrlChar c@'.' = [c] +encodeUrlChar c@'~' = [c] +encodeUrlChar ' ' = "+" +encodeUrlChar y = + let (a, c) = fromEnum y `divMod` 16 + b = a `mod` 16 + showHex' x + | x < 10 = toEnum $ x + (fromEnum '0') + | x < 16 = toEnum $ x - 10 + (fromEnum 'A') + | otherwise = error $ "Invalid argument to showHex: " ++ show x + in ['%', showHex' b, showHex' c] hunk ./web-routes/Web/Routes/PathInfo.hs 94 fromPathSegments :: URLParser a toPathInfo :: (PathInfo u) => u -> String -toPathInfo = ('/' :) . encodePathInfo . toPathSegments +toPathInfo = ('/' :) . flip encodePathInfo [] . toPathSegments -- should this fail if not all the input was consumed? -- hunk ./web-routes/Web/Routes/PathInfo.hs 116 dropSlash ('/':rs) = rs dropSlash x = x -mkSitePI :: (PathInfo url) => ((url -> String) -> url -> a) -> Site url a +mkSitePI :: (PathInfo url) => ((url -> [(String, String)] -> String) -> url -> a) -> Site url a mkSitePI handler = Site { handleSite = handler hunk ./web-routes/Web/Routes/PathInfo.hs 119 - , formatPathSegments = toPathSegments + , formatPathSegments = (\x -> (x, [])) . toPathSegments , parsePathSegments = parseSegments fromPathSegments } hunk ./web-routes/Web/Routes/Site.hs 34 Well behaving applications should use this function to generating all internal URLs. -} - handleSite :: (url -> String) -> url -> a + handleSite :: (url -> [(String, String)] -> String) -> url -> a -- | This function must be the inverse of 'parsePathSegments'. hunk ./web-routes/Web/Routes/Site.hs 36 - , formatPathSegments :: url -> [String] + , formatPathSegments :: url -> ([String], [(String, String)]) -- | This function must be the inverse of 'formatPathSegments'. , parsePathSegments :: [String] -> Either String url } hunk ./web-routes/Web/Routes/Site.hs 58 -> String -- ^ path info, leading slash stripped -> (Either String a) runSite approot site pathInfo = - case parsePathSegments site $ decodePathInfo pathInfo of - (Left errs) -> (Left errs) - (Right url) -> Right $ (handleSite site) (\url -> approot ++ (encodePathInfo $ formatPathSegments site url)) url + case parsePathSegments site $ decodePathInfo pathInfo of + (Left errs) -> (Left errs) + (Right url) -> Right $ handleSite site go url + where + go url qs = + let (pieces, qs') = formatPathSegments site url + in approot ++ encodePathInfo pieces (qs ++ qs') hunk ./web-routes/web-routes.cabal 2 Name: web-routes -Version: 0.22.0 +Version: 0.23.0 License: BSD3 Author: jeremy@seereason.com Maintainer: partners@seereason.com } Context: [Add build dependencies on utf8-string David Fox **20100521031923 Ignore-this: 84660a0c019e5c56b23ce94340969631 ] [web-routes-hsp: updated to hsx 0.7.0. Added EmbedAs* instances for Text and lazy Text Jeremy Shaw **20100428185421 Ignore-this: bab67d70abc6c76d39bfc6a1c95b52d ] [web-route-transformers: updated to work with transformers == 0.2.* Jeremy Shaw **20100426173012 Ignore-this: 473b96e97eb5122162bc00d1a35018e4 ] [Fixed bug in fromPathSegments when constructor has multiple arguments Jeremy Shaw **20100413230649 Ignore-this: 63e5c7f44e209836fa29c3e3a2e0fdfc ] [web-routes-wai, WaiExample: update to work with web-routes 0.22 Jeremy Shaw **20100413140113 Ignore-this: f716355ddb499f761cac4a4a957964bc ] [web-routes: bumped to version 0.22.0, tweaked behavior of splitPaths Jeremy Shaw **20100413135702 Ignore-this: 6814116e02ecae302de21dd0cf82e7b8 ] [Replace defaultPage with setDefault michael@snoyman.com**20100411043729 Ignore-this: 9d519d4d568026f94cef7e8567a8a513 ] [Add version bounds for Build-Depends. michael@snoyman.com**20100411043156 Ignore-this: f49069954ad179623f8bbf0d3a22fb6c ] [Haddocks for Web.Route.Site michael@snoyman.com**20100410003933 Ignore-this: 80a3f9b328a31424f757a45a95553dfc ] [Add haddocks for Web.Routes.Base michael@snoyman.com**20100410002841 Ignore-this: df69f5a7c4ad95a09b56776df52a08af ] [splitPaths does not use reverse michael@snoyman.com**20100410000913 Ignore-this: 8c47dcfe948b15fa9a81da83cec06fb0 This does not change behavior at all, and probably will have no noticeable performance impact, but it bothered my OCD ;). ] [HandleT -> Site, Monad -> RouteT. Added mkSitePI Jeremy Shaw **20100330150443 Ignore-this: f30300c7f4d7367c97e1409aaa2f1293 ] [Added Functor (Site url) Jeremy Shaw **20100330031005 Ignore-this: e853f3464fb83d6528fe58574d9fb742 ] [Added MonadReader, MonadState, MonadWriter, MonadCont, MonadRWS, and MonadError instances for RouteT Jeremy Shaw **20100330015246 Ignore-this: 1f48f3cd48ae7e05763b0ac4c0fd91cf ] [added, parseSegments :: URLParser a -> [String] -> Either String a Jeremy Shaw **20100330010121 Ignore-this: ab6f96760375237d6feaeaabfac1cd4a ] [debianized web-routes-mtl Jeremy Shaw **20100329215146 Ignore-this: 3f7a81964ea1d62a4767fed600765902 ] [added PathInfo Integer instance Jeremy Shaw **20100329215116 Ignore-this: c19881372490945c4e15e1c52a6dd5ee ] [added some debianization Jeremy Shaw **20100329203349 Ignore-this: 2280fd8d830e065704dac6fafb34623f ] [added patternParse Jeremy Shaw **20100329180957 Ignore-this: ba090fdd897735868c100d56d29ef3af ] [backported to parsec 2 Jeremy Shaw **20100329174743 Ignore-this: 44caa0d5ae1b2bc1ece4ca14da0e00be ] [change Site to use [String], and make defaultPage a Maybe value. Jeremy Shaw **20100329165700 Ignore-this: 74c55895027cc333e2b686e4708920c8 ] [split web-routes into pieces. Drop pathInfo from Site. Convert from Failing to Either. Jeremy Shaw **20100329000222 Ignore-this: 38ad93e7b0995d3f41931c63d355c0b7 ] [finish conversion to parsec Jeremy Shaw **20100328205223 Ignore-this: d3ca0de3586c8621904369f9a194094b ] [improvements to Parsec based PathInfo parser. disabled TH temporarily until it is updated to parsec Jeremy Shaw **20100328021918 Ignore-this: ce19a91237582ab13b4007ce45ee9a0b ] [merged in partial Consumer -> Parsec conversion Jeremy Shaw **20100326220457 Ignore-this: 32347aa2f6b4e362f2380ea2d72aade5 ] [Parsing URLs using parser combinators chris@eidhof.nl**20100326210028 Ignore-this: 386d31d536e036e01b6a27a538ae7d27 This patch uses Parsec to parse URLs. It simplifies the parser a lot, because we get automatic parser state and error handling capabilities. ] [fromPathInfo will fail if there are left over path segments Jeremy Shaw **20100326163109 Ignore-this: 97e88a1e8797e6df261f79d428aa1efe ] [rename package, urlt -> web-routes, import URLT.* -> Web.Routes.*, URLT -> RouteT Jeremy Shaw **20100326150501 Ignore-this: c7092b87b9dedd9d89c24a973d71697c ] [clean up imports. add some variation on Site handling functions that supports errors Jeremy Shaw **20100326144425 Ignore-this: 8f9831241780d17007e26808afafffd6 ] [urlt: a bunch of improvements and additions to high-level components of library Jeremy Shaw **20100324222819 Ignore-this: b93a1a1002a37b05c4febff083a2af76 ] [Regular: added missing instance for :*: Jeremy Shaw **20100324003108 Ignore-this: de828cfabc96ed11361a3c7e7c69f203 ] [more updates. cabal build works again. Jeremy Shaw **20100324000714 Ignore-this: 220ca155995516e16ce3ee41b01cafc7 ] [update QuickCheck property Jeremy Shaw **20100324000024 Ignore-this: eb69df644e44c2f0c7a1c8a22b8a3235 ] [updated URLT.TH to work with new system Jeremy Shaw **20100323202232 Ignore-this: e67111d4551dec012b5bda5d1653ae56 ] [updated URLT.Regular to latest code base. Jeremy Shaw **20100323195503 Ignore-this: 91b194e4f0714f8945e1e3b00906cace ] [changed fromPathSegments so that it uses the Consumer monad Jeremy Shaw **20100323195414 Ignore-this: 1c08958da5836848fc32815c944a8f27 ] [updated Base, Monad, PathInfo and Wai to use path segments method Jeremy Shaw **20100323193808 Ignore-this: 924b23347406c7191fda420ac10b6690 ] [split AsURL into separate module. added URLT.Parsec. Added more to WaiExample. Jeremy Shaw **20100318205818 Ignore-this: 5130593fcb1bcad140ee2df68729c6ae ] [added URLT/Transformers.hs Jeremy Shaw **20100318181123 Ignore-this: d408243462ed3d44a3c344655bfe3aa3 ] [factored out mtl and transformer specific code. Jeremy Shaw **20100318181056 Ignore-this: 38f3a60e227a88f08f9c7c5ea2576aca ] [added handleWaiD and handleWaiU to WaiExample Jeremy Shaw **20100318180929 Ignore-this: e2f7b62a58a525ef08b45977a9031230 ] [added handleWaiU Jeremy Shaw **20100318180902 Ignore-this: 41b8edc5a69f0ac885593ded18112ba3 ] [added handleWaiD Jeremy Shaw **20100318180837 Ignore-this: 44dc1ccfecca8b124e6f760e95e5d0ef ] [added URLT.Wai, URLT.Dispatch and WaiExample Jeremy Shaw **20100317193028 Ignore-this: 9c997581ead1e83002b394109504ef15 ] [bumped cabal depends to >= 1.6 Jeremy Shaw **20100316213939 Ignore-this: 74f2ef0b87f03f0d7d5280534a6aa5d4 ] [added URLT.Regular Jeremy Shaw **20100316213845 Ignore-this: 58513687243ea53c94dfc0b4153cbe87 ] [removed bogus build-type directive in Library section Jeremy Shaw **20100118011138 Ignore-this: bb4953d235aa98e650fc45d17ccb64de ] [update to QuickCheck 2 Jeremy Shaw **20100104212416 Ignore-this: bf15f8adccb99b53302f5c93f8a2302b ] [Update to QuickCheck 2 Jeremy Shaw **20100104212345 Ignore-this: 78775b4f96682ed162da5ed0c9680ca9 ] [TABS -> spaces in .cabal jeremy@seereason.com**20091231190701 Ignore-this: 8de7f9e74e161104203903d017cbe99e ] [added support for template-haskell >= 2.4.0 jeremy@seereason.com**20091231190019 Ignore-this: c205ee15cbed715de11e1c83971afee0 ] [fixes to .cabal file Jeremy Shaw **20091214221222 Ignore-this: bdf9dd1cf4c8ec25e664bfc88a31a81f ] [updated source and bug location in .cabal Jeremy Shaw **20091130013750 Ignore-this: c58c7af8d2e551dc368def6020f4dff7 ] [Generalize type of implSite Jeremy Shaw **20091116155437 Ignore-this: 3d747224c2ff4f476606e186168de81f ] [ * Turn showURL into a class so that we can call it with out having to use lift when we use additional monad transformers such as XMLGenT Jeremy Shaw **20091010175058 Ignore-this: 87c61d155090fad08f8f825d7361877b ] [0.9: reorganized modules. Added Functor instance for Site. Turn URLT into a newtype. Jeremy Shaw **20090929012059 Ignore-this: 85bce6aaad5365f44d056295ea5dcb1c ] [moved URLT.Happstack into Happstack.Server.URLT Jeremy Shaw **20090831184607] [fix type error Jeremy Shaw **20090815204934] [Updated URLT.HandleT to use Failing instead of Maybe Jeremy Shaw **20090815193923] [fromURL now returns (Success a) instead of a Jeremy Shaw **20090815181430] [Added EmbedAsChild instance for () Jeremy Shaw **20090813223831] [Use debian's hlibrary.mk instead of ours David Fox **20090721030209 Ignore-this: b8af662fda847fb8727a408e922e2f84 ] [Fix a syntax error in the dependency list David Fox **20090721012625 Ignore-this: 407c16be5bca5f28ec4a8012ca0f9819 ] [0.4: implSite now takes the domain as an argument Jeremy Shaw **20090727035134] [bumped to 0.3 Jeremy Shaw **20090719144852] [implSite now has its own guard for the prefix Jeremy Shaw **20090718213102] [added URLT.Happstack and URTL.XMLGenT Jeremy Shaw **20090714191253] [added URLT.HandleT and URLT.QuickCheck Jeremy Shaw **20090710180258] [Fix name of consumer doc package David Fox **20090423171122] [Add -doc and -prof as build dependencies. Clifford Beshers **20090423021332] [Add template haskell to the build dependency list. Clifford Beshers **20090423020704] [Add Consumer to the cabal file. Clifford Beshers **20090423020100] [Add libghc6-consumer-dev as build dependency. Clifford Beshers **20090423015253] [Adding haskell-cdbs to finish previous patch. Clifford Beshers **20090423014009] [Switch to our hlibrary.mk because hscolour isn't found during build. Clifford Beshers **20090423013149] [Debianization, untested. Clifford Beshers **20090422004704] [switch pattern in readM from o to _, this seems like an MLism. Clifford Beshers **20090304211223 Ignore-this: 85d263d4d87eead8ded3c983d9e0f1e2 ] [SimpleSite.hs: updated to use happstack jeremy@n-heptane.com**20090302203432] [added URLTH jeremy@n-heptane.com**20090228013314] [hyper linked each part to the other parts jeremy@n-heptane.com**20080421004840] [commit SimpleSite3.lhs instead of .html jeremy@n-heptane.com**20080326023213] [Added code for part III, but not the text. jeremy@n-heptane.com**20080323054549] [fixed typo jeremy@n-heptane.com**20080322050921] [added second part to tutorial jeremy@n-heptane.com**20080322050201] [tutorial: tweaks to generating .html jeremy@n-heptane.com**20080322005019] [more type signature cleanups, formatting cleans, and start of a tutorial jeremy@n-heptane.com**20080322002223] [type signiture cleanups jeremy@n-heptane.com**20080321002010] [include YourGallery to show that the links generated by each Gallery are unique jeremy@n-heptane.com**20080321001458] [comment out .css link for now jeremy@n-heptane.com**20080321001225] [use State monad instead of Consumer monad, since people probably do not have the Consumer monad package installed jeremy@n-heptane.com**20080320234935] [attempt to generalize handleURL a bit. Make pretty urlShow and urlRead functions jeremy@n-heptane.com**20080320220630] [added HAppS example jeremy@n-heptane.com**20080319044118] [a simple mechanism for type-safe urls jeremy@n-heptane.com**20080319012823] Patch bundle hash: c01a53a650557380560b9ece5e376c7bce6f86d7