es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Haskell Servant: ¿Cómo agregar un prefijo a rutas al usar genéricos?

Estoy usando Servant generic y tengo un tipo de dato para mis rutas:

data Routes route = Routes
  { getLiveness :: route :- GetLiveness,
    getReadiness :: route :- GetReadiness,

    getAuthVerifyEmailToken :: route :- GetAuthVerifyEmailToken,
    postAuthEmail :: route :- PostAuthEmail,
...
  }
  deriving (Generic)

type BackendPrefix = "backend"
type AuthPrefix = "auth"
type GetLiveness = BackendPrefix :> "liveness" :> Get '[JSON] Text
type GetReadiness = BackendPrefix :> "readiness" :> Get '[JSON] Text
type GetAuthVerifyEmailToken = AuthPrefix :> "verify" :> "email" :> Capture "token" JWT :> RedirectResponse '[PlainText] NoContent
type PostAuthEmail = AuthPrefix :> "email" :> ReqBody '[JSON] AuthEmailRequest :> PostNoContent

Las primeras dos rutas utilizan el mismo prefijo backend, y todas las demás tienen un prefijo auth.

Sin embargo, ahora quiero cambiar el prefijo auth a backend/auth. Entonces intenté cambiar:

type AuthPrefix = BackendPrefix :> "auth"

Esto da como resultado un error:

    • Se esperaba un tipo, pero ‘"auth"’ tiene el tipo ‘GHC.Types.Symbol’
    • En el segundo argumento de ‘(:>)’, a saber ‘"auth"’
      En el tipo ‘BackendPrefix :> "auth"’
      En la declaración del tipo ‘AuthPrefix’
   |
34 | type AuthPrefix = BackendPrefix :> "auth"
   |

Así que busqué en Google y encontré que puedes hacer esto aquí cuando no estás usando generic:

type APIv1 = "api" :> "v1" :> API

Pero no pude entender cómo hacer esto con generic.

Supongo que eso deja dos preguntas:

  1. ¿Qué significa el error anterior y puedo usar algo como type AuthPrefix = BackendPrefix :> "auth" para crear un prefijo más complejo?
  2. ¿Hay alguna manera de agregar un prefijo distinto a algunas rutas y un prefijo diferente a otras rutas al usar generic en Servant?
Tags:  ,

Answer

  1. Avatar for davy.ai
    1. El mensaje de error significa que :> espera un tipo como su segundo argumento, pero "auth" es un tipo Symbol, no un tipo. Para crear un prefijo más complejo usando :>, puedes encadenar múltiples operadores :> juntos, de esta manera:
    type AuthPrefix = "backend" :> "auth"
    
    1. Sí, hay una forma de agregar un prefijo a algunas rutas con un prefijo diferente al usar genéricos en Servant. Un enfoque es crear tipos separados para cada prefijo, de esta manera:
    data BackendRoutes route = BackendRoutes
      { getLiveness :: route :- "liveness" :> Get '[JSON] Text
      , getReadiness :: route :- "readiness" :> Get '[JSON] Text
      }
    
    data AuthRoutes route = AuthRoutes
      { getVerifyEmailToken :: route :- "verify" :> "email" :> Capture "token" JWT :> RedirectResponse '[PlainText] NoContent
      , postAuthEmail :: route :- "email" :> ReqBody '[JSON] AuthEmailRequest :> PostNoContent
      }
    
    type API = BackendRoutes :<|> AuthRoutes
    

    Aquí, BackendRoutes y AuthRoutes son dos tipos de registros separados que contienen las rutas para cada prefijo. El operador :<|> los combina en un solo tipo de API. Este enfoque te permite agregar o eliminar fácilmente rutas para cada prefijo sin tener que modificar un tipo de Routes compartido.

Comments are closed.