나는 Happstack, Heist 및 web-routes를 사용하여 응용 프로그램 서버를 작성하려고하지만 splices가 시작하지 않은 값에 액세스하는 방법을 알아내는 데 어려움이 있습니다. 내 응용 프로그램의 모나드 스택. 웹 루트를 통해 URL 경로에서 추출Heist 템플릿이있는 응용 프로그램 모나드에서 가져온 값을 사용하지 마십시오.
- 매개 변수 :
이가 오는 두 가지 상황이 있습니다. 이는 적절한 처리기로 요청을 라우팅 할 때 형식 안전 URL에서 패턴 일치를 통해 발생합니다.
- 세션 정보. 요청이 새로운 세션에 대한 요청 인 경우 요청에있는 쿠키에서 세션 식별자를 읽을 수 없으며 (그러한 쿠키가 아직 존재하지 않으므로) 필요에 따라 스플 라이스를 사용하여 새 세션을 만들 수 없습니다. 이후 하나 이상의 스플 라이스가 그것을 시도하면, 나는 하나의 요청에 대해 여러 개의 새로운 세션을 만들어야 만한다. 그러나 웹 경로 항목을 입력하기 전에 세션을 만들면 세션은 응용 프로그램 모나드 외부에 존재합니다./가
- /계승/N가 N
- 의 계승 출력/STR 출력을 STR 역방향 :
은 다음의 URL을 제공하려고 다음 샘플 프로그램을 고려 거꾸로
매개 변수가 쿼리 문자열 대신 URL 경로에 나타나므로 매개 변수는 ServerPartT 모나드에서 오는 대신 웹 경로를 통해 추출됩니다. 거기에서, 비록 그들이 응용 프로그램 모나드에만 접근 할 수 있기 때문에 splice가 그것을 볼 수있는 어딘가에 매개 변수를 놓을 분명한 방법이 없습니다.
모나드 스택에 어딘가에 ReaderT을 고집의 확실한 해결책은 두 가지 문제가 있습니다
- ReaderT이 ServerMonad, FilterMonad를 구현하지 않기 때문에 ServerPartT는 모나드 스택의 Happstack 부분을 숨 깁니다 위에 ReaderT을 갖는,
- 내가 제공하는 모든 페이지가 동일한 유형의 매개 변수를 사용한다고 가정하지만이 예제에서/factorial은 Int를 원하지만/reverse는 String을 원합니다. 그러나 두 페이지 핸들러가 동일한 TemplateDirectory를 사용하려면 ReaderT에 동일한 유형의 값이 있어야합니다.
Snap 설명서를 살펴본 후 URL 경로의 Snap handles 매개 변수가 효과적으로 쿼리 문자열에 복사되어 문제를 회피하는 것처럼 보입니다. 그러나 그것은 Happstack과 웹 라우트의 옵션이 아니며, URL이 동일한 값을 지정하는 두 가지 다른 방법을 사용하면 보안 상 나쁜 아이디어라는 것을 알게됩니다.
비 응용 프로그램 모나드 요청 데이터를 스플 라이스에 노출시키는 "적절한"방법이 있습니까, 아니면 Heist를 포기하고 문제가 아닌 Blaze-HTML과 같은 것을 사용해야합니까? 나는 명백한 것을 놓치고있는 것처럼 느껴지지만 그것이 무엇인지 알 수는 없다.
예제 코드 :
{-# LANGUAGE TemplateHaskell #-}
import Prelude hiding ((.))
import Control.Category ((.))
import Happstack.Server (Response, ServerPartT, nullConf, ok, simpleHTTP)
import Happstack.Server.Heist (render)
import Text.Boomerang.TH (derivePrinterParsers)
import Text.Templating.Heist (Splice, bindSplices, emptyTemplateState, getParamNode)
import Text.Templating.Heist.TemplateDirectory (TemplateDirectory, newTemplateDirectory')
import Web.Routes (RouteT, Site, runRouteT)
import Web.Routes.Boomerang (Router, anyString, boomerangSite, int, lit, (<>), (</>))
import Web.Routes.Happstack (implSite)
import qualified Data.ByteString.Char8 as C
import qualified Data.Text as T
import qualified Text.XmlHtml as X
data Sitemap = Factorial Int
| Reverse String
$(derivePrinterParsers ''Sitemap)
-- Conversion between type-safe URLs and URL strings.
sitemap :: Router Sitemap
sitemap = rFactorial . (lit "factorial" </> int)
<> rReverse . (lit "reverse" </> anyString)
-- Serve a page for each type-safe URL.
route :: TemplateDirectory (RouteT Sitemap (ServerPartT IO)) -> Sitemap -> RouteT Sitemap (ServerPartT IO) Response
route templates url = case url of
Factorial _num -> render templates (C.pack "factorial") >>= ok
Reverse _str -> render templates (C.pack "reverse") >>= ok
site :: TemplateDirectory (RouteT Sitemap (ServerPartT IO)) -> Site Sitemap (ServerPartT IO Response)
site templates = boomerangSite (runRouteT $ route templates) sitemap
-- <factorial>n</factorial> --> n!
factorialSplice :: (Monad m) => Splice m
factorialSplice = do input <- getParamNode
let n = read . T.unpack $ X.nodeText input :: Int
return [X.TextNode . T.pack . show $ product [1 .. n]]
-- <reverse>text</reverse> --> reversed text
reverseSplice :: (Monad m) => Splice m
reverseSplice = do input <- getParamNode
return [X.TextNode . T.reverse $ X.nodeText input]
main :: IO()
main = do templates <- newTemplateDirectory' path . bindSplices splices $ emptyTemplateState path
simpleHTTP nullConf $ implSite "http://localhost:8000" "" $ site templates
where splices = [(T.pack "factorial", factorialSplice), (T.pack "reverse", reverseSplice)]
path = "."
계승.TPL :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>Factorial</title>
</head>
<body>
<p>The factorial of 6 is <factorial>6</factorial>.</p>
<p>The factorial of ??? is ???.</p>
</body>
</html>
reverse.tpl :에 사용
func :: a -> m b
하스켈 순수 강한 정적 타입 시스템을 가지고 있기 때문에, 데이터 :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>Reverse</title>
</head>
<body>
<p>The reverse of "<tt>hello world</tt>" is "<tt><reverse>hello world</reverse></tt>".</p>
<p>The reverse of "<tt>???</tt>" is "<tt>???</tt>".</p>
</body>
</html>
나는 여기에 스냅'rendWithSplices '에 대한 정의 happstack 변화를 사용했습니다 '함수가있는 경우'App TemplateState '. –