Apollo-link-rest: ¿Estrategia recomendada para manejar errores 404?

Creado en 6 jun. 2018  ·  12Comentarios  ·  Fuente: apollographql/apollo-link-rest


Es bastante común que una API REST use una respuesta 404 para indicar que no existe un registro. En este momento, cuando esto sucede, el resultado es un networkError que parece, por defecto, ser tratado como un error más fatal que un error GraphQL por la pila de Apollo.

Por ejemplo, con la consulta:

query BookQuery($slug: ID!) {
  book(slug: $slug) @rest(type: "Book", path: "book/:slug") {
    name
    author
  }
}

Si el punto final devuelve 404, lo rechaza con un error de red que debe manejarse donde es probable que la intención simplemente use la propiedad de renderización error para mostrar el mensaje de error no fatal a un usuario. es decir, si se tratara de una consulta GraphQL en lugar de REST, no se clasificaría como un error de red y se manejaría de esta manera.

Lo que hice para solucionar esto fue agregar un cheque a mi error-link que transforma el error de red 404 en un error GraphQL:

forward(operation).subscribe({
  next: result => {...},
  error: networkError => {
    if (networkError.statusCode === 404) {
      return observer.next({errors: [networkError]});
    }
    //...
    observer.error(networkError);
  },
  complete: observer.complete.bind(observer),
});

Probablemente todavía hay margen de mejora en esto, pero resuelve el problema.

Me preguntaba si esto podría / debería abordarse de alguna manera en apollo-link-rest , así que pensé que comenzaría la conversación.

enhancement💡 question❔

Todos 12 comentarios

Esa es una gran pregunta. - Me encantaría que este patrón se agregara como sugerencia a la documentación. Creo que es una clase de problemas que sufren múltiples enlaces apolo (me viene a la mente apollo-link-state).

Sin embargo, no sé si estamos seguros de que esta sea la respuesta correcta para todos los usuarios de ApolloLink.

Así es como se manejan actualmente todos los errores http en apollo-link-rest

        if (res.status >= 300) {
          // Throw a JSError, that will be available under the
          // "Network error" category in apollo-link-error
          let parsed: any;
          try {
            parsed = await res.json();
          } catch (error) {
            // its not json
            parsed = await res.text();
          }
          rethrowServerSideError(
            res,
            parsed,
            `Response not successful: Received status code ${res.status}`,
          );
        }
        return res;

¿Quizás agregamos una función de coincidencia de casos que permite a los usuarios dictar cómo se procesa el error?
Podría proporcionar algunas utilidades predeterminadas útiles para casos comunes como 404 == null

Si bien comparto la preocupación de @fbartho de que una solución que presentemos podría no ser adecuada para todos los usuarios de este enlace, pensé en un caso en el que un error 404 es particularmente dañino. Si tomamos este ejemplo de las pruebas:

query postAndTags {
  post @rest(type: "Post", path: "/post/1") {
    id
    title
  }
  tags @rest(type: "[Tag]", path: "/tags") {
    name
  }
}

y el post no existe y devuelve un 404, entonces toda la consulta falla por un error de red. Si bien eso podría desearse en algunos casos, parece que el resultado debería ser:

const data = {
  post: null,
  tags: [{ name: 'apollo' }, { name: 'graphql' }],
}

Si queremos atender esto, agregar manejo de errores adicional como sugiere @paulpdaniels será bastante fácil. Al revisar los errores 4xx, solo puedo ver que 404 y 400/412/422 (en mutaciones) posiblemente sean errores no fatales que requieran un tratamiento especial, ya sea como errores GraphQL o estableciendo el resultado en null .

La pregunta sigue siendo si es razonable proporcionar algún controlador fijo para estos errores o si debería dejarse en manos de la aplicación error-link . Dado que las consultas de mutaciones múltiples no son compatibles (¿creo?), El único inconveniente actual que parece particularmente relevante es el ejemplo 404 con el que comencé anteriormente.

También existe la opción de agregar un controlador de errores a la configuración, pero parece que podría estar robando funcionalidad a un error-link que realmente pertenece allí. También puede hacer que la API de este enlace sea innecesariamente compleja.

@marnusw Esa es una gran respuesta. ¡Apoyaría una solución que implemente su comportamiento de forma predeterminada!

142 agrega manejo de errores 404. Creo que eso es lo más importante de esta discusión.

Según muchos estándares de la API de descanso , todos los códigos de error siempre deben incluir un mensaje legible por humanos. Anular ese resultado, como se hizo en el n. ° 142, se opone directamente a eso.

He puesto un PR para restablecer los 404 como errores de red normales, para coincidir con las buenas prácticas de API REST: https://github.com/apollographql/apollo-link-rest/pull/283

@christrude, aunque no puedo estar en desacuerdo contigo en lo que respecta a las API REST, el propósito de esta biblioteca es hacer que las API REST funcionen como GraphQL. Por lo tanto, si el enfoque de GraphQL para los recursos faltantes es devolver null , esta biblioteca debería convertir la convención RESTful 404 a la convención de valor de retorno GraphQL null .

@christrude, aunque no puedo estar en desacuerdo contigo en lo que respecta a las API REST, el propósito de esta biblioteca es hacer que las API REST funcionen como GraphQL. Por lo tanto, si el enfoque de GraphQL para los recursos faltantes es devolver null , esta biblioteca debería convertir la convención RESTful 404 a la convención de valor de retorno GraphQL null .

Entonces, ¿cómo te propone GraphQL que manejes una respuesta 404 en la interfaz de usuario? ¿Hacer nada? ¿Entonces las solicitudes simplemente mueren en silencio? Eso es una gestión de UX / api increíblemente mala / pobre.

Si consulta un elemento por ID y obtiene un valor nulo, maneje eso en consecuencia en la interfaz de usuario. Si contiene datos, muéstrelos.

Estoy de acuerdo con @marnusw aquí, realmente no podemos controlar lo que hace la API de descanso del usuario, por lo que la biblioteca no debería ser demasiado restrictiva en lo que permite. El mapeo 404 => null es una semántica relativamente intuitiva que le permite pasar del modelo de recurso único por solicitud de REST al recurso múltiple por solicitud (desde la perspectiva del cliente) de GraphQL sin explotar con los datos faltantes.

Quizás podría haber una mejor manera de optar por no participar en este comportamiento, como una versión preempaquetada del transformador de respuesta o una abstracción de la lógica de manejo de solicitudes que permite al usuario controlar completamente el manejo del estado http. Pero no creo que volver al comportamiento anterior sea el enfoque correcto.

Parte del problema del enfoque es que, en la suscripción de resultados, no tiene conocimiento de si es un resultado nulo porque es un 404, o si es un retorno sin contenido 201 o algo similar. He solucionado esto en el software posterior, verificando el estado y forzándolo a lanzar un error que asume el problema porque no puedo acceder al mensaje de error del servidor real, especialmente en mi caso porque usamos la recuperación personalizada para inyectar un token de autenticación , y no puede usarlo para obtener la respuesta antes de que apollo lo elimine. Mi solución es una mala manta para otras respuestas 404 en la aplicación, aparte de un caso.

¿Fue útil esta página
0 / 5 - 0 calificaciones