Tôi đang cố gắng viết một máy chủ ứng dụng bằng cách sử dụng Happstack, Heist và web-routes, nhưng gặp khó khăn trong việc tìm ra cách để cho các giá trị truy cập không bắt nguồn từ chồng đơn lẻ của ứng dụng của tôi.Sử dụng các giá trị không phải từ mẫu đơn ứng dụng với các mẫu Heist
Có hai tình huống nơi này đi lên:
- thông số chiết xuất từ đường dẫn URL qua web tìm đường khác. Chúng xuất phát từ mẫu khớp với URL an toàn loại khi định tuyến yêu cầu đến trình xử lý thích hợp.
- Thông tin phiên. Nếu yêu cầu là phiên mới, tôi không thể đọc số nhận dạng phiên từ cookie trong yêu cầu (vì không có cookie như vậy) và tôi không thể sử dụng các kết nối để tạo phiên mới nếu cần, kể từ đó nếu nhiều hơn một mối nối cố gắng làm điều đó, tôi sẽ tạo ra nhiều phiên mới cho một yêu cầu duy nhất. Nhưng nếu tôi tạo phiên trước khi nhập nội dung trên web, phiên tồn tại bên ngoài đơn đăng ký.
Hãy xem xét các chương trình mẫu sau mà cố gắng để phục vụ các URL sau:
- /thừa/n kết quả đầu ra giai thừa của n
- /ngược/str đầu ra str backwards
Vì tham số xuất hiện trong đường dẫn URL thay vì chuỗi truy vấn, nó được trích xuất qua các tuyến đường web thay vì đến từ đơn nguyên ServerPartT. Mặc dù vậy, từ đó, không có cách nào rõ ràng để đặt tham số ở đâu đó mà các liên kết có thể nhìn thấy nó, vì chúng chỉ có quyền truy cập vào đơn ứng dụng.
Các giải pháp rõ ràng gắn bó một ReaderT ở đâu đó trên đơn nguyên stack có hai vấn đề:
- Có ReaderT trên ServerPartT ẩn những phần Happstack của đơn nguyên đống, vì ReaderT không thực hiện ServerMonad, FilterMonad, v.v.
- Giả định rằng tất cả các trang tôi đang phân phát đều có cùng loại tham số, nhưng trong ví dụ này,/giai thừa muốn Int nhưng ngược lại muốn có Chuỗi. Nhưng đối với cả hai trình xử lý trang để sử dụng cùng một TemplateDirectory, ReaderT sẽ cần phải mang theo một giá trị cùng loại.
Nhìn trộm tài liệu Snap, có vẻ như Snap các tham số xử lý trong đường dẫn URL bằng cách sao chép chúng hiệu quả vào chuỗi truy vấn, điều này sẽ tránh được vấn đề. Nhưng đó không phải là một tùy chọn với Happstack và các tuyến đường web, và bên cạnh đó, có hai cách khác nhau để một URL chỉ định cùng một giá trị đánh tôi như một ý tưởng tồi về bảo mật. Vì vậy, có cách "thích hợp" để hiển thị dữ liệu yêu cầu không áp dụng đơn lẻ cho các mối nối hay tôi cần phải từ bỏ Heist và sử dụng thứ gì đó như Blaze-HTML thay vì đây không phải là vấn đề? Tôi cảm thấy như tôi đang thiếu một cái gì đó hiển nhiên, nhưng không thể tìm ra nó có thể là gì.
Ví dụ mã:
{-# 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 = "."
thừa.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:
<!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>
Tôi đã sử dụng biến thể tùy chỉnh happstack trên snap 'rendWithSplices' ở đây: https://github.com/aslatter/blog/blob/master/Blog/Templates.hs Trong ví dụ này, 'appTemplates 'chức năng nếu loại' App TemplateState '. –