- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
Get '[HTML] Text : "-6ren">
我想获取与我的处理程序相对应的当前路由。这是我的服务器的样机,仅供参考:
type ServerAPI =
"route01" :> Get '[HTML] Text
:<|> "route02" :> "subroute" :> Get '[HTML] Text
:<|> "route03" :> Get '[HTML] Text
route1and2Handler :: Handler Text
route1and2Handler = do
route <- getCurrentRoute
addVisitCountForRouteToDatabaseOrSomethingOfThatSort...
return template
route3Handler :: Handler Text
route3Handler = return "Hello, I'm route 03"
server :: Server ServerAPI
server = route1and2Handler :<|> route1and2Handler :<|> route3Handler
route1and2Handler
应该具有某种获取当前路线的方法。我试图通过实现
HasServer
实例将请求对象放入处理程序并从中提取url,如下所示:
data FullRequest
instance HasServer a => HasServer (FullRequest :> a) where
type Server (FullRequest :> a) = Request -> Server a
route Proxy subserver request respond =
route (Proxy :: Proxy a) (subserver request) request respond
route
具有
route :: Proxy api -> Context context -> Delayed env (Server api) -> Router env
的类型签名,我真的不知道从这里获取
Request
的方法。
route1and2Handler
类型签名设置为
Request -> Handler Text
,但是在尝试创建
HasServer
实例时出现此错误:
`Server' is not a (visible) associated type of class `HasServer'
Handler
中获取当前路线,在数据库中添加路线的访问计数只是出于示例目的。我对统计访问次数或类似次数的更好方式不感兴趣。
最佳答案
一个有两个问题:
如何获得当前的请求或URL?
如何获得当前的“路线”?
请注意,URL(例如/route12/42
)与路由不同
(例如`“” route12“:>捕获” id“ Int:>获取'[JSON] Int)。
让我们看看如何在解决了这两个问题之后
简短的语言说明和导入部分。
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE UndecidableSuperClasses #-}
{-# OPTIONS_GHC -Wno-orphans #-}
module Main where
import Data.Maybe (fromMaybe)
import Control.Monad.IO.Class (liftIO)
import System.Environment (getArgs)
import GHC.Generics (to, from, M1 (..), K1 (..), (:*:) (..))
-- for "unsafe" vault key creation
import System.IO.Unsafe (unsafePerformIO)
import qualified Data.ByteString.Char8 as BS8
import qualified Data.Vault.Lazy as V
import qualified Network.Wai as Wai
import qualified Network.Wai.Handler.Warp as Warp
import Servant
import Servant.API.Generic
import Servant.Server.Generic
import Servant.Server.Internal.RoutingApplication (passToServer)
Request
对象或URL
WAI
Request
传递给处理程序实际上很容易。
requestBody
)。
wai
服务器实现联系起来,
servant-server
外,
wai
中的其他所有元素都不会公开
Raw
内部)。
Server (Wai.Request :> api) = Wai.Request -> Server api
。
Servant.API.Generic
进行编写(请参见“使用泛型”食谱):
data Routes1 route = Routes1
{ route11 :: route :- Wai.Request :> "route1" :> Get '[JSON] Int
, route12 :: route :- Wai.Request :> "route2" :> Capture "id" Int :> Get '[JSON] Int
}
deriving (Generic)
routes1 :: Routes1 AsServer
routes1 = Routes1
{ route11 = \req -> liftIO $ do
let p = Wai.rawPathInfo req
BS8.putStrLn p
return (BS8.length p)
, route12 = \req i -> liftIO $ do
let p = Wai.rawPathInfo req
BS8.putStrLn p
return (succ i)
}
app1 :: Application
app1 = genericServe routes1
Routes1
数据类型,实现
Routes1 AsServer
值并将其打开
wai
的
Application
。但是,要编译此示例,我们需要
passToServer
组合器
route
的实现。
instance HasServer api ctx => HasServer (Wai.Request :> api) ctx where
type ServerT (Wai.Request :> api) m = Wai.Request -> ServerT api m
hoistServerWithContext _ pc nt s =
hoistServerWithContext (Proxy :: Proxy api) pc nt . s
route _ ctx d = route (Proxy :: Proxy api) ctx $
passToServer d id
Wai.rawPathInto req
调用。
servant
的设计原则之一。
data RawPathInfo
instance HasServer api ctx => HasServer (RawPathInfo :> api) ctx where
type ServerT (RawPathInfo :> api) m = BS8.ByteString -> ServerT api m
hoistServerWithContext _ pc nt s =
hoistServerWithContext (Proxy :: Proxy api) pc nt . s
route _ ctx d = route (Proxy :: Proxy api) ctx $
passToServer d Wai.rawPathInfo
RawPathInfo
组合器,我们可以重新实现我们的应用程序:
data Routes2 route = Routes2
{ route21 :: route :- RawPathInfo :> "route1" :> Get '[JSON] Int
, route22 :: route :- RawPathInfo :> "route2" :> Capture "id" Int :> Get '[JSON] Int
}
deriving (Generic)
routes2 :: Routes2 AsServer
routes2 = Routes2
{ route21 = \p -> liftIO $ do
BS8.putStrLn p
return (BS8.length p)
, route22 = \p i -> liftIO $ do
BS8.putStrLn p
return (succ i)
}
app2 :: Application
app2 = genericServe routes2
rawPathInfo
选择器从处理程序移至组合器实现,
Vault
vault
wai
中的
Request
值不是众所周知的或未使用的。
Request
的“动态”鸿沟:我们可以将任意数据附加到请求,
servant-server
基于
wai
,因此使用库是第三个答案
rpiKey :: V.Key BS8.ByteString
rpiKey = unsafePerformIO V.newKey
rawPathInfo
放入
vault
的中间件。
middleware :: Wai.Middleware
middleware app req respond = do
let vault' = V.insert rpiKey (Wai.rawPathInfo req) (Wai.vault req)
req' = req { Wai.vault = vault' }
app req' respond
data Routes3 route = Routes3
{ route31 :: route :- Vault :> "route1" :> Get '[JSON] Int
, route32 :: route :- Vault :> "route2" :> Capture "id" Int :> Get '[JSON] Int
}
deriving (Generic)
routes3 :: Routes3 AsServer
routes3 = Routes3
{ route31 = \v -> liftIO $ do
let p = fromMaybe "?" $ V.lookup rpiKey v
BS8.putStrLn p
return (BS8.length p)
, route32 = \v i -> liftIO $ do
let p = fromMaybe "?" $ V.lookup rpiKey v
BS8.putStrLn p
return (succ i)
}
app3 :: Application
app3 = middleware $ genericServe routes3
vault
可用于将信息从中间件传递到处理程序
route2/:id
吗?
fix
组合器。
Servant.API.Generics
我们也可以减少样板。
Routes4
数据结构开始。
data Routes4 route = Routes4
{ route41 :: route :- "route1" :> Get '[JSON] Int
, route42 :: route :- "route2" :> Capture "id" Int :> Get '[JSON] Int
}
deriving (Generic)
Routes4 AsServer
值。
AsRecServer route
是一个以
route :- api
为首的处理程序
HasLink'
,但读者可以自由使用其他
servant-client
做代理!
data AsRecServer route
instance GenericMode (AsRecServer route) where
type AsRecServer route :- api = (route :- api) -> (AsServer :- api)
routes4 :: Routes4 (AsRecServer (AsLink Link))
routes4 = Routes4
{ route41 = \l -> liftIO $ do
print l
return 42
, route42 = \l i -> liftIO $ do
print (l i)
return i
}
app4 :: Application
app4 = genericRecServe routes4
genericRecServe
的实现令人生畏。
genericHoist
。
modeA :- api
的
modeB :- api
转换为
api
的函数,
genericHoist
将
routes modeA
转换为
routes modeB
。
Servant.API.Generic
中?
genericHoist
:: ( GenericMode modeA, GenericMode modeB
, Generic (routes modeA), Generic (routes modeB)
, GServantHoist c api modeA modeB (Rep (routes modeA)) (Rep (routes modeB))
)
=> Proxy modeA -> Proxy modeB -> Proxy c -> Proxy api
-> (forall api'. c api' => Proxy api' -> (modeA :- api') -> (modeB :- api'))
-> routes modeA -> routes modeB
genericHoist pa pb pc api nt = to . gservantHoist pa pb pc api nt . from
genericRecServe
由
genericHoist
组成,带有
genericServe
的变体。
genericRecServe
:: forall routes.
( HasServer (ToServantApi routes) '[]
, GenericServant routes AsApi
, GenericServant routes AsServer
, GenericServant routes (AsRecServer (AsLink Link))
, Server (ToServantApi routes) ~ ToServant routes AsServer
, GServantHoist
HasLink'
(ToServantApi routes)
(AsRecServer (AsLink Link))
AsServer
(Rep (routes (AsRecServer (AsLink Link))))
(Rep (routes AsServer))
)
=> routes (AsRecServer (AsLink Link)) -> Application
genericRecServe
= serve (Proxy :: Proxy (ToServantApi routes))
. toServant
. genericHoist
(Proxy :: Proxy (AsRecServer (AsLink Link)))
(Proxy :: Proxy AsServer)
(Proxy :: Proxy HasLink')
(genericApi (Proxy :: Proxy routes))
(\p f -> f $ safeLink p p)
HasLink
。
class (IsElem api api, HasLink api) => HasLink' api
instance (IsElem api api, HasLink api) => HasLink' api
genericHoist
的工作马是
gservantHoist
Rep
上。
c
和
api
参数是类参数。
class GServantHoist c api modeA modeB f g where
gservantHoist
:: Proxy modeA -> Proxy modeB -> Proxy c -> Proxy api
-> (forall api'. c api' => Proxy api' -> (modeA :- api') -> (modeB :- api'))
-> f x -> g x
M1
(元数据)和
:*:
(产品)的实例很简单
instance
GServantHoist c api modeA modeB f g
=>
GServantHoist c api modeA modeB (M1 i j f) (M1 i' j' g)
where
gservantHoist pa pb pc api nt
= M1
. gservantHoist pa pb pc api nt
. unM1
instance
( GServantHoist c apiA modeA modeB f f'
, GServantHoist c apiB modeA modeB g g'
) =>
GServantHoist c (apiA :<|> apiB) modeA modeB (f :*: g) (f' :*: g')
where
gservantHoist pa pb pc _ nt (f :*: g) =
gservantHoist pa pb pc (Proxy :: Proxy apiA) nt f
:*:
gservantHoist pa pb pc (Proxy :: Proxy apiB) nt g
K1
的实现显示了为什么我们需要
c
和
api
c api
和“连贯”条件,
api
,
modeA
,
modeB
,
x
和
y
匹配。
instance
( c api, (modeA :- api) ~ x, (modeB :- api) ~ y )
=> GServantHoist c api modeA modeB (K1 i x) (K1 i y)
where
gservantHoist _pa _pb _pc api nt
= K1
. nt api
. unK1
Generic
方法,我们可以对处理程序进行各种转换。
servant
“ middleware”中,这将
vault
,并且该信息可能被
wai
使用
Middleware
收集统计信息。这样我们可以制作一个改进的版本
servant-ekg
,因为当前
servant-ekg
可能会被重叠的路线弄糊涂。
main :: IO ()
main = do
args <- getArgs
case args of
("run1":_) -> run app1
("run2":_) -> run app2
("run3":_) -> run app3
("run4":_) -> run app4
_ -> putStrLn "To run, pass 'run1' argument: cabal new-run cookbook-generic run"
where
run app = do
putStrLn "Starting cookbook-current-route at http://localhost:8000"
Warp.run 8000 app
关于haskell - Haskell Servant从处理程序获取当前路由/URL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41538438/
我试图通过这段代码读取未知数量的整数: while (1) { int c = getchar (); if (c == EOF) break;
我正试图找到一个类似于谷歌分析日期选择器的日期选择器: 知道 jQuery 是否提供了类似的东西吗? 最佳答案 这个 Twitter Bootstrap 风格的日期范围选择器非常接近。 https:/
我正在使用 javascript。如何获取当前 URL 的路径并将其分配给我的代码?这是我的代码: $(document).ready(function() { $(".share").hides
如何获得今天的Julian day number (JDN)相等的?或任何日期? 我看了又看,但只发现了一些产生“year-dayOfYear”的函数,而不是:2457854。 最佳答案 在 bash
我有相当简单的 UDP 服务器写在 c 上。 有时我需要知道在套接字中排队的所有 udp 数据包(字节)的当前长度。 据我了解,getsockopt 没有得到这样的信息。 欢迎使用 Linux 和 F
我一直在寻找几个小时来找到一个可以在图像中添加诸如“填充:5px”之类的东西的插件。每个人都通过纯 html 做到这一点吗?我们的客户需要一种方法来简单地使用按钮或右键单击上下文菜单来添加它。有什么建
是否有可能获得当前正在执行的 TCL 脚本的完整路径? 在 PHP 中,它将是:__FILE__ 最佳答案 根据“当前正在执行的 TCL 脚本”的含义,您实际上可能会寻找 info script ,甚
我最近从直接使用 ISession 转向了包装的 ISession,即工作单元类型模式。 我曾经使用 SQL Lite(内存中)对此进行测试。我有一个简单的帮助器类,它配置我的 SessionFact
我按照步骤操作 here在 WebStorm 中配置代码完成和其他内容,但我仍然收到以下语法错误。 我该如何解决这个问题? 最佳答案 通过相应地将“JavaScript 语言版本”(Settings/
我可以为我团队的 TFS 当前 Sprint 任务板添加书签吗?我们有两周的冲刺,因此 URL 每两周更改一次。 默认 URL 的形式为: http://[Server]/tfs/[Project]/
是否有 Subversion 命令可以显示当前版本号? 在svn checkout之后,我想启动一个脚本并需要变量中的修订号。如果有像 svn info get_revision_number 这样的
我正在编写表单的一个组件 首次安装组件时,sources={{}} ,一本空字典。由于该组件包装了现有的 Javascript 库,因此我正在实现一个自定义比较函数。为了让这个 diffing 函数
无论系统时间设置为多少以及机器所在的时区,我都需要正确的 UTC 时间。 (即使我必须打电话到互联网才能同步......) 是否有一些库或其他方法可以优雅地做到这一点? 最佳答案 如果您想获得准确可靠
我一边编码,一边拿出一些我和 friend 建立的旧网站来重新开始工作。我已经有一段时间没有做过任何 AJAX 了,当我试图找出我的代码失败的地方时,我发现没有显示很多资源。我猜这是因为我使用的是旧方
由于对性能的巨大影响,我从不怀疑我现在的桌面CPU是否有分支预测。当然可以。但各种 ARM 产品又如何呢? iPhone或Android手机有分支预测吗?较旧的任天堂 DS?基于 PowerPC 的
我有一个具有以下有效负载的 JWT: { "id": "394a71988caa6cc30601e43f5b6569d52cd7f6df", "jti": "394a71988caa6cc30
从其他一些帖子中,我能够通过以下方式获取当前 URI: 但是以下方法不起作用: 我很好奇为什么上面的方法不起作用,以及如何将当前 URI 分配给字符串。 最佳答案 每the javadocs ,g
我在表格 View 中有几个单元格。现在在任何给定的时间点,我想计算 View 中单元格的当前高度,即如果它是 View 的 3/4,它应该返回 (cellheight)*3/4 高度。 我通过以下方
这是网站的身份验证脚本。这安全吗?是最近的节目吗?它已经过时了吗?是否有“更好更安全的方法”我很新,但我没有看到太多地方使用 header 授权。 如有任何帮助,我们将不胜感激!这是我制作的第一个登录
我已经在其他 stackoverflow 线程上检查过这个错误,但在我的代码中没有发现任何错误。也许我累了,但我觉得还好。 网站.urls.py: from django.conf.urls impo
我是一名优秀的程序员,十分优秀!