2016-02-08 2 views
5

में प्रतिक्रिया शीर्षलेख जोड़ना मैं Servant में CORS प्रतिक्रिया शीर्षलेख जोड़ने के तरीके को समझने की कोशिश कर रहा हूं (मूल रूप से, एक प्रतिक्रिया शीर्षलेख "एक्सेस-कंट्रोल-अनुमति-उत्पत्ति: *") सेट करें। मैंने addHeader फ़ंक्शन के साथ नीचे एक छोटा परीक्षण केस लिखा लेकिन यह त्रुटियां समाप्त हो गईं। मैं नीचे दी गई त्रुटि को समझने में सहायता की सराहना करूंगा।Servant

कोड:

{-# LANGUAGE CPP   #-} 
{-# LANGUAGE DataKinds  #-} 
{-# LANGUAGE DeriveGeneriC#-} 
{-# LANGUAGE TypeFamilies #-} 
{-# LANGUAGE TypeOperators #-} 
{-# LANGUAGE OverloadedStrings #-} 
module Main where 

import Data.Aeson 
import GHC.Generics 
import Network.Wai 
import Servant 
import Network.Wai.Handler.Warp (run) 
import Control.Monad.Trans.Either 
import Control.Monad.IO.Class (liftIO) 
import Control.Monad (when, (<$!>)) 
import Data.Text as T 
import Data.Configurator as C 
import Data.Maybe 
import System.Exit (exitFailure) 

data User = User 
    { name    :: T.Text 
    , password   :: T.Text 
    } deriving (Eq, Show, Generic) 

instance ToJSON User 
instance FromJSON User 

type Token = T.Text 

type UserAPI = "grant" :> ReqBody '[JSON] User :> Post '[JSON] (Headers '[Header "Access-Control-Allow-Origin" T.Text] Token) 

userAPI :: Proxy UserAPI 
userAPI = Proxy 

authUser :: User -> Bool 
authUser u = case (password u) of 
    "somepass" -> True 
    _  -> False 

server :: Server UserAPI 
server = users 
    where users :: User -> EitherT ServantErr IO Token 
     users u = case (authUser u) of 
      True -> return $ addHeader "*" $ ("ok" :: Token) 
      False -> return $ addHeader "*" $ ("notok" :: Token) 

app :: Application 
app = serve userAPI server 

main :: IO() 
main = run 8081 app 

यह त्रुटि मैं मिलता है:

src/Test.hs:43:10: 
    Couldn't match type ‘Headers 
          '[Header "Access-Control-Allow-Origin" Text] Text’ 
        with ‘Text’ 
    Expected type: Server UserAPI 
     Actual type: User -> EitherT ServantErr IO Token 
    In the expression: users 
    In an equation for ‘server’: 
     server 
      = users 
      where 
       users :: User -> EitherT ServantErr IO Token 
       users u 
       = case (authUser u) of { 
        True -> return $ addHeader "*" $ ("something" :: Token) 
        False -> return $ addHeader "*" $ ("something" :: Token) } 

src/Test.hs:46:28: 
    Couldn't match type ‘Text’ with ‘Headers '[Header h v0] Text’ 
    In the expression: addHeader "*" 
    In the second argument of ‘($)’, namely 
     ‘addHeader "*" $ ("something" :: Token)’ 
    In the expression: return $ addHeader "*" $ ("something" :: Token) 

src/Test.hs:47:29: 
    Couldn't match type ‘Text’ with ‘Headers '[Header h1 v1] Text’ 
    In the expression: addHeader "*" 
    In the second argument of ‘($)’, namely 
     ‘addHeader "*" $ ("something" :: Token)’ 
    In the expression: return $ addHeader "*" $ ("something" :: Token) 

मैं एक सरल एपीआई (सरल GET) जहां यह काम करता है के साथ एक काम कर संस्करण है। लेकिन, उपरोक्त प्रकार के UserAPI के लिए, यह त्रुटियों से बाहर है। addHeader फ़ंक्शन प्रकार उस प्रकार के हस्ताक्षर से सहमत होता है जिस तरह से मैं इसके बारे में सोचता हूं। मुझे निश्चित रूप से कुछ याद आ रही है या यह इस तरह से त्रुटि नहीं होगी।

उत्तर

4

madjar पहले से ही इस सुझाव दिया है, लेकिन यह उनका विस्तार करना: addHeader में परिवर्तन वापसी प्रकार:

x :: Int 
x = 5 

y :: Headers '[Header "SomeHeader" String] Int 
y = addHeader "headerVal" y 

आपके मामले में, यह आप users के प्रकार के अपडेट करना पड़ता है इसका मतलब है जहां Either ServantErr IO (Headers '[Header "Access-Control-Allow-Origin" T.Text] Token

लौटने के लिए बाध्य

अधिक आम तौर पर, आप ghci में :kind! Server UserAPI का उपयोग कर सकते हैं यह देखने के लिए कि किस प्रकार का समानार्थी विस्तार होता है - यह अक्सर नौकर के साथ सहायक होता है!

+0

आह को निर्देशित नहीं किया, बहुत निर्देशक। धन्यवाद! मैं उलझन में था कि हेडर जोड़ते समय प्रकार क्यों नहीं बदलेंगे। जैसा कि आपने बताया है, वे बदलते हैं। – Sal

8

मुझे लगता है कि प्रतिक्रिया के लिए सीओआरएस हेडर जोड़ने का सबसे आसान तरीका नौकर के शीर्ष पर एक मिडलवेयर का उपयोग करना है। wai-cors यह बहुत आसान बनाता है:

import Network.Wai.Middleware.Cors 

[...] 

app :: Application 
app = simpleCors (serve userAPI server) 

अपने वास्तविक प्रतिक्रिया के लिए, मैं तुम्हें प्रकार Headers '[Header "Access-Control-Allow-Origin" T.Text के एक मूल्य में टाइप Text के एक मूल्य चालू करने के लिए addHeader उपयोग करने की आवश्यकता है लगता है।

+0

@majdar, बहुत उपयोगी सूचक। यह संभव है कि मैं जिस मार्ग पर जाऊंगा। मुझे उस उपयोगी लाइब्रेरी के बारे में पता नहीं था जब तक कि आपने – Sal