¿Consecuencias de no hacer una API REST de la manera "correcta"?

8

Haré esta pregunta de esta manera: ¿cuáles son las preocupaciones de ingeniería de software para no implementar mi API REST de la manera "correcta"?

¿Qué quieres decir con la forma "correcta"? Bueno, permítame explicar mi percepción de la manera correcta, luego le diré cómo lo estoy haciendo (también, suponga que estoy hablando de una API JSON REST).

La direccion correcta

  1. Apatridia. Esta es la parte que sí entiendo. El cliente mantiene el estado siempre el 100% del tiempo para siempre. No es el trabajo del servidor, es del cliente.

  2. Las acciones esperadas y la respuesta para cada verbo:

    • GET : obtiene un recurso especificado en su totalidad, solo limitado por la autorización en la solicitud o por un parámetro de consulta. Esto asegura que no se modifique ningún recurso en el proceso.
    • POST : dada una descripción completa del recurso (como un objeto JSON), crea un recurso, luego devuelve ese recurso, con cualquier propiedad del servidor también creada, como fechas o ID.
    • BORRAR : elimina un recurso especificado, dando solo una especie de 200 OK como respuesta
    • PUT : dada una declaración de objeto completa como entrada, actualiza el recurso en una ubicación específica, actualizando todos los campos del recurso a cada uno de los campos dados en la entrada. Para que quede claro, esto espera que todo el objeto se pase como entrada. Se devuelve todo el recurso actualizado, con todos los campos (según la autorización o cualquier otro indicador de entrada).
    • PARCHE : dado que solo los campos que se desean modificar para un recurso, se actualizan solo los campos de un recurso específico que se proporcionan como entrada. (Aquí es donde no estoy claro): ¿Se devuelve todo el recurso? (¿O son solo los campos actualizados? No sé. No me importa).
  3. Rutas de recursos. Dada la relación de los recursos entre sí, una ruta de recursos puede verse como una de:
    • / parentresource /: id
    • / parentresource /: id / childresource
    • / parentresource /: id / childresource /: childId
    • / parentresource /: id / childresource /: childId / subresource /: subresourceId (en este ejemplo, un subrecurso pertenece a un childresource, que pertenece a un recurso primario).

La forma en que quiero hacerlo

Lo anterior es mi comprensión de cómo se supone que funciona una API REST. Ahora déjame enumerar algunas de mis variaciones a lo anterior:

  1. PUT / PATCH - ¿Cuál es el punto de pasar todo el recurso para su modificación? Solo uso PUT para modificar recursos, y solo paso en los campos que quiero actualizar. Como resultado, no necesito usar PATCH
  2. Rutas de recursos: utilizo GUID en mi aplicación. Como resultado, serán globalmente únicos. ¿Por qué necesito la ruta completa de los recursos, incluidos los recursos principales, si solo puedo referirme a un subrecurso por sí solo? Como:
     
    / subresource /: subresourceId
     
    Si tuviera que hacerlo de la manera "correcta", tratar de hacer referencia a la subresource requeriría una ruta completa como:
     
    / parentresource /: id / childresource /: childId / subresource /: subresourceId
     
    Es todo lo necesario ? Porque ahora tengo que tener un manejo de errores adicional si mi ruta contiene un: subresourceId que en realidad no es propiedad de un dado: childId, y lo mismo para un: childId que no es propiedad de un padre: id. Mi servidor se encarga de la autorización de recursos. ¿No puedo hacer referencia al recurso en sí, en lugar de la ruta completa?

  3. La respuesta de regreso. Digamos, por ejemplo, que mi estructura de datos es un árbol jerárquico, sin límites prácticos en la profundidad del árbol. Los recursos se encuentran en diferentes niveles en el árbol, de forma jerárquica.

    • El GET es obvio. Si obtengo este árbol completo, espero el árbol completo como respuesta, con los recursos contenidos dentro de los recursos.
    • Si POST para crear un nuevo recurso, PONER para actualizar o ELIMINAR para eliminar, quiero ver los deltas en el árbol, en lugar de solo ver el recurso que creé / actualicé / eliminé. No quiero tener que volver a llamar al GET del árbol principal después de cada POST, PUT o DELETE, especialmente si hay pequeños cambios en el árbol y solo quiero ver los deltas.

Espero que mis preguntas sean claras.

Si tuviera que ver una implementación REST como la describí, ¿lo miraría y me hablaría de sus inquietudes de ingeniería de software? Si es así, ¿cuáles serían?

Michael Plautz
fuente
44
Curiosamente, ninguna de sus preocupaciones implica las limitaciones arquitectónicas de REST. Sus preguntas están estrictamente vinculadas a la semántica WEB y HTTP. Parece que no te sientes cómodo con estos últimos, ¿qué me hace pensar, por qué hacer una interfaz web? Por otro lado, no existe tal cosa como "forma correcta" o "forma incorrecta". Solo implementaciones que se adapten mejor a sus necesidades. Lo que llamas "correcto" es más "amigable para la web" y "amigable para el desarrollador". Cuanto más "amigable para la web" sea, más ventajas tendrá de la arquitectura WWW. Ese sería el punto de hacer "cosas" web.
Laiv
El riesgo de desviarse de REST es que alguien que espera una interfaz RESTful se verá confundido por el comportamiento de su aplicación web. Sin embargo, lo que sugieres ni siquiera parece desviarse tanto para causar una confusión total, por lo que diría que lo que estás sugiriendo está perfectamente bien. ¡Solo agregue documentación!
Neil
@Laiv, haces una buena pregunta: ¿por qué hacer una interfaz web? Porque no estoy familiarizado con ninguna otra arquitectura que admita un marco de representación del lado del cliente, como React o Vue, que tener una interfaz web que envíe los datos que necesito. Para ser claros, no quiero la representación del lado del servidor, por razones de flexibilidad y rendimiento. También sé que GraphQL es una opción, pero no estoy muy familiarizado con ella.
Michael Plautz
GraphQL no es un estilo arquitectónico, es solo un lenguaje de consulta más con una gran cantidad de código de caldera debajo del capó. puedes aprovechar la WWW sin tener que DESCANSAR. Todavía hay WebSockets o ProtocolBuffers. Si su aplicación no es puramente transferencia de estadísticas representativas, REST no le sirve.
Laiv

Respuestas:

3

La respuesta subyacente general aquí es que sus ideas pueden funcionar a nivel técnico, pero eso no significa que se ajusten a las convenciones estandarizadas de REST.


  1. PUT / PATCH - ¿Cuál es el punto de pasar todo el recurso para su modificación? Solo uso PUT para modificar recursos, y solo paso en los campos que quiero actualizar. Como resultado, no necesito usar PATCH

Su idea funciona a nivel técnico, pero simplemente no es cómo se ha descrito REST. Tenga en cuenta que cualquier discusión sobre el código de trabajo (es decir, sin errores de compilación o tiempo de ejecución) siempre será una cuestión de convención , no necesariamente de clara superioridad técnica.


  1. Rutas de recursos: uso GUID en mi aplicación. Como resultado, serán globalmente únicos. ¿Por qué necesito la ruta completa de los recursos, incluidos los recursos principales, si solo puedo referirme a un subrecurso por sí solo?

Hay muchos matices en la forma en que definimos las entidades "hijo / padre". Más comúnmente, se refiere a una relación de uno a muchos (padres a hijos).

Sin embargo, sospecho que para REST, parte de lo que hace que un niño sea un niño es que existe la expectativa de poder acceder a ellos solo a través del padre, que no tienen su propio identificador único global (y conocido externamente).
Sospecho que esto sigue la misma filosofía (pero no necesariamente por la misma razón) que la de los agregados (y sus raíces) en el Desarrollo impulsado por dominio .

Un agregado DDD es un grupo de objetos de dominio que se pueden tratar como una sola unidad. Un agregado tendrá uno de sus objetos componentes como la raíz agregada. Cualquier referencia desde fuera del agregado solo debe ir a la raíz del agregado .

En su caso, lo que llama el "padre" funciona como la raíz agregada. El único punto de contacto (si lo desea) para las llamadas externas.

Es posible que desee concluir de esto que su hijo es en realidad un agregado diferente. Ese puede ser el caso, pero quiero emitir una advertencia con esa decisión. No debe basar su arquitectura en el tipo particular de un campo. No tiene forma de saber si siempre seguirá usando ID únicos a nivel mundial para todas sus entidades. Si eso cambia, por cualquier razón, comprometerá la viabilidad de su arquitectura REST; ya que puede terminar en una situación en la que el niño ya no es identificable de manera única y, por lo tanto, debe ser referenciado a través de su padre.


  1. Si POST para crear un nuevo recurso, PONER para actualizar o ELIMINAR para eliminar, quiero ver los deltas en el árbol, en lugar de solo ver el recurso que creé / actualicé / eliminé.

Estás violando el orden de operaciones del diseño. Una API REST está diseñada específicamente para ser independiente del consumidor. La API no debe construirse de acuerdo con las especificaciones de uno de sus consumidores.

Cuando dices "Quiero ver los deltas en el árbol", lo que realmente estás diciendo es "la aplicación que consume solo necesita ver los deltas en el árbol". Pero eso no le importa a la API REST. Simplemente proporciona un enfoque estandarizado.

Es la naturaleza de los enfoques estandarizados que a menudo carecen de herramientas altamente personalizables y, en cambio, favorecen las herramientas más utilizadas .


¿Puedes desviarte del camino? Bueno, funcionará a nivel técnico. Pero ya no será puro REST. Esto es algo altamente contextual y debe sopesar las opciones.

  • Si está creando una API que se espera que atienda a muchos consumidores variados, le sugiero que se apegue a REST lo mejor que pueda.
  • Si está creando una API que solo tendrá un consumidor que también desarrolle usted; entonces no hay necesidad real de apegarse a REST puro.
  • Alejarse del camino significa que tendrá que documentar cómo se ha desviado para que otros desarrolladores aún puedan entenderlo. Si se apega a REST puro, no tiene que escribir la documentación y los otros desarrolladores no tienen que gastar tiempo y esfuerzo en descubrir su enfoque personalizado.
Flater
fuente
9

¿Cuáles son las preocupaciones de ingeniería de software para no implementar mi API REST de la manera "correcta"?

La principal, en mi opinión, es la capacidad de delegar el trabajo a componentes genéricos que solo conocen los estándares, no su caso de negocio específico.

Si se está adhiriendo a la interfaz uniforme, es más fácil para otras partes crear componentes que se integren bien con los suyos.

Aquí está Fielding escribiendo en 2008

REST está destinado a aplicaciones basadas en red de larga duración que abarcan varias organizaciones.

Una de las formas en que manejamos la "larga vida" es tener un estándar claro que describa la semántica de los mensajes que transmitimos. Si todos están de acuerdo con lo que PUTsignifica, entonces los consumidores y productores de esas solicitudes pueden desarrollarse de manera independiente, y los componentes intermedios entre los dos pueden tomar medidas sensatas sin necesidad de conocer los detalles del mensaje en su contexto específico.

PUT / PATCH - ¿Cuál es el punto de pasar todo el recurso para su modificación? Solo uso PUT para modificar recursos, y solo paso en los campos que quiero actualizar. Como resultado, no necesito usar PATCH

¿Cuál es el punto de usar PUTentonces?

PURPLE /014d8c83-604d-4cf0-a6ba-e1f7ef8c4898 HTTP/1.1
...

Esa es una línea de solicitud perfectamente válida para un mensaje HTTP, y el cambio en la semántica no confundirá a nadie.

Equivalentemente

POST /014d8c83-604d-4cf0-a6ba-e1f7ef8c4898 HTTP/1.1
...

Lo cual tiene una semántica sin restricciones; el servidor puede implementar el manejo de esa solicitud de la forma que desee.

supongo que estoy hablando de una API JSON REST

Su renuencia a usar PATCH es especialmente extraña en este caso, ya que ya hay estándares propuestos para JSON Patch y JSON Merge Patch : el trabajo de estandarizar un formato de documento de parche ya puede hacerse por usted.

Otra alternativa válida sería tratar el documento de parche como un recurso separado. Semánticamente, podrías imaginar algo como

PUT /014d8c83-604d-4cf0-a6ba-e1f7ef8c4898/patches/5c42c414-03c0-4ac5-af14-2b1165ac98b3 HTTP/1.1

Eso le brinda una semántica de mensajes honesta y uniforme, sacrificando la invalidación de caché estandarizada .

En una configuración de revisión de código, rechazaría un cambio propuesto que intentara redefinir la semántica de PUT.

HTTP no intenta exigir que los resultados de un GET sean seguros. Lo que hace es exigir que la semántica de la operación sea segura y, por lo tanto, es un error de la implementación, no de la interfaz o del usuario de esa interfaz, si algo sucede como resultado de una pérdida de propiedad (dinero, por cierto, se considera propiedad por el bien de esta definición). - Fielding, 2002 .

La misma consideración es válida también para PUT; Si su implementación de PUT se desvía de la semántica estandarizada, entonces su implementación es responsable del daño resultante.

Rutas de recursos: uso GUID en mi aplicación. Como resultado, serán globalmente únicos. ¿Por qué necesito la ruta completa de los recursos, incluidos los recursos principales, si solo puedo referirme a un subrecurso por sí solo?

Eso está perfectamente bien. A REST no le importa qué ortografía use para sus identificadores de recursos.

Considere la página de inicio de google. ¿Necesita prestar atención a la ortografía del URI para el doodle de hoy? o donde se envía el formulario de búsqueda? No claro que no. La carga útil de HTML incluye URI, y los clientes solo usan los identificadores que se proporcionan, de manera estándar, sin necesidad de analizar esos identificadores.

La información codificada en un URI queda a discreción del servidor de origen, para sus propios fines.

Desalentaría el uso de un URI como punto de entrada de su API. https://www.example.org/df8f5f87-15ff-4212-8fb8-4fbca2c7efcfEs un poco incómodo para el consumo humano. Un URI legible por humanos que redirige al recurso UUID estaría bien, un URI legible por humanos que devuelve el contenido del recurso UUID sería mejor.

Si POST para crear un nuevo recurso, PONER para actualizar o ELIMINAR para eliminar, quiero ver los deltas en el árbol, en lugar de solo ver el recurso que creé / actualicé / eliminé

Eso está bien, de nuevo, mira el estándar .

La carga útil enviada en una respuesta 200 depende del método de solicitud. Para los métodos definidos por esta especificación, el significado previsto de la carga útil se puede resumir como

PUBLICAR una representación del estado de los resultados obtenidos de la acción

PONER, BORRAR una representación del estado de la acción

En algunos casos, tiene sentido enviar la nueva representación del recurso como parte de la respuesta (para ahorrarle al cliente la latencia de una solicitud / respuesta GET).

VoiceOfUnreason
fuente
2
What's the point in using PUT then?-- En efecto. Un POST funcionaría perfectamente bien.
Robert Harvey
@RobertHarvey ¿O por qué no usarlo PATCH? La definición se ajusta mejor.
Solomon Ucko
@SolomonUcko: Hacer de todo un POST tiene la virtud de la simplicidad.
Robert Harvey
3

REST es un estilo arquitectónico para manipular recursos de manera apátrida (donde apátrida significa que cada manipulación se sostiene por sí misma y no depende de otras manipulaciones que puedan haber tenido lugar).

El uso de los verbos PUT / PATCH / POST / GET / DELETE proviene del uso común del protocolo HTTP utilizado para transferir y manipular los recursos. El significado de esos verbos está definido por un estándar de Internet ( RFC7231 ).

Teniendo en cuenta estos antecedentes, su uso de PUT no es estándar y puede confundir a otros desarrolladores que quieran usar su API.

Con respecto a las rutas de recursos, casi nadie se preocupa por su ortografía exacta (incluso si un recurso secundario aparece como secundario). Lo que le importa a la gente es que cada recurso esté identificado de manera única. El sistema /parent/:pid/child/:cidse usa a menudo cuando las identificaciones secundarias solo son únicas dentro de un padre para tener una ruta global única al recurso.

Bart van Ingen Schenau
fuente
2
Además de la respuesta de Bart. Solo recuerde que el único que debe leer y comprender el URI es el Cliente HTTP, y no le importa la jerarquía de los recursos. Entonces, si el URI expresa jerarquía, relación o cualquier otro tipo de relación solo tiene sentido para el ser vivo pobre que necesita leerlo
Laiv
1
  1. PUT / PATCH - ¿Cuál es el punto de pasar todo el recurso para su modificación? Solo uso PUT para modificar recursos, y solo paso en los campos que quiero actualizar. Como resultado, no necesito usar PATCH

Me parece que realmente deberías estar usando PATCH como la semántica aquí.

  • PUT explica el estado exacto deseado. Esto es útil cuando un recurso puede estar cambiando con frecuencia, y el cambio deseado debe ocurrir dentro de un contexto específico.

  • PATCH explica un delta deseado a lo que sea que esté allí. Esto es útil cuando al cambio no le importa el contexto, o el contexto relevante es mucho más pequeño que todo el recurso.

Una imagen es un buen ejemplo en el que tendría sentido simplemente cargar todo. Es importante que todo el recurso se comunique para garantizar un contexto relevante.

Por el contrario, actualizar el recuento de reproducción en una lista de reproducción de música podría tener más sentido para ser un delta. No porque sea un pequeño cambio, sino porque volver a enviar la lista completa podría deshacer fácilmente los cambios en el contenido de la lista.

  1. Rutas de recursos: uso GUID en mi aplicación. Como resultado, serán globalmente únicos. ¿Por qué necesito la ruta completa de los recursos, incluidos los recursos principales, si solo puedo referirme a un subrecurso por sí solo?

...recorte...

¿Es todo eso necesario? Porque ahora tengo que tener un manejo de errores adicional si mi ruta contiene un: subresourceId que en realidad no es propiedad de un dado: childId, y lo mismo para un: childId que no es propiedad de un padre: id. Mi servidor se encarga de la autorización de recursos. ¿No puedo hacer referencia al recurso en sí, en lugar de la ruta completa?

No, realmente no necesitas usar rutas, nunca. Digamos que mantiene todos sus archivos en el escritorio? ¿No? Por qué no?

Probablemente tenga algo que ver con hacerlo más fácil de ver, el mismo problema aquí. Un GUID no le dice lo que está manejando mientras lo configura, lo depura o lo ejecuta.

Entonces, ¿qué se siente al apoyar este sistema? o para interactuar con él? Si no lo ha pensado, tómese un tiempo y considere el trabajo que está haciendo.

Tener información de ruta explícita sirve para ayudar a validar la solicitud. También ayuda a diferenciar la información lo suficiente como para que el soporte y los desarrolladores de sistemas posteriores puedan abordar estas URL y usarlas.

  1. La respuesta de regreso. Digamos, por ejemplo, que mi estructura de datos es un árbol jerárquico, sin límites prácticos en la profundidad del árbol. Los recursos se encuentran en diferentes niveles en el árbol, de forma jerárquica.

    a. El GET es obvio. Si obtengo este árbol completo, espero el árbol completo como respuesta, con los recursos contenidos dentro de los recursos.

Es posible que desee imponer un límite de profundidad, simplemente para que un niño inteligente no obtenga simplemente la raíz de su sitio para cada operación que se les ocurra.

si. Si POST para crear un nuevo recurso, PONER para actualizar o ELIMINAR para eliminar, quiero ver los deltas en el árbol, en lugar de solo ver el recurso que creé / actualicé / eliminé. No quiero tener que volver a llamar al GET del árbol principal después de cada POST, PUT o DELETE, especialmente si hay pequeños cambios en el árbol y solo quiero ver los deltas.

Si actualizar un recurso está afectando a su padre de una manera no trivial y predecible, tiene otros problemas ... Realmente necesita mirar el modelo de estado y descubrir por qué la información está saltando.

Si solo desea devolver una lista detallada de deltas, ¿por qué no? ¿Por qué no admitir varias vistas de salida conmutadas por varios parámetros? Jenkins devuelve sus respuestas API en una opción de xml o json y le permite especificar varios filtros para extraer el subárbol deseado.

Úselo usted mismo

Francamente, sin embargo, retrocede de lo que estás haciendo e intenta admitirlo, o crea otra aplicación para usarlo (no una de tus aplicaciones preexistentes). Haga algo similar para las API de terceros para tener un pequeño contexto de fondo.

Siempre que tenga que hacer algo que no resuelva directamente la solicitud de soporte, o que sea directamente necesario para la aplicación del cliente, entonces la API es menos que ideal, y sabe por qué es menos que ideal, lo que es aún mejor, porque puede arreglarlo o no cometer el mismo error.

Por ejemplo, si las solicitudes a una URL dada fallan constantemente, ¿cuánto esfuerzo tiene que invertir para determinar qué está fallando y por qué? ¿Qué pasos tomaste? ¿Podrías haber evitado uno de esos pasos al tener un mejor URI, o un mejor registro, o un mejor monitoreo, etc.?

Del mismo modo, si está escribiendo un nuevo cliente, ¿cuántas veces necesita consultar la documentación o el código fuente de la API? ¿Qué podrías hacer para reducir esa necesidad? ¿Qué podrías hacer para dejar de violar tus propias expectativas? ¿Qué podría hacer para simplificar el problema de las aplicaciones del cliente sin hacer que el servidor sea una pesadilla de mantener?

Manera correcta

Francamente, el camino correcto es circunstancial. REST es un conjunto de prácticas que funcionan en varias circunstancias para una serie de problemas. Si su problema no encaja, no lo haga, pero tampoco pretenda utilizar esas prácticas.

Kain0_0
fuente
-1

La mayoría de las características de las API REST están ahí por una razón, pero puede que no sea una razón relevante para usted. Dar todo el recurso, como en PUT, por ejemplo, es relevante si necesita idempotencia, de lo contrario no lo es. (Aunque creo que sería mejor para los usuarios / colegas / lo que sea anunciar el hecho de que su punto final no es idempotente al usar POST o PATCH en su lugar).

Por lo del camino, nunca he oído que esté relacionado con el descanso. /root/345dd4dc-e175-455f-b545-85b1b1ce3e82es tan parte de un árbol como /foo/bar/baz. Tal vez un poco menos fácil de usar, pero no menos resty hasta donde puedo ver.

Si desea un razonamiento más detallado sobre por qué REST fue diseñado tal como está, creo que debería leer la disertación original: https://www.ics.uci.edu/~fielding/pubs/dissertation/fielding_dissertation.pdf

Leyendo que podría descubrir que es bastante diferente de cómo REST se representa en las conversaciones o se usa en las API de hoy. Claramente, muchas otras personas han encontrado una razón, buena o mala, para apartarse de ella.

Particularmente me gusta esta cita que puede encontrar relevante:

HTTP no está diseñado para ser un protocolo de transporte. Es un protocolo de transferencia en el que los mensajes reflejan la semántica de la arquitectura web mediante la realización de acciones sobre los recursos a través de la transferencia y manipulación de representaciones de esos recursos. Es posible lograr una amplia gama de funcionalidades utilizando esta interfaz muy simple, pero se requiere seguir la interfaz para que la semántica HTTP permanezca visible para los intermediarios. Es por eso que HTTP atraviesa firewalls. La mayoría de las extensiones propuestas recientemente para HTTP, aparte de WebDAV [60], simplemente han utilizado HTTP como una forma de mover otros protocolos de aplicación a través de un firewall, lo cual es una idea fundamentalmente equivocada. No solo vence el propósito de tener un firewall, pero no funcionará a largo plazo porque los proveedores de firewall simplemente tendrán que realizar un filtrado de protocolo adicional. Por lo tanto, no tiene sentido hacer esas extensiones sobre HTTP, ya que lo único que HTTP logra en esa situación es agregar una sobrecarga desde una sintaxis heredada. Una verdadera aplicación de HTTP asigna las acciones del usuario del protocolo a algo que se puede expresar utilizando la semántica HTTP, creando así una API basada en la red para servicios que los agentes e intermediarios pueden entender sin ningún conocimiento de la aplicación.

monocelda
fuente
2
"Aunque creo que sería más amable con los usuarios / colegas / lo que sea anunciar el hecho de que su punto final no es idempotente utilizando POST o PATCH". - Esto no es una cuestión de amabilidad. Los métodos HTTP tienen una semántica definida con precisión, y toda la infraestructura web mundial depende de esa semántica. Por ejemplo, los proxies pueden volver a intentar las PUTsolicitudes varias veces sin que usted lo sepa, y pueden hacerlo porque la especificación HTTP dice que PUTes idempotente . Si sus PUTcorreos electrónicos no son idempotentes, esto interrumpirá su servicio .
Jörg W Mittag
2
Por un tiempo, los "aceleradores web" estaban de moda, y de hecho, están regresando para dispositivos móviles. Esos aceleradores hicieron la precarga y el almacenamiento en caché de los recursos, y se les permitió hacer eso, porque la especificación HTTP garantiza eso GETy HEADson puros y sin efectos secundarios. Algunas personas perdieron datos, porque estaban usando aplicaciones web mal diseñadas, donde la eliminación del contenido se realizó con una GETsolicitud, y el acelerador web felizmente envió GETsolicitudes a todos los URI que pudo encontrar.
Jörg W Mittag
Estas en lo correcto, por su puesto. Ya no puedo generar más entusiasmo con respecto a una web que funcione correctamente. Se siente como una batalla perdida para mí, pero tal vez estás en un ambiente más agradable donde estas cosas realmente funcionan. Donde estoy http es solo un transporte con la adición de que es debugable desde un navegador en lugar de netcat, y eso es todo.
monocell