Haskell Servant: GET 带有任意请求数据的请求
Haskell Servant: GET Requests with arbitrary request data
我正在使用 Servant 为 API 提供服务,全部由 Snap 管理。在 Servant 中,很容易包含任意数据类型作为 POST 请求的一部分,假设它有一个 FromJSON
实例。例如,我可能有以下端点:
ReqBody '[JSON] RequestData :> Post '[JSON] [ResponseData]
如何对 GET 请求执行相同的操作?据我了解,我需要使用查询参数,但我的请求数据包含复杂的数据类型(列表、嵌套字典),这些数据类型似乎不容易阅读,例如QueryParam "vals" [Int] :> Post '[JSON] [Int]
导致错误 No instance for (FromHttpApiData [Int])
解决方法是使用 POST 请求,这些请求具有易于阅读的请求正文。但是,这会与我在 Nginx 中的缓存方案发生冲突,因为对 POST 请求的响应并不那么容易缓存。即使我可以缓存它们,我也不想缓存所有 post 请求,所以这将是一个混乱的方法。
感谢您的帮助!
如果您想要与 JSON post 主体相同级别的自动推导,一个简单的解决方案是将查询参数发送为 JSON
import Data.Aeson
import Servant.API
import qualified Data.Text as T
import Data.Text.Encoding
import qualified Data.ByteString.Lazy as LBS
newtype JSONEncoded a = JSONEncoded { unJSONEncoded :: a }
deriving (Eq, Show)
instance (FromJSON a) => FromHttpApiData (JSONEncoded a) where
parseQueryParam x = case eitherDecode $ LBS.fromStrict $ encodeUtf8 x of
Left err -> Left (T.pack err)
Right val -> Right (JSONEncoded val)
instance (ToJSON a) => ToHttpApiData (JSONEncoded a) where
toQueryParam (JSONEncoded x) = decodeUtf8 $ LBS.toStrict $ encode x
我正在使用 Servant 为 API 提供服务,全部由 Snap 管理。在 Servant 中,很容易包含任意数据类型作为 POST 请求的一部分,假设它有一个 FromJSON
实例。例如,我可能有以下端点:
ReqBody '[JSON] RequestData :> Post '[JSON] [ResponseData]
如何对 GET 请求执行相同的操作?据我了解,我需要使用查询参数,但我的请求数据包含复杂的数据类型(列表、嵌套字典),这些数据类型似乎不容易阅读,例如QueryParam "vals" [Int] :> Post '[JSON] [Int]
导致错误 No instance for (FromHttpApiData [Int])
解决方法是使用 POST 请求,这些请求具有易于阅读的请求正文。但是,这会与我在 Nginx 中的缓存方案发生冲突,因为对 POST 请求的响应并不那么容易缓存。即使我可以缓存它们,我也不想缓存所有 post 请求,所以这将是一个混乱的方法。
感谢您的帮助!
如果您想要与 JSON post 主体相同级别的自动推导,一个简单的解决方案是将查询参数发送为 JSON
import Data.Aeson
import Servant.API
import qualified Data.Text as T
import Data.Text.Encoding
import qualified Data.ByteString.Lazy as LBS
newtype JSONEncoded a = JSONEncoded { unJSONEncoded :: a }
deriving (Eq, Show)
instance (FromJSON a) => FromHttpApiData (JSONEncoded a) where
parseQueryParam x = case eitherDecode $ LBS.fromStrict $ encodeUtf8 x of
Left err -> Left (T.pack err)
Right val -> Right (JSONEncoded val)
instance (ToJSON a) => ToHttpApiData (JSONEncoded a) where
toQueryParam (JSONEncoded x) = decodeUtf8 $ LBS.toStrict $ encode x