4

ハンドラーに対応する現在のルートを取得したいと思います。参考までに、私のサーバーのモックアップを次に示します。

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

[編集]サーバントの古いバージョンの API を見ていたことに気付きましたが、これはもはや有効ではありません。Newrouteには の型シグネチャが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です。ルートの訪問回数をデータベースに追加するのは、単なる例です。訪問数をカウントするより良い方法などには興味がありません。

4

3 に答える 3

2

これを自動的に行う方法はわかりませんが、safeLink関数を使用して「手動で」行うことができます。

アイデアは、API がある場合、

type ServerAPI = 
        "route01" :> Get '[HTML] Text
   :<|> "route02" :> "subroute" :> Get '[HTML] Text
   :<|> Route3

type Route3 = "route03" :> Get '[HTML] Text

safeLinkAPI 全体を使用してプロキシに渡し、特定のルートを使用してプロキシに渡し、結果を表示できURIます。

show (safeLink (Proxy::Proxy ServerAPI) (Proxy::Proxy Route3))

ルートにパラメーターがある場合は、ハンドラーが取得したパラメーターも渡す必要があります。例えば:

type ServerAPI =
       ...
   :<|> Route4

type Route4 = "route04" :> Capture "cap" Int :> Get '[JSON] Text

ghciで:

ghci> :set -XKindSignatures -XDataKinds -XTypeOperators -XTypeFamilies
ghci> :type safeLink (Proxy::Proxy ServerAPI) (Proxy::Proxy Route4)
Int -> URI

ルートごとにこれを行う必要があります。

于 2017-01-10T10:02:22.047 に答える
0

ハンドラーに「ルート」パラメーターを追加すると、サーバーのハンドラーを組み合わせるときに関数アプリケーションを介してパラメーター値を設定できます。

あなたの例に基づいて:

type ServerAPI = 
         "route01" :> Get '[JSON] Text
    :<|> "route02" :> "subroute" :> Get '[JSON] Text
    :<|> "route03" :> Get '[JSON] Text

route1and2Handler :: String -> Handler Text
route1and2Handler route = do
    -- addVisitCountForRouteToDatabaseOrSomethingOfThatSort...
    return (pack route)

route3Handler :: Handler Text
route3Handler = return "Hello, I'm route 03"

server :: Server ServerAPI
server = route1and2Handler "route01" :<|> route1and2Handler "route02" :<|> route3Handler

あるいは、本当に関心があるのがすべてのルートに対する一般的なリクエスト処理である場合は、サーバーとアプリケーションの間に「ミドルウェア」を適用することにより、おそらくより適切に実現できます。ミドルウェア (通常は type Application -> Application) はリクエストにアクセスできます。wai ミドルウェアの例については、wai-extraを参照してください。

すべてのリクエストのロギングを実行する例:

import Network.Wai.Middleware.RequestLogger (logStdoutDev)

...

app :: Application
app = serve serverAPI server

main :: IO ()
main = run 8081 $ logStdoutDev app
于 2019-02-23T22:54:57.760 に答える