使用 reflex-dom 客户端访问 servant 服务器
Acess a servant server with a reflex-dom client
我正在使用 0.4 版的 reflex-dom 并且我有一个小型 reflex-dom 客户端:
{-# LANGUAGE OverloadedStrings #-}
import Reflex.Dom
import qualified Data.Text as T
import Data.Monoid
main :: IO ()
main = mainWidget body
body :: MonadWidget t m => m ()
body = el "div" $ do
pb <- getPostBuild
snd <- button "Send"
-- Use one of the following URL's:
let defReq = "http://localhost:8080/name/3"
-- let defReq = "https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY"
let req = XhrRequest "GET" defReq (def {_xhrRequestConfig_sendData = defReq} )
let evReq = tagPromptlyDyn (constDyn req) snd
evRsp <- performRequestAsync evReq
let evResult = (result . _xhrResponse_responseText) <$> evRsp
el "p" $ return ()
dynText =<< holdDyn "NOPE" evResult
return ()
result :: Show a => Maybe a -> T.Text
result (Just x) = "Received: " <> T.pack (show x)
result Nothing = "Response is Nothing"
如 中所述,我使用的是 _xhrResponse_responseText 而不是 decodeXhrResponse。
当我 运行 这个客户端使用 NASA URL 时,它会显示一个漂亮的 JSON 字符串。因此我假设,这个 reflex-dom 客户端正在工作。
我也有一个小型仆人服务器:
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
import Servant
import Servant.API
import Servant.Server
import Network.Wai
import Network.Wai.Handler.Warp
import Network.Wai.Logger (withStdoutLogger)
import qualified Data.Text as T
main :: IO ()
main = withStdoutLogger $ \aplogger -> do
let settings = setPort 8080 $ setLogger aplogger defaultSettings
runSettings settings app
app :: Application
app = serve userAPI server
userAPI :: Proxy API -- API usage: http://localhost:8080/name/2
userAPI = Proxy
type API = "name" :> Capture "pid" Int :> Get '[PlainText] T.Text
server :: Server API
server = name
name :: Monad m => Int -> m T.Text
name pid = return $ nameById pid
nameById :: Int -> T.Text
nameById 1 = "Isaac Newton"
nameById 2 = "Galileo Galilei"
nameById 3 = "Marie Curie"
nameById _ = "UNKNOWN!!"
当我在浏览器中使用 http://localhost:8080/name/3
或 curl
访问此服务器时,我看到了预期的结果 Marie Curie
。因此我假设,这个仆人服务器正在工作。
当我 运行 上面的 reflex-dom 客户端与本地主机的 URL 时,我可以在服务器的标准输出日志中看到请求,但是客户端没有不 显示 居里夫人 的名字。相反,客户端只显示一个空字符串!
所以作为一个团队,客户端和服务器不一起工作!为什么?
您可能遇到了 Cross-Origin 资源共享 (CORS) 问题。您可以通过检查您的浏览器控制台是否出现如下所示的错误来验证这一点(至少在 chrome 中):
XMLHttpRequest cannot load http://localhost:8080/name/3. No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:8000' is therefore not allowed
access.
如果是这种情况,您可以通过替换此行在您的服务器中启用 CORS:
app = serve userAPI server
这一行:
app = simpleCors (serve userAPI server)
您需要导入 wai-cors:
import Network.Wai.Middleware.Cors
这是您的仆人服务器,进行了这些更改:
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
import Servant
import Servant.API
import Servant.Server
import Network.Wai
import Network.Wai.Handler.Warp
import Network.Wai.Logger (withStdoutLogger)
import Network.Wai.Middleware.Cors
import qualified Data.Text as T
main :: IO ()
main = withStdoutLogger $ \aplogger -> do
let settings = setPort 8080 $ setLogger aplogger defaultSettings
runSettings settings app
app :: Application
app = simpleCors (serve userAPI server)
userAPI :: Proxy API -- API usage: http://localhost:8080/name/2
userAPI = Proxy
type API = "name" :> Capture "pid" Int :> Get '[PlainText] T.Text
server :: Server API
server = name
name :: Monad m => Int -> m T.Text
name pid = return $ nameById pid
nameById :: Int -> T.Text
nameById 1 = "Isaac Newton"
nameById 2 = "Galileo Galilei"
nameById 3 = "Marie Curie"
nameById _ = "UNKNOWN!!"
我正在使用 0.4 版的 reflex-dom 并且我有一个小型 reflex-dom 客户端:
{-# LANGUAGE OverloadedStrings #-}
import Reflex.Dom
import qualified Data.Text as T
import Data.Monoid
main :: IO ()
main = mainWidget body
body :: MonadWidget t m => m ()
body = el "div" $ do
pb <- getPostBuild
snd <- button "Send"
-- Use one of the following URL's:
let defReq = "http://localhost:8080/name/3"
-- let defReq = "https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY"
let req = XhrRequest "GET" defReq (def {_xhrRequestConfig_sendData = defReq} )
let evReq = tagPromptlyDyn (constDyn req) snd
evRsp <- performRequestAsync evReq
let evResult = (result . _xhrResponse_responseText) <$> evRsp
el "p" $ return ()
dynText =<< holdDyn "NOPE" evResult
return ()
result :: Show a => Maybe a -> T.Text
result (Just x) = "Received: " <> T.pack (show x)
result Nothing = "Response is Nothing"
如
当我 运行 这个客户端使用 NASA URL 时,它会显示一个漂亮的 JSON 字符串。因此我假设,这个 reflex-dom 客户端正在工作。
我也有一个小型仆人服务器:
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
import Servant
import Servant.API
import Servant.Server
import Network.Wai
import Network.Wai.Handler.Warp
import Network.Wai.Logger (withStdoutLogger)
import qualified Data.Text as T
main :: IO ()
main = withStdoutLogger $ \aplogger -> do
let settings = setPort 8080 $ setLogger aplogger defaultSettings
runSettings settings app
app :: Application
app = serve userAPI server
userAPI :: Proxy API -- API usage: http://localhost:8080/name/2
userAPI = Proxy
type API = "name" :> Capture "pid" Int :> Get '[PlainText] T.Text
server :: Server API
server = name
name :: Monad m => Int -> m T.Text
name pid = return $ nameById pid
nameById :: Int -> T.Text
nameById 1 = "Isaac Newton"
nameById 2 = "Galileo Galilei"
nameById 3 = "Marie Curie"
nameById _ = "UNKNOWN!!"
当我在浏览器中使用 http://localhost:8080/name/3
或 curl
访问此服务器时,我看到了预期的结果 Marie Curie
。因此我假设,这个仆人服务器正在工作。
当我 运行 上面的 reflex-dom 客户端与本地主机的 URL 时,我可以在服务器的标准输出日志中看到请求,但是客户端没有不 显示 居里夫人 的名字。相反,客户端只显示一个空字符串! 所以作为一个团队,客户端和服务器不一起工作!为什么?
您可能遇到了 Cross-Origin 资源共享 (CORS) 问题。您可以通过检查您的浏览器控制台是否出现如下所示的错误来验证这一点(至少在 chrome 中):
XMLHttpRequest cannot load http://localhost:8080/name/3. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8000' is therefore not allowed access.
如果是这种情况,您可以通过替换此行在您的服务器中启用 CORS:
app = serve userAPI server
这一行:
app = simpleCors (serve userAPI server)
您需要导入 wai-cors:
import Network.Wai.Middleware.Cors
这是您的仆人服务器,进行了这些更改:
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
import Servant
import Servant.API
import Servant.Server
import Network.Wai
import Network.Wai.Handler.Warp
import Network.Wai.Logger (withStdoutLogger)
import Network.Wai.Middleware.Cors
import qualified Data.Text as T
main :: IO ()
main = withStdoutLogger $ \aplogger -> do
let settings = setPort 8080 $ setLogger aplogger defaultSettings
runSettings settings app
app :: Application
app = simpleCors (serve userAPI server)
userAPI :: Proxy API -- API usage: http://localhost:8080/name/2
userAPI = Proxy
type API = "name" :> Capture "pid" Int :> Get '[PlainText] T.Text
server :: Server API
server = name
name :: Monad m => Int -> m T.Text
name pid = return $ nameById pid
nameById :: Int -> T.Text
nameById 1 = "Isaac Newton"
nameById 2 = "Galileo Galilei"
nameById 3 = "Marie Curie"
nameById _ = "UNKNOWN!!"