rest - son - servicios web tutorial
El mejor enfoque para diseñar un servicio web de descanso con datos binarios para ser consumidos desde el navegador (3)
Creo que el método definitivo es el número 3 (recurso separado) por la razón principal de que permite maximizar el valor que obtengo del estándar HTTP, que coincide con mi opinión sobre las API REST. Por ejemplo, y suponiendo que esté en uso un cliente HTTP bien fundamentado, obtendrá los siguientes beneficios:
- Compresión de contenido : optimiza permitiendo que los servidores respondan con un resultado comprimido si los clientes indican que admiten, su API no se modifica, los clientes existentes continúan funcionando, los futuros clientes pueden hacer uso de ella.
- Almacenamiento en caché : If-Modified-Since, ETag, etc. Los clientes pueden evitar volver a recopilar los datos binarios por completo
- Abstracción del tipo de contenido : por ejemplo, necesita una imagen cargada, puede ser de tipos
image/jpeg
oimage/png
. Los encabezados HTTP Aceptar y Tipo de contenido nos dan una semántica elegante para negociar esto entre clientes y servidores sin tener que codificarlo todo como parte de nuestro esquema y / o API
Por otro lado, creo que es justo concluir que este método no es el más simple si los datos binarios en cuestión no son opcionales. En cuyo caso los contras listados en la respuesta de Eric Hu entrarán en juego.
Estoy desarrollando un servicio web json rest que se consumirá desde una única aplicación de página web creada con backbone.js
Esta API permitirá al consumidor cargar archivos relacionados con alguna entidad, como informes en formato PDF relacionados con un proyecto
Buscando en Google y haciendo una investigación en el desbordamiento de pila llegué con estos posibles enfoques:
Primer acercamiento: campo de datos codificados base64
POST: /api/projects/234/reports
{
author: ''xxxx'',
abstract: ''xxxx'',
filename: ''xxxx'',
filesize: 222,
content: ''<base64 encoded binary data>''
}
Segundo enfoque: publicación de formulario multiparte:
POST: /api/projects/234/reports
{
author: ''xxxx'',
abstract: ''xxxx'',
}
como respuesta obtendré una identificación de informe, y con eso publicaré otra publicación
POST: /api/projects/234/reports/1/content
enctype=multipart/form-data
y luego solo envíe los datos binarios
(Eche un vistazo a esto: https://stackoverflow.com/a/3938816/47633 )
Tercer enfoque: publicar los datos binarios en un recurso separado y guardar el href
primero genero una clave aleatoria en el cliente y publico el contenido binario allí
POST: /api/files/E4304205-29B7-48EE-A359-74250E19EFC4
enctype=multipart/form-data
y entonces
POST: /api/projects/234/reports
{
author: ''xxxx'',
abstract: ''xxxx'',
filename: ''xxxx'',
filesize: 222,
href: ''/api/files/E4304205-29B7-48EE-A359-74250E19EFC4''
}
(mira esto: https://stackoverflow.com/a/4032079/47633 )
Solo quería saber si hay algún otro enfoque que pueda usar, los pros / contra de cada uno, y si hay alguna forma establecida de lidiar con este tipo de requisitos.
El gran problema que veo para el primer enfoque, es que tengo que cargar completamente y codificar el archivo base64 en el cliente
algunos recursos útiles:
- Publicar datos binarios en una aplicación RESTful
- ¿Cuál es una buena forma de transferir datos binarios a un servicio HTTP REST API?
- ¿Cómo cargo un archivo con metadatos usando un servicio web REST?
- ¿Una mala idea para transferir una gran carga usando servicios web?
- https://stackoverflow.com/a/5528267/47633
Mis resultados de investigación:
Solicitud individual (datos incluidos)
La solicitud contiene metadatos. Los datos son una propiedad de los metadatos y están codificados (por ejemplo, Base64).
Pros:
- transaccional
- cada vez que sea válido (no faltan metadatos o datos)
Contras:
- la codificación hace que la solicitud sea muy grande
Ejemplos:
Solicitud individual (multiparte)
La solicitud contiene una o más partes con metadatos y datos.
Tipos de contenido:
Pros:
- transaccional
- cada vez que sea válido (no faltan metadatos o datos)
Contras:
- la negociación del tipo de contenido es compleja
- el tipo de contenido para los datos no es visible en WADL
Ejemplos:
- Confluence (con partes de datos y metadatos)
- Jira (con una parte para los datos, los metadatos solo encabezados de parte para el nombre de archivo y el tipo de mimo)
- Bitbucket (con una parte para datos, sin metadatos)
- Google Drive (con una parte para los metadatos y otra para los datos de las piezas)
Solicitud única (metadatos en encabezado HTTP y URL)
El cuerpo de la solicitud contiene los datos y el encabezado HTTP y el URL contiene los metadatos.
Pros:
- transaccional
- cada vez que sea válido (no faltan metadatos o datos)
Contras:
- no hay metadatos anidados posibles
Dos solicitud
Una solicitud de metadatos y una o más solicitudes de datos.
Pros:
- escalabilidad (por ejemplo: la solicitud de datos podría ir al servidor del repositorio)
- reanudable (ver, por ejemplo, Google Drive )
Contras:
- no transaccional
- no cada vez que es válido (antes de la segunda solicitud, falta una parte)
Ejemplos:
No puedo pensar en ningún otro enfoque fuera de mi cabeza.
De sus 3 enfoques, he trabajado con el método 3 más. La mayor diferencia que veo es entre el primer método y el otro 2: separar los metadatos y el contenido en 2 recursos
- Pro: escalabilidad
- mientras que su solución implica publicar en el mismo servidor, esto puede cambiarse fácilmente para apuntar el contenido cargado a un servidor por separado (es decir, Amazon S3)
- En el primer método, el mismo servidor que sirve metadatos a los usuarios tendrá un proceso bloqueado por una gran carga.
- Con: datos huérfanos / complejidad añadida
- las cargas fallidas (ya sean metadatos o contenido) dejarán datos huérfanos en la base de datos del servidor
- Los datos huérfanos se pueden limpiar con un trabajo programado, pero esto agrega complejidad de código
- El Método II reduce las posibilidades huérfanas, a costa de un tiempo de espera del cliente más largo, ya que está bloqueando la respuesta del primer POST
El primer método parece ser el más simple de codificar. Sin embargo, solo utilizaría el primer método si anticipo que este servicio se utiliza con poca frecuencia y puede establecer un límite razonable para la carga de archivos del usuario.