-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathejercicios-web.tex
4476 lines (3023 loc) · 238 KB
/
ejercicios-web.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
%% ejercicios.tex
%%
%% Ejercicios (comunes para SAT y SARO), 2013-2014.
%% %%----------------------------------------------------------------------------
%% %%----------------------------------------------------------------------------
%%----------------------------------------------------------------------------
\section{Prácticas de entrega voluntaria}
%%---------------------------------------------------------------------------
%%---------------------------------------------------------------------------
%%---------------------------------------------------------------------------
\subsection{Entrega de microprácticas y miniprácticas}
\label{sec:eje-entrega-practicas-incr}
Para la entrega de prácticas incrementales se utilizarán repositorios git públicos alojados en el GitLab de la ETSIT. Para cada práctica entregable los profesores abrirán un repositorio público en el proyecto CursosWeb~\footnote{\url{https://gitlab.etsit.urjc.es/CursosWeb}}, con un nombre que comenzará por ``X--Serv--'', seguirá con el nombre del tema en el que se inscribe la práctica (por ejemplo, ``Python'' para el tema de introducción a Python) y el identificador del ejercicio (por ejemplo, ``Calculadora''). En el caso de las miniprácticas, el nombre comenzará por ``Mini--'', seguido de un número (el de orden de entrega), y el identificador del ejercicio. Este repositorio incluirá un fichero README.md, con el enunciado de la práctica, y cualquier otro material que los profesores estimen conveniente.
Cada alumno dispondrá de una cuenta en el GitLab de la ETSIT, que usará a efectos de entrega de prácticas. Esta cuenta deberá ser apuntada en una lista, en el sitio de la asignatura en el campus virtual, cuando los profesores se lo soliciten. Si el alumno desea que no sea fácil trazar su identidad a partir de esta cuenta, puede elegir abrir una cuenta no ligada a sus datos personales: a efectos de valoración, los profesores utilizará la lista anterior. Si el alumno lo desea, puede usar la misma cuenta en GitLab para otros fines, además de para la entrega de prácticas.
Para trabajar en una práctica, los alumnos comenzarán por realizar una copia (fork) de cada uno de estos repositorios. Esto se realiza en GitLab, visitando (tras haberse autenticado con su cuenta de usuario de GitLab para entrega de prácticas) el repositorio con la práctica, y pulsando sobre la opción de realizar un fork. Una vez esto se haya hecho, el alumno tendrá un fork del repositorio en su cuenta, con los mismos contenidos que el repositorio original de la práctica. Visitando este nuevo repositorio, el alumno podrá conocer la url para clonarlo, con lo que podrá realizar su clon (copia) local, usando la orden \verb|git clone|.
A partir de este momento, el alumno creará los ficheros que necesite en su copia local, los irá marcando como cambios con \verb|git commit| (usando previamente \verb|git add|, si es preciso, para añadirlos a los ficheros considerados por git), y cuando lo estime conveniente, los subirá a su repositorio en GitLab usando \verb|git push|.
Por lo tanto, el flujo normal de trabajo de un alumno con una nueva práctica será:
\begin{verbatim}
[En GitLab: visita el repositorio de la práctica en CursosWeb,
y le hace un fork, creando su propia copia del repositorio]
git clone url_copia_propia
[Se cera el directorio copia_propia, copia local del repositorio propio]
cd copia_propia
git add ... [ficheros de la práctica]
git commit .
git push
\end{verbatim}
Conviene visitar el repositorio propio en GitLab, para comprobar que efectivamente los cambios realizados en la copia local se han propagado adecuadamente a él, tras haber invocado \verb|git push|.
%%----------------------------------------------------------------------------
%%----------------------------------------------------------------------------
\subsection{Minipráctica 1 (entrega voluntaria)}
\label{subsec:minipractica-1-2025}
\textbf{Repositorio plantilla (para entrega):} \\
\url{https://gitlab.eif.urjc.es/cursosweb/2024-2025/mini-1-acortadora}
Esta práctica tiene como objetivo la creación de una aplicación web para acortar URLs. Los usuarios podrán especificar una URL y un alias para la URL acortada. Si no especifican un alias, se mostrará un error. La aplicación almacenará las URLs acortadas en un fichero persistente utilizando la biblioteca \texttt{shelve}.
El código ha de guardarse en un fichero llamado \emph{shortener.py}.
El funcionamiento de la aplicación ha de ser el siguiente:
\begin{itemize}
\item \textbf{Recurso ``/'' (GET):} Devuelve una página HTML con un formulario donde el usuario podrá ingresar una URL y un alias para la URL acortada. También mostrará un listado de todas las URLs acortadas hasta el momento.
\item \textbf{Recurso ``/'' (POST):} Si el formulario incluye una \texttt{qs} con un campo \texttt{url} y un campo \texttt{alias}, se validará la entrada y se generará una URL acortada con el alias proporcionado por el usuario. Si el alias ya ha sido utilizado, se actualizará con la nueva URL. La respuesta incluirá el formulario junto con la lista de URLs acortadas, incluyendo la nueva o la actualizada. Si no se especifica un alias, se devolverá un mensaje error.
\item \textbf{Recurso ``/alias'' (GET):} Si el alias corresponde a una URL almacenada, se realizará un HTTP 3XX Redirect a la URL real. Si no existe, se mostrará un mensaje de error de cliente (4XX) indicando que el recurso no está disponible.
\item \textbf{Recurso ``/delete/alias'' (GET):} Permite eliminar una URL acortada si el usuario lo desea. Se mostrará un mensaje confirmando la eliminación o un error si no existiera tal alias.
\end{itemize}
\textbf{Ejemplo de funcionamiento:}
\begin{itemize}
\item Un usuario accede a la aplicación en \texttt{http://localhost:1234/} y ve un formulario donde puede ingresar la URL que desea acortar y un alias. Justo debajo aparece un listado de todas las URLs acortadas hasta el momento (extraído del fichero persistente usando \texttt{shelve})
\item El usuario ingresa ``http://gsyc.es'' y el alias ``miweb'' en el formulario.
\item Al enviar el formulario, la aplicación responde con una página que contiene:
\begin{verbatim}
URL original: http://gsyc.es
URL acortada: http://localhost:1234/miweb
\end{verbatim}
Internamente se habrá guardado la información en el fichero persistente con \texttt{shelve}.
\item Si otro usuario intenta usar el alias ``miweb'' con una URL diferente, la aplicación actualizará la URL almacenada para ese alias. Internamente se habrá actualizado la URL en el fichero persistente con \texttt{shelve}.
\item Si alguien accede a \texttt{http://localhost:1234/miweb}, la aplicación redirige a la URL actualizada.
\item El usuario puede eliminar una URL acortada accediendo a \texttt{http://localhost:1234/delete/miweb}. Internamente se habrá borrado la URL del fichero persistente también con \texttt{shelve}.
\end{itemize}
\textbf{Pasos recomendados para la implementación:}
\begin{itemize}
\item Implementar ``GET /'' para mostrar el formulario y la lista de URLs acortadas.
\item Implementar ``POST /'' para procesar el formulario y almacenar las URLs acortadas.
\item Implementar ``GET /recurso'' para redireccionar correctamente a las URLs.
\item Implementar ``GET /delete/alias'' para permitir eliminar URLs acortadas.
\item Manejar las condiciones de error y realizar el resto de la funcionalidad.
\end{itemize}
\textbf{Comentario:} Se recomienda el uso de un diccionario para almacenar las URLs reales y los alias. La clave será el alias y el valor será la URL real.
%%---------------------------------------------------------------------
%%---------------------------------------------------------------------
\subsection{Minipráctica 2 (entrega voluntaria)}
\label{subsec:minipractica-2-2024}
\textbf{Repositorio plantilla (para entrega):} \\
\url{https://gitlab.eif.urjc.es/cursosweb/2023-2024/mini-2-acortadora}
Esta práctica tendrá como objetivo la creación de una aplicación web (de nombre \emph{acorta}) simple para acortar URLs utilizando Django (en un nuevo proyecto Django llamado \emph{project}). Su enunciado será igual que el de la práctica 1 de entrega voluntaria (ejercicio~\ref{subsec:minipractica-1-2025}), salvo en los siguientes aspectos:
\begin{itemize}
\item Se implementará utilizando Django.
\item Se añadirá una nueva entrada en el formulario para elegir manualmente el recurso para la url acortada. Por lo tanto, en el recurso ``/'' invocado mediante POST, incluirá una qs que tenga campos \texttt{url} y \texttt{short}.
Así, por ejemplo, si se quiere acortar \texttt{http://gsyc.urjc.es} con el nombre de recurso \texttt{gsyc}, y la aplicación está en el puerto 1234 de la máquina ``localhost'', se invocará (mediante POST) la URL
\texttt{https://localhost:1234/}
y en el cuerpo de esa petición HTTP irá la \texttt{qs}
\verb|url=https://gsyc.urjc.es&short=gsyc|
Normalmente, esta invocación POST se realizará rellenando el formulario que ofrece la aplicación.
Como respuesta, la aplicación devolverá (en el cuerpo de la respuesta HTTP) una página HTML con el formulario, y la lista de URLs acortadas hasta el momento para este navegador, incluyendo esta.
\item Además si el recurso para la url acortada está vacío, se deberá acortar mediante un número entero que irá aumentando un valor de manera secuencial.
Así, por ejemplo, si se quiere acortar \texttt{http://gsyc.urjc.es} con el nombre de recurso vacío, y la aplicación está en el puerto 1234 de la máquina ``localhost'', se invocará (mediante POST) la URL
\texttt{https://localhost:1234/}
y en el cuerpo de esa petición HTTP irá la \texttt{qs}
\verb|url=https://gsyc.urjc.es&short=|
Y se eligirá para acortar el número ``1'', por lo que la url acortada sería \texttt{https://localhost:1234/1}
Seguidamente si se quiere acortar \texttt{http://www.urjc.es} con el nombre de recurso vacío de nuevo, se eligirá para acortar el número ``2'' por lo que la url acortada sería \texttt{https://localhost:1234/2}
Así sucesivamente siempre y cuando el formulario para el nombre de recurso este vacío.
\item Tendrá que almacenar la información relativa a las URLs que acorta en una base de datos, de forma que aunque la aplicación sea rearrancada, las URLs acortadas sigan funcionando adecuadamente.
\item Utilizará plantillas, de manera que el código Python y el HTML estarán separados.
\end{itemize}
Repositorio de partida: \\
\url{https://gitlab.eif.urjc.es/cursosweb/2023-2024/mini-2-acortadora}
\newpage
%%-----------------------------------------------------------------------------
%%-----------------------------------------------------------------------------
%%-----------------------------------------------------------------------------
\section{Ejercicios 01: Conceptos básicos de aplicaciones web}
%%-----------------------------------------------------------------------------
%%-----------------------------------------------------------------------------
\subsection{Web 2.0}
\label{subsec:web-20}
\textbf{Enunciado:}
Seguramente has oído hablar muchas veces de la ``web 2.0''. ¿Qué es lo que significa esta expresión? Si puedes, cita referencias en la Red al respecto.
%%-----------------------------------------------------------------------------
%%-----------------------------------------------------------------------------
\subsection{Diferencias entre ``lado servidor'' y ``lado navegador''}
\label{subsec:appweb-servidor-navegador}
\textbf{Enunciado:}
Cuando hablamos de aplicaciones web, podemos estar hablando de ``aplicaciones web del lado del servidor'', ``aplicaciones web del lado del navegador'' o ``aplicaciones mixtas'' (una parte está del lado del servidor, otra del lado del cliente). ¿Qué son ``aplicacione web en el lado del servidor'' y ``aplicaciones web en el lado del cliente''? ¿Qué tienen en común, qué tienen que las diferencia?
%%-----------------------------------------------------------------------------
%%-----------------------------------------------------------------------------
\subsection{Última búsqueda}
\label{subsec:ultima-busqueda}
\textbf{Enunciado:}
¿Cómo mostrar la última búsqueda en un buscador?
Se quiere que un cierto buscador web muestre a sus usuarios la última búsqueda que hicieron en él. Para ello, se utilizarán cookies. Son relevantes tres interacciones HTTP: la primera, en la que el navegador pide la página HTML con el formulario de búsquedas, la segunda, en la que el navegador envía la cadena de búsqueda que el usuario ha escrito en el navegador, y la tercera, que se realizará en cualquier momento posterior, en la que el navegador vuelve a pedir la página con el formulario de búsquedas, que ahora se recibe anotada con la cadena de la última búsqueda. Se pide indicar dónde van las cookies, cómo son éstas, y cómo solucionan el problema.
\textbf{Solución:}
Se puede hacer utilizando identificador de sesión en las cookies. Pero también es posible hacerlo sin que el servidor (el buscador) tenga que almacenar todos los identificadores de sesión junto con la última búsqueda realizada, lo que tiene varias ventajas.
Para identificador de sesión, basta con un número aleatorio grande que se almacena en la cookie. La cookie la envía el buscador al navegador en la respuesta al HTTP GET que se realiza para obtener la página del buscador. Luego, esa cookie va en cada POST que hace el navegador (para realizar una nueva búsqueda). Si no se quiere que el buscador almacena la última pregunta para cada sesión, se puede enviar la propia búsqueda en la cookie.
\textbf{Discusiones relacionadas:}
\begin{itemize}
\item Ventajas y desventajas de utilizar identificadores de sesión, o de almacenar las preguntas en cookies en el navegador.
\item ¿Serviría el mismo esquema para un servicio de banca electrónica? (en lugar de ``recordar'' la última pregunta, se quiere recordar qué usuario se autenticó.
\item Cómo implementarlo usando el identificador de usuario y la contraseña en la cookie. Implicaciones para la seguridad. El problema de la salida de la sesión.
\end{itemize}
%%--------------------------------------------------------------------
%%--------------------------------------------------------------------
\subsection{Espía a tu navegador (Firefox Developer Tools)}
\label{subsec:firefox-devel}
\textbf{Enunciado:}
El navegador hace una gran cantidad de tareas interesantes para esta asignatura. Es muy útil poder ver cómo lo hace, y aprender de los detalles que veamos. De hecho, también, en ciertos casos, se puede modificar su comportamiento. Para todo esto, se pueden usar herramientas específicas. En nuestro caso, vamos a usar las ``Firefox Developer Tools'', que vienen ya preinstaladas en Firefox.
El ejercicio consiste en:
\begin{itemize}
\item Ojear las distintas herramientas de Firefox Developer Tools.
\item Utilizarlas para ver la interacción HTTP al descargar una página web real.
\item Utilizarlas para ver el árbol DOM de una página HTML real.
\end{itemize}
Más adelante, lo utilizaremos para otras cosas, así que si quieres jugar un rato con lo que permiten hacer estas herramientas, mucho mejor.
\textbf{Referencias}
Sitio web de Firefox Developer Tools: \\
\url{https://developer.mozilla.org/en/docs/Tools}
%%--------------------------------------------------------------------
%%--------------------------------------------------------------------
\subsection{Espía a tu navegador (Firebug)}
\label{subsec:firebug}
\textbf{Enunciado:}
El navegador hace una gran cantidad de tareas interesantes para esta asignatura. Es muy útil poder ver cómo lo hace, y aprender de los detalles que veamos. De hecho, también, en ciertos casos, se puede modificar su comportamiento. Para todo esto, se pueden usar herramientas específicas. En nuestro caso, vamos a usar el módulo ``Firebug'' de Firefox (también disponible para otros navegadores).
El ejercicio consiste en:
\begin{itemize}
\item Instalar el módulo Firebug en tu navegador
\item Utilizarlo para ver la interacción HTTP al descargar una página web real.
\item Utilizarlo para ver el árbol DOM de una página HTML real.
\end{itemize}
Más adelante, lo utilizaremos para otras cosas, así que si quieres jugar un rato con lo que permite hacer Firebug, mucho mejor.
\textbf{Referencias}
Sitio web de Firebug: \url{https://getfirebug.com/}
%%-----------------------------------------------------------------------------
%%-----------------------------------------------------------------------------
\subsection{Explora tus cookies}
\label{subsec:explora-cookies}
\textbf{Enunciado:}
En este ejercicio vamos a ver las cookies que intercambia nuestro navegador con un servidor simple. El servidor que vamos a usar es \verb|cookies-server-6.py| (en la carpeta \verb|Python-Web/cookies|). Ejecuta el servidor, y luego, utilizando las herramientas de desarrollador de Firefox (ver ejercicio~\ref{subsec:firefox-devel}, observa las cookies que se intercambian entre este servidor y el navegador. En concreto, carga en el navegador la página principal del servidor, escribe algo en el formulario que te aparecerá, y contesta a este ejercicio escribiendo las cookies que observes en la interacción que se produce cuando le das al botón ``Submit'' para enviar al servidor el texto que has escrito.
Cuando lances el servidor, indicarás en qué puerto TCP escuchará (que tendrá que estar libre en la máquina donde se lance). Por ejemplo, para lanzarlo escuchando en el puerto 8000, usarás la línea:
\begin{verbatim}
python3 cookies-server-6.py -p 8000
\end{verbatim}
En el navegador, tendrás que indicar la url correspondiente al puerto que hayas indicado. Por ejemplo, para acceder al servidor lanzado en el puerto 8000, la url será \url{http://localhost:8000}.
%%-----------------------------------------------------------------------------
%%-----------------------------------------------------------------------------
\subsection{Explora tus cookies (2)}
\label{subsec:explora-cookies-2}
\textbf{Enunciado:}
Vamos a explorar las diferencias entre dos programas que tratan de ``recordarte'' lo último que escribiste en un formulario. Ambos son servidores HTTP, y están en el directorio \verb|Python-Web/cookies| (en el repositorio de código de la asignatura), y son \verb|cookies-server-8.py| y \verb|cookies-server-9.py|. El ejercicio consiste en ejecutar cada uno de ellos de esta forma:
\begin{itemize}
\item Lanza el programa servidor que vas a probar.
\item En el navegador, carga la página correspondiente al recurso principal de ese servidor.
\item Borra las cookies que pueda haber para ese servidor.
\item Recarga la página que tienes en el navegador
\item En el formulario que tienes en la página, escribe ``Primero'', y envíalo al servidor. Llamaremos al resultado de este envío (la página que muestre el navegador al recibir la respuesta del servidor ``Página~1''.
\item En el formulario que tienes ahora en la Página~1, escribe ``Segundo'', y vuelve a enviarlo al servidor. Llamaremos al resultado de este envío (la página que muestre el navegador al recibir la respuesta del servidor ``Página~2''.
\item En el formulario que tienes ahora en la Página~2, escribe ``Tercero'', y vuelve a enviarlo al servidor. Llamaremos al resultado de este envío (la página que muestre el navegador al recibir la respuesta del servidor ``Página~3''.
\end{itemize}
Compara qué ves en Página~1, Página~2 y Página~3 en los dos casos (cuando lanzas cada uno de los dos servidores, y sigues el proceso con ellos). Trata de explicar lo que ocurre viendo en el navegador las cookies que envía el servidor en cada uno de los casos. A continuación, trata de explicarlo mirando el código de los dos servidores. Puedes utilizar la herramienta \verb|diff| para ver las diferencias en el código de ambos, si eso te ayuda.
Escribe como respuesta:
\begin{itemize}
\item Las diferencias que observes entre Página~1, Página~2 y Página~3 (descritas, acompañadas de capturas de pantalla si lo ves útil).
\item La explicación que hayas podido encontrar a las diferencias mirando las cookies en el navegador.
\item La explicación que hayas podido encontrar a las diferencias mirando el código de los dos servidores.
\end{itemize}
%%-----------------------------------------------------------------------------
%%-----------------------------------------------------------------------------
\subsection{Servidores que recuerdan}
\label{subsec:servidores-recuerdan}
\textbf{Enunciado:}
En el directorio \verb|Python-Web/cookies| (en el repositorio de código de la asignatura) puedes encontrar los programas \verb|content-server-1.py| y \verb|content-server-2.py|. Ambos utilizan cookies de datos para ``recordar'' el último texto que se introdujo en el formulario que proporciona el servidor. El primero, utiliza GET para enviar al servidor el contenido del formulario, y el segundo utiliza POST.
Este ejercicio consiste en entender el código de ambos programas, y escribir otros dos, \verb|content-server-3.py| y \verb|content-server-4.py|, que hagan lo mismo, pero utilizando cookies de sesión (que identifican el navegador, y utilizan el identificador para buscar el último contenido del formulario en un diccionario que mantienen).
%%-----------------------------------------------------------------------------
%%-----------------------------------------------------------------------------
\subsection{Servicio horario}
\label{subsec:ej-servicio-horario}
\textbf{Enunciado:}
Queremos construir una aplicación web que cuando se consulta, devuelva la hora actual. Además, queremos que cuando se consulta por segunda vez, devuelva la hora actual y la hora en que se consultó por última vez. Explicar cómo se pueden usar cookies para conseguirlo.
\textbf{Enunciado avanzado:}
Igual que el anterior, pero se quiere que se muestre no sólo la hora en que se consultó por última vez, sino las horas de todas las consultas previas (además de la hora actual).
%%-----------------------------------------------------------------------------
%%-----------------------------------------------------------------------------
\subsection{Última búsqueda: números aleatorios o consecutivos}
\label{subsec:ultima-busqueda-aleconsec}
\textbf{Enunciado:}
En el ejercicio ``Última búsqueda'' (ejercicio~\ref{subsec:ultima-busqueda}) una de las soluciones pasa por usar cookies con identificadores de sesión. En principio, se han propuesto dos posibilidades para esos identificadores:
\begin{itemize}
\item Números enteros aleatorios sobre un espacio de números grande (por ejemplo entre 0 y $2^{128}-1$)
\item Números enteros consecutivos, comenzando por ejemplo por 0.
\end{itemize}
Comenta cuál de las dos soluciones te parece mejor, y si crees que alguna de ellas no sirve para resolver el problema. En ambos casos, indica las razones que te llevan a esa conclusión
%%------------------------------------------------------------------------------
%%------------------------------------------------------------------------------
\subsection{Cookies en tu navegador}
\label{subsec:cookies-navegador}
\textbf{Enunciado:}
Busca dónde tiene tu navegador accesible la lista de cookies que mantiene, y mírala. ¿Cuántas cookies tienes? ¿Qué sitio te ha puesto más cookies? ¿Cuál es la cookie más antigua que tienes? Explica también qué navegador usas (nombre y versión), desde cuándo más o menos, y cómo has podido ver las cookies en él.
%%------------------------------------------------------------------------------------
%%------------------------------------------------------------------------------------
\subsection{Cookies en tu navegador avanzado}
\label{subsec:cookies-navegador-2}
\textbf{Enunciado:}
Con el módulo adecuado, pueden editarse las cookies del navegador, lo que permite manejarlas con gran flexibilidad. Utiliza uno de estos módulos (por ejemplo, Cookie Quick Manager para Firefox) para manipular las cookies que tenga tu navegador. Utilízalo para ``traspasar'' una sesión de un navegador a otro. Por ejemplo, puedes buscar las cookies que te autentican con un servicio (el campus virtual, una red social en la que tengas cuenta, etc.), guardarlas en un fichero, transferirlas a otro ordenador con otro navegador, e instalarlas en él, para comprobar cómo puedes continuar con la sesión desde él.
\textbf{Referencias}
Cookie Quick Manager: \url{https://addons.mozilla.org/en-US/firefox/addon/cookie-quick-manager/}
%%--------------------------------------------------------------------------
%%--------------------------------------------------------------------------
\subsection{Sumador simple con varios navegadores}
\label{subsec:sumador-simple-varios}
\textbf{Enunciado:}
Igual que el ejercicio ``Sumador simple'' (\ref{subsec:sumador-simple}), pero ahora puede haber varios navegadores invocando la aplicación web. Se supone que los navegadores no se interfieren (esto es, uno completa una suma antes de que otro la empiece).
\textbf{Comentario:}
No hacen falta modificaciones al código del ejercicio ``Sumador simple'' (\ref{subsec:sumador-simple}).
%%------------------------------------------------------------------------------------
%%------------------------------------------------------------------------------------
\subsection{Sumador simple con varios navegadores intercalados}
\label{subsec:sumador-simple-varios-intercalados}
\textbf{Enunciado:}
Igual que``Sumador simple con varios navegadores'' (\ref{subsec:sumador-simple-varios}), pero ahora un navegador puede comenzar una suma en cualquier momento, incluyendo momentos en los que otro navegador no la haya terminado.
\textbf{Comentarios:}
En una primera versión, se implementa con una cookie simple que incluye el primer operando, de forma que el servidor de aplicaciones no tiene que almacenar los operandos ni las cookies.
En una segunda versión, se utiliza una cookie de sesión más clásica, con un entero aleatorio, y se almacena el estado en un diccionario indexado por ese entero.
%%------------------------------------------------------------------------------------
%%------------------------------------------------------------------------------------
\subsection{Sumador simple con rearranques}
\label{subsec:sumador-simple-rearranques}
\textbf{Enunciado:}
Igual que el ejercicio ``Sumador simple con varios navegadores intercalados'' (\ref{subsec:sumador-simple-varios-intercalados}), pero ahora desde que el navegador inicia la suma hasta que la completa, puede haberse caído la aplicación web.
\textbf{Comentario:}
La aplicación web tendrá que almacenar su estado en almacenamiento estable. Hay que detectar cuál es ese estado, y almacenarlo en un fichero, en una base de datos, etc.
%%--------------------------------------------------------------------------
%%--------------------------------------------------------------------------
\subsection{Contador simple}
\label{subsec:contador-simple}
\textbf{Enunciado:}
Construir una aplicación web que funcione como contador inverso. Ofrecerá un recurso que, cuando sea invocado mediante un método GET, devolverá un número entero. La primera vez que se invoque, el número devuelto será un 5. Cuando se le invoque sucesivamente, el número obtenido se irá decrementando en uno (4, 3, 2...). Cuando se haya obtenido un 0, el siguiente número será de nuevo el 5 (esto es, el contador funciona como un contador inverso cíclico).
\textbf{Comentario:}
Es importante hacer énfasis en la solución en la estructura de la aplicación, tratando de estructurar el código de forma que las diferentes acciones que hará la aplicación web queden claras.
%%--------------------------------------------------------------------------
%%--------------------------------------------------------------------------
\subsection{cURL básico}
\label{subsec:curl-basico}
\textbf{Enunciado:}
Prueba el ejercicio ``Contador simple'' (\ref{subsec:contador-simple}) con el programa \verb|curl|. Utilizalo para ver el documento que se recibe de tu servidor, para ver las cabeceras que te envía, para ver tanto cabeceras (de ida y vuelta) como cabeceras...
\textbf{Materiales:}
\begin{itemize}
\item \href{https://linuxacademy.com/guide/13852-understanding-curl-and-http-headers/}{Understanding CURL and HTTP Headers} (tutorial)
\item \href{https://curl.haxx.se/}{cURL} (sitio web)
\item \href{https://curl.haxx.se/book.html}{Everything curl} (libro)
\end{itemize}
\textbf{Solución:}
\begin{verbatim}
curl -XGET http://localhost:1234/
curl -XGET -I http://localhost:1234/
curl -XGET -Iv http://localhost:1234/
\end{verbatim}
%%--------------------------------------------------------------------------
%%--------------------------------------------------------------------------
\subsection{Distinto contenido según navegador}
\label{subsec:contador-simple-navegador}
\textbf{Enunciado:}
Realiza una versión del ejercicio ``Contador simple'' (\ref{subsec:contador-simple}) que sirva distinto contenido según el navegador que lo pida. En particular, si el navegador que pide una página es Firefox, se responderá con una página HTML tal y como se hace en el ejercicio ``Contador simple''. Pero si la petición la hace \verb|curl|, se responderá con un documento de texto plano sólo con el resultado.
\textbf{Materiales:}
\begin{itemize}
\item Cabecera User Agent (MDN): \\
\url{https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent}
\end{itemize}
%%--------------------------------------------------------------------------
%%--------------------------------------------------------------------------
\subsection{Depurador básico}
\label{subsec:depurador-basico}
\textbf{Enunciado:}
Prueba el ejercicio ``Contador simple'' (\ref{subsec:contador-simple}) con el depurador de Python, por ejemplo, ejecutándolo desde PyCharm.
%%--------------------------------------------------------------------------
%%--------------------------------------------------------------------------
\subsection{Contador simple con varios navegadores}
\label{subsec:contador-simple-varios}
\textbf{Enunciado:}
Igual que el ejercicio ``Contador simple'' (\ref{subsec:contador-simple}), pero ahora puede haber varios navegadores invocando la aplicación web. Se supone que los navegadores no se interfieren (esto es, uno completa todas sus operaciones con el contador antes de que otro la empiece).
\textbf{Comentario:}
No hacen falta modificaciones al código del ejercicio ``Contador simple'' (\ref{subsec:contador-simple}), si se asume que cuando se invoque el contador, éste puede empezar por cualquier número de su ciclo. Si por el contrario se quiere que comience como ``la primera vez'' (por 5) es preciso detectar que se está sirviendo a un nuevo navegador, y habrá que prever algún mecanismo al respecto.
Puede consultarse la implementación de referencia disponible en
\href{https://github.com/CursosWeb/Code/blob/master/Python-Web/counter/counter-server-1.py}{counter-server-1.py}
%%-------------------------------------------------------------------------
%%-------------------------------------------------------------------------
\subsection{Contador simple con varios navegadores intercalados}
\label{subsec:contador-simple-varios-intercalados}
\textbf{Enunciado:}
Igual que ``Contador simple con varios navegadores'' (\ref{subsec:contador-simple-varios}), pero ahora un navegador puede comenzar a trabajar con el contador en cualquier momento, incluyendo momentos en los que otro navegador no haya terminado aún.
\textbf{Comentarios:}
En una primera versión, se implementa con una cookie simple que incluye el número que ha servido el contador de forma que la aplicación no tiene que almacenar el valor del contador para cada navegador.
En una segunda versión, se utiliza una cookie de sesión más clásica, con un entero aleatorio, y se almacena el estado del contador correspondiente en un diccionario indexado por ese entero.
En una tercera versión, se podría añadir una operación para crear un contador único para cada navegador, con un nombre de recurso propio. Cada navegador conocería su recurso, y sólo utilizaría ese. Se puede evitar que un navegador utilice un recurso que no le corresponde haciendo que su nombre no sea fácilmente descubrible.
Puede consultarse la implementación de referencia disponible en
\href{https://github.com/CursosWeb/Code/blob/master/Python-Web/counter/counter-server-2.py}{counter-server-2.py}
%%------------------------------------------------------------------------------------
%%------------------------------------------------------------------------------------
\subsection{Contador simple con rearranques}
\label{subsec:contador-simple-rearranques}
\textbf{Repositorio plantilla (para entrega):} \\
\url{https://gitlab.etsit.urjc.es/cursosweb/2023-2024/contador-simple-rearranques}
\textbf{Enunciado:}
Igual que el ejercicio ``Contador simple con varios navegadores intercalados'' (\ref{subsec:contador-simple-varios-intercalados}), pero ahora desde que el navegador inicia el trabajo con el contador hasta que la completa, puede haberse caído la aplicación web.
\textbf{Comentario:}
La aplicación web tendrá que almacenar su estado en almacenamiento estable. Hay que detectar cuál es ese estado, y almacenarlo en un fichero, en una base de datos, etc.
Puede consultarse la implementación de referencia disponible en
\href{https://github.com/CursosWeb/Code/blob/master/Python-Web/counter/counter-server-3.py}{counter-server-3.py} y
\href{https://github.com/CursosWeb/Code/blob/master/Python-Web/counter/counter-server-4.py}{counter-server-4.py}.
%%-----------------------------------------------------------------------------
%%-----------------------------------------------------------------------------
\subsection{Traza de historiales de navegación por terceras partes}
\label{subsec:navegacion-terceras-partes}
Cuando un navegador realiza un GET sobre una página web HTML lanza a continuación, de forma automática, otras operaciones GET sobre los elementos cargables automáticamente que contenga esa página, como por ejemplo, las imágenes empotradas. Cada vez que se realiza uno de estos GET, se pueden recibir una o más cookies de los servidores que las sirven (y que en general pueden ser diferentes del que sirve la página HTML).
De esta forma, sirviendo imágenes para diferentes páginas HTML en diferentes sitios, una tercera parte puede trazar historiales de navegación, ligándolos a identificadores únicos. ¿Cómo?
Además, si la tercera parte en cuestión tiene acceso a información de un sitio web que permita identificar identidades, esos historiales pueden también ser ligados a identidades. ¿Cómo?
\textbf{Comentarios:}
La liga con identificadores únicos se puede lograr de varias formas, Por ejemplo se puede incluir en cada página HTML a trazar una imagen con nombre único, todas servidas por la tercera parte. La primera vez que sirve una imagen a un navegador dado, le envía también una cookie con identificador único. Todas las peticiones de imagen que se reciban serán escritas en un historial, junto con el identificador único de la cookie.
Para poder ligar este historial a una identidad, basta con que, en un servidor que ha identificado una identidad, sirva una imagen de la tercera parte con un nombre que permita posteriormente ligarlo a la identidad.
%%-----------------------------------------------------------------------------
%%-----------------------------------------------------------------------------
\subsection{Trackers en páginas web}
\label{subsec:trackers-paginas-web}
Instala algún \emph{plug-in} similar a Lightbeam para tu navegador. Este \emph{plug-in} permite detectar todos los sitios web que se acceden al descargar una página, incluyendo los forzados por ``trackers'' (objetos incluidos en una página web para trazar a quienes descargan esa página). Utilízalo para encontrar páginas web con muchos trackers. Una vez lo hayas hecho, indica las dos páginas (de sitios distintos) en las que hayas encontrado más trackers.
\textbf{Referencias}
\begin{itemize}
\item Sitio web de Lightbeam (sin mantenimiento, no funciona en versiones modernas de navegadores): \\
\url{https://www.mozilla.org/lightbeam/}
\item GreenBeam para Firefox: \\
\url{https://addons.mozilla.org/en-US/firefox/addon/greenbeam/}
\item Thunderbeam-Lightbeam para Chrome: \\
\url{https://chrome.google.com/webstore/detail/thunderbeam-lightbeam-for/hjkajeglckopdkbggdiajobpilgccgnj}
\end{itemize}
%%-----------------------------------------------------------------------------
%%-----------------------------------------------------------------------------
\subsection{Trackers en páginas web (Ghostery)}
\label{subsec:trackers-paginas-web-2}
Instala el \emph{plug-in} Ghostery para tu navegador. Este \emph{plug-in} permite detectar ``trackers'', objetos incluidos en una página web para trazar a quienes descargan esa página. Utilízalo para encontrar páginas web con muchos trackers. Una vez lo hayas hecho, indica las dos páginas (de sitios distintos) en las que hayas encontrado más trackers.
\textbf{Referencias}
Sitio web de Ghostery: \url{http://www.ghostery.com/}
%%-----------------------------------------------------------------------------
%%-----------------------------------------------------------------------------
\subsection{Protección contra trackers en el navegador}
\label{subsec:trackers-navegador}
Estudia las capacidades de protección contra trackers de tu navegador. Por ejemplo, en Firefox, están accesibles a partir del ``escudo'' que aparece junto a la barra de enlaces. Trata de entenderlas en el contexto de lo que has aprendido sobre cookies y otras formas de trazar historiales de navegación.
\textbf{Referencias}
Información sobre protección ante trackers de Firefox: \\
\url{https://support.mozilla.org/en-US/kb/enhanced-tracking-protection-firefox-desktop}
%%-----------------------------------------------------------------------------
\subsection{Transplante de cookies}
\label{subsec:transplante-cookies}
En el ejercicio ``Explora tus cookies (2)'' (ejercicio~\ref{subsec:explora-cookies-2}) hemos explorado cómo se comportan las cookies con dos aplicaciones web simples. En este ejercicio se te pide que elijas una cualquiera de estas dos aplicaciones, y pruebes a transplantar las cookies que tenga un navegador después de haberla usado, a otro navegador diferente. Por ejemplo, puedes transplantarlas de Chrome a Firefox, o de un navegador que tengas en tu ordenador a un Firefox en un ordenador del laboratorio. Para responder al ejercicio, explica cómo has hecho para transplantar las cookies, y qué has observado al acceder a la aplicación desde el navegador al que las has transplantado.
%%-----------------------------------------------------------------------------
\subsection{Transplante de cookies 2}
\label{subsec:transplante-cookies2}
En el ejercicio ``Contador Simple'' (ejercicio~\ref{subsec:contador-simple}) hemos explorado cómo realizar un contador general, que descuenta según cada petición recibida. En este ejercicio se pide modificar el código para que el contador sea particular de cada navegador (con una cookie). De esta manera, cada navegador contará con un contador particular, que sólo se decrementará con cada visita.
Finalmente, se puede que se pruebe a transplantar las cookies que tenga un navegador después de haberla usado, a otro navegador diferente. Por ejemplo, puedes transplantarlas de Chrome a Firefox, o de un navegador que tengas en tu ordenador a un Firefox en un ordenador del laboratorio.
%%-----------------------------------------------------------------------------
%%-----------------------------------------------------------------------------
%%-----------------------------------------------------------------------------
\section{Ejercicios 02: Servicios web que interoperan}
%%-----------------------------------------------------------------------------
\subsection{Arquitectura escalable}
\label{subsec:arq-escalable}
\textbf{Enunciado:}
Diseñar una arquitectura para una aplicación distribuida que cumpla las siguientes condiciones:
\begin{itemize}
\item Puede ser usada por millones de usuarios simultáneamente.
\item Hay miles de equipos de desarrollo trabajando sobre ella. Entre los equipos hay poca comunicación pero no deben tener conflictos entre sí.
\item Cada uno de los equipos podrían extender lo que habían hecho los otros sin que estos lo sepan y sin que la evolución de cada sistema rompiera la integración.
\end{itemize}
\textbf{Comentarios:}
Desde luego, hay otros sistemas, pero el web, entendido en sentido amplio, es uno que cumple bien estos requisitos.
%%-----------------------------------------------------------------------------
\subsection{Arquitectura distribuida}
\label{subsec:arq-distribuida}
\textbf{Enunciado:}
Diseñar una arquitectura para una aplicación distribuida que cumpla las siguientes condiciones:
\begin{itemize}
\item Pueda gestionar elementos en mi casa desde remoto, en particular, mi comida. Por tanto, tendrá que gestionar los alimentos que se encuentran en la nevera, la despensa, el bol de frutas, etc.
\item Pueda interactuar tanto con máquinas como con humanos
\item Sea lo más sencilla posible
\item Sea escalable
\end{itemize}
En particular, usando REST, define algunos recursos, y las operaciones que se podrían hacer sobre ellos. Explica también qué necesitaría para poder interoperar con los recursos correspondientes, por ejemplo, a la casa de tus amigos.
\textbf{Comentarios:}
Desde luego, hay muchas maneras de hacerlo y eso favorecerá el debate.
Una primera idea es modelar los elementos como objetos (la nevera, los alimentos, etc.) y hacerlo llegar de alguna manera al otro lado de la red, donde está mi portátil (esta es una solución que siguen muchos web services, o incluso CORBA). Hay que entender que esto hará que en el lado del portátil tengamos que conocer cómo funcionan los elementos (sus atributos y sus métodos). Es como tener que aprender el manual de instrucciones (los verbos) para cada cacharro que tengamos en la cocina.
Al ver esta solución, nos damos cuenta de que contamos en el otro lado con sustantivos. Éstos tienen una localización única, que especificamos mediante una URL. Asimismo, existe la URN, que permite especificar unívocamente un elemento según su nombre, pero se ha de tener en cuenta de que puede haber un URN para muchos elementos (es como el ISBN, que hay uno para toda la edición, o sea para muchos libros). Dado la URL localizamos un URN de manera unívoca.
Mientas, en el otro lado (en el cliente) tendremos un número mínimo de acciones (los verbos). Vemos el primero: GET. Éste no obtiene el sustantivo, sino una representación del mismo. Los sustantivos son recursos. Y estos recursos pueden venir expresados de varias maneras. Así, por ejemplo, si pedimos manzanas desde un portátil la representación podría ser una imagen muy detallada; para el móvil, la imagen será más pequeña; y si el que lo pide es una máquina, podría ser un XML. Vemos los demás métodos: PUT, POST y DELETE.
Vistos los métodos discutimos si cambian el estado (vemos que sólo GET no lo hace) y si el resultado de realizar varios consecutivos es igual a hacerlo una vez (lo que llamamos idempotencia, vemos que sólo POST no lo es).
Introducimos el concepto de elemento y colección de elementos (cuando pedimos una colección, nos da un listado de los elementos que contiene; este listado contiene enlaces a los mismos) y qué pasa cuando aplicamos un método a cada uno. Hacemos especial hincapié en la diferencia entre PUT y POST.
Introducimos el concepto de REST y sus reglas. Hay varias las hemos visto ya: URLs, enlaces, representaciones y métodos. Nos falta por ver que las comunicaciones son sin estado. Los recursos pueden tenerlo, pero no la comunicación. Discutimos qué significa esto con respecto a lo que hemos visto en la asignatura hasta ahora, en particular con respecto a las sesiones (y las cookies).
Finalmente discutimos porque la web no es así, si en realidad los diseñadores de HTTP habían diseñado el protocolo para que todo fuera REST. Comentamos que con los navegadores sólo podemos hacer GETs y POSTs (y contamos que podemos utilizar los demás métodos mediante plug-ins como Poster (ver ejercicio~\ref{subsec:inst-poster}). Mostramos que, más allá de los navegadores, ya estamos en disposición de crear programas para interactuar con servidores REST, de manera que podemos comunicar máquinas entre sí siguiendo estas reglas. Discutimos las ventajas de este enfoque en esos casos.
%%-----------------------------------------------------------------------------
\subsection{Lista de la compra}
\label{subsec:lista-compra}
\textbf{Enunciado:}
Vamos a diseñar una API HTTP para un servicio que permite guardar una lista de la compra. Supongamos que esta lista está compuesta únicamente por los items que quiero comprar en un momento dado (zanahorias, yogures, etc.) y un número natural para cada item que tengo, que expresa la cantidad que quiero comprar. Por ejemplo, en un momento dado, la lista podría ser:
\begin{itemize}
\item Zanahorias: 5
\item Yogures: 4
\item Leche: 2
\end{itemize}
Puede haber items en la lista de la compra con valor 0, si se encuentra que es útil por algún motivo.
Las operaciones que permitirá la API del servicio son: consultar la lista, añadir un item (con su correspondiente cantidad) a la lista, modificar la cantidad de un item en la lista, y borrar un item de la lista.
Se pide diseñar una API HTTP para esta aplicación (servicio) web, identificando cuáles son los recursos relevantes, las operaciones HTTP válidas sobre ellas, y describiendo la semántica de cada una de ellas.
Podemos imaginar que el servicio web va a ser usado, por ejemplo, desde una aplicación en el móvil, que podrá hacer GET, PUT, POST y DELETE (usando HTTP). Cada vez que quiero apuntar o borrar algo de la lista de la compra, o quiero consultar la lista, utilizo la app del móvil para acceder, mediante HTTP, al servicio de lista de la compra.
%%-----------------------------------------------------------------------------
\subsection{Listado de lo que tengo en la nevera}
\label{subsec:contenido-nevera}
\textbf{Enunciado:}
Este es un ejercicio muy similar a ``Lista de la compra'' (\ref{subsec:lista-compra}). Vamos a diseñar una API REST para una aplicación web que mantenga la lista de lo que tengo en la nevera. El tipo de lista será el mismo que se indica para en el ejercicio de la lista de la compra, pero ahora trataremos de que la API cumpla los principios REST.
\textbf{Comentarios:}
Hay muchas soluciones posibles para este problema, que sobre todo pretende que se reflexione sobre las características que hacen de una interfaz HTTP una interfaz REST. Pero en cualquier caso, como mínimo hay que definir cuáles serán los recursos (y sus nombres), las operaciones sobre cada uno de ellos, y un breve comentario sobre su funcionamiento.
Una posible solución sería: \\
\begin{tabular}{l|l|p{10cm}}
Recurso & Método & Descripción \\ \hline \hline
/ & GET & Lista de items en la nevera (enlaces a recursos) \\
& POST & Crea un nuevo item, \verb|item=xx&cantidad=yy| \\
/[item] & GET & Obten el valor (número) del alimento ``item'' \\
& PUT & Actualiza el valor del alimento ``item'' \\
& DELETE & Borra el item (elimina el recurso) \\
\end{tabular}
Esta interfaz HTTP podría usarse desde la aplicación como se ve en los siguiente ejemplos.
La primera vez que se introducen zanahorias (supongamos que se introducen 5):
\begin{itemize}
\item Petición (para ver si hay zanahorias):
\begin{verbatim}
GET / HTTP/1.1
\end{verbatim}
\item Respuesta:
\begin{verbatim}
HTTP/1.1 200 OK
<a href="/leche"></a>
<a href="/chorizo"></a>
\end{verbatim}
\item Petición (para crear el recurso para las zanahorias):
\begin{verbatim}
POST / HTTP/1.1
item=zanahorias&cantidad=5
\end{verbatim}
\item Respuesta:
\begin{verbatim}
HTTP/1.1 200 OK
<a href="/chorizo"></a>
\end{verbatim}
\end{itemize}
Si sacamos 3 zanahorias:
\begin{itemize}
\item Petición (para ver cuántas zanahorias hay):
\begin{verbatim}
GET /zanahorias HTTP/1.1
\end{verbatim}
\item Respuesta:
\begin{verbatim}
HTTP/1.1 200 OK
5
\end{verbatim}
\item Petición (para actualizar al nuevo número de zanahorias):
\begin{verbatim}
PUT /zanahorias HTTP/1.1
2
\end{verbatim}
\item Respuesta:
\begin{verbatim}
HTTP/1.1 200 OK
2
\end{verbatim}
\end{itemize}
Si sacamos otras 2 zanahorias:
\begin{itemize}
\item Petición (para ver cuántas zanahorias hay):
\begin{verbatim}
GET /zanahorias HTTP/1.1
\end{verbatim}
\item Respuesta:
\begin{verbatim}
HTTP/1.1 200 OK
2
\end{verbatim}
\item Petición (para eliminar el recurso, porque quedaría a cero):
\begin{verbatim}
DELETE /zanahorias HTTP/1.1
\end{verbatim}
\item Respuesta:
\begin{verbatim}
HTTP/1.1 200 OK
\end{verbatim}
\end{itemize}
%%-----------------------------------------------------------------------------
\subsection{Sumador simple versión REST}
\label{subsec:sumador-simple-rest}
\textbf{Enunciado:}
Desarrollar una versión RESTful de ``Sumador simple'' (ejercicio~\ref{subsec:sumador-simple}). ¿Plantea problemas si se usa simultáneamente desde varios navegadores? ¿Plantea problemas si se cae el servidor entre dos invocaciones por parte del mismo navegador?
\textbf{Comentarios:}
Hay varias formas de hacer el diseño, pero por ejemplo, cada sumando podría ser un recurso, y el resultado obtenerse en un tercero (o bien como respuesta al actualizar el segundo sumando). Cada suma podría también realizarse en un espacio de nombres de recurso distinto (con su propio primer sumando, segundo sumando y resultado).
%%-----------------------------------------------------------------------------
\subsection{Calculadora simple versión REST}
\label{subsec:calc-simple-rest}
\textbf{Enunciado:}
Realizar una calculadora de las cuatro operaciones aritméticas básicas (suma, resta, multiplicación y división), siguiendo los principios REST, a la manera del sumador simple versión REST (ejercicio~\ref{subsec:sumador-simple-rest}).
\textbf{Comentarios:}
Este ejercicio, más que para proponer una solución concreta, está diseñado para debatir sobre las posibles soluciones que se le podrían dar. Por ejemplo, tenemos primero la versiones donde se supone un único usuario:
\begin{itemize}
\item Versión con un recurso por tipo de operación (``/suma'', ``resta'', etc.). Se actualiza con PUT, que envía los operandos (ej: 4,5), se consulta con GET, que devuelve el resultado (ej: 4+5=9).
\item Versión con un único recurso, ``/operacion''. Se actualiza con PUT, que envía en el cuerpo la operación (ej: 4+5), se consulta con GET, que devuelve el resultado (ej: 4+5=7).
\item Versión actualizando por separado los elementos de la operación, con un único recurso ``/operacion''. PUT podrá llevar en el cuerpo ``Primero: 4'' o ``Segundo: 5'', o ``Op: +''. Cada uno de ellos actualiza el elemento correspondiente de la operación. GET de ese recurso, devuelve el resultado de la operación con los elementos que tiene en este momento.
\item Versión actualizando por separado los elementos de la operación, con un único recurso ``/operación''. PUT podrá llevar en el cuerpo un número si es la primera o segunda vez que se invoca, un símbolo de operación si es la tercera. GET dará el resultado si se han especificado todos los elementos de la operación, error si no. Es ``menos REST'', en el sentido que guarda más estado en el lado del servidor. Pero cumple los requisitos generales de REST si consideramos que le cliente es responsable de mantener su estado y saber en qué fase de la operación está en cada momento.
\item Versión donde cada elemento se envía con un PUT a un recurso (``/operacion/primeroperando'', ``/operacion/segundooperando'', ``/operacion/signo''), y el resultado se obtiene con ``GET /operacion/resultado''. No es REST, porque el estado del recurso ``/operacion/resultado'' depende del estado de los otros recursos
.
\end{itemize}
También podemos extender el diseño a versiones con varios usuarios:
\begin{itemize}
\item Podría tenerse un identificador para cada operación. ``POST /operaciones'' podría devolver el enlace a una nueva operación creada, como ``/operaciones/2af434ad3''. Cada una de estas sumas se comportaría como las ``sumas con un usuario'' que se han comentado antes. ``DELETE /operaciones/2af434ad3'' destruiría una operación.
\end{itemize}
\textbf{Material:}
\begin{itemize}
\item \texttt{simplecalc.py}: Programa con una posible solución a este ejercicio. Proporciona cuatro recursos ``calculadora'', uno para cada operación matemática (suma, resta, multiplicación, división). Cada calculadora mantiene un estado (operación matemática) que se actualiza con PUT y se consulta con GET.
\item Vídeo que muestra el funcionamiento de \texttt{simplecalc.py} \\
\url{http://vimeo.com/31427714}
\item Vídeo que describe el programa \texttt{simplecalc.py} \\
\url{http://vimeo.com/31430208}
\item \texttt{multicalc.py}: Programa con otra posible solución a este ejercicio. Proporciona un recurso para crear calculadoras (mediante POST). Al crear una calculadora se especifica de qué tipo (operación) es. Cada calculadora mantiene un estado (operación matemática) que se actualiza con PUT y se consulta con GET. Se apoya en las clases definidas en \texttt{simplecalc.py} para implementar las calculadoras.
\item \texttt{webappmulti.py}: Clase que proporciona la estructura básica para los dos programas anteriores (clase raíz de servicio web, de \emph{aplis}, etc.)
\end{itemize}
%%-----------------------------------------------------------------------------
\subsection{Calculadora simple versión REST (Django)}
\label{subsec:calc-simple-rest-django}
\textbf{Repositorio plantilla (para entrega):} \\
\url{https://gitlab.etsit.urjc.es/cursosweb/2022-2023/calculadora-simple-rest-django}
\textbf{Enunciado:}
Realizar el ejercicio~\ref{subsec:calc-simple-rest} usando Django.
\textbf{Comentarios:}
Ver los comentarios del ejercicio~\ref{subsec:calc-simple-rest}.
%%-----------------------------------------------------------------------------
%%-----------------------------------------------------------------------------
\subsection{Cache de contenidos}
\label{subsec:cache-contenidos}
\textbf{Enunciado:}
Vamos a construir una aplicación web que no sólo recibe peticiones de un cliente, sino que también hace peticiones a otros servicios web. El ejercicio consiste en construir una aplicación que, dada una URL (sin ``http://'') como nombre de recurso, devuelve el contenido de la página correspondiente a esa URL. Esto es, si se le pide http://localhost:1234/gsyc.es/ devuelve el contenido de la página http://gsyc.es/. Además, lo guarda en un diccionario, de forma que si se le vuelve a pedir, lo devuelve directamente de ese diccionario.
%Puede usarse como base ``Django cms'' (ejercicio~\ref{subsec:django-cms}), y si se quiere, el módulo estándar de Python ``urllib''.
Puede usarse como base ContentApp, y si se quiere, el módulo estándar de Python urllib.
\textbf{Comentarios:}
Pueden discutirse muchos detalles de esta aplicación. Por ejemplo, cómo gestionar las cabeceras, y en particular las cookies. También, cómo saber si la página ha cambiado en el sitio original antes de decidir volver a bajarla (cabeceras relacionadas con ``cacheable'', peticiones ``HEAD'' para ver fechas, etc.)
Para la implementación de la aplicación sólo se pide lo más básico: no hay tratamiento de cabeceras, y no se vuelve a bajar el original una vez está en la cache.
%%-----------------------------------------------------------------------------
%%-----------------------------------------------------------------------------
\subsection{Cache de contenidos versión Django}
\label{subsec:cache-contenidos-django}
\textbf{Enunciado:}
Construir una aplicación que implemente una cache de contenidos, como la descrita en el ejercicio~\ref{subsec:cache-contenidos}, pero sobre Django.
Puede usarse como base ``Django cms'' (ejercicio~\ref{subsec:django-cms}), y si se quiere, el módulo estándar de Python ``urllib''.
%%-----------------------------------------------------------------------------
%%-----------------------------------------------------------------------------
\subsection{Cache de contenidos anotado}
\label{subsec:cache-contenidos-anotado}
\textbf{Enunciado:}
Construir una aplicación como ``Cache de contenidos'' (ejercicio~\ref{subsec:cache-contenidos}), pero que anote cada página, en la primera línea, con un enlace a la página original, y que incluya también un enlace para ``recargar'' la página (volverla a refrescar a partir del original), otro enlace para ver el HTTP (de ida y de vuelta, si fuera posible) que se intercambió para conseguir la página original, y otro enlace para ver el HTTP de la consulta del navegador y de la respuesta del servidor al pedir esta página (de nuevo si fuera posible).
\textbf{Comentarios:}
Téngase en cuenta que por lo tanto cada página que sirva la aplicación, además de los contenidos HTML correspondientes (obtenidos de la cache o directamente de Internet) tendrá cuatro enlaces en la primera línea:
\begin{itemize}
\item Enlace a la página original.
\item Enlace a un recurso de la aplicación que permita recargar.
\item Enlace a un recurso de la aplicación que permita ver el HTTP que se intercambió con el servidor que tenía la página.
\item Enlace a un recurso de la aplicación que permita ver el HTTP que se intercambió cuando se cargó en cache esa página.
\end{itemize}
Estos enlaces conviene introducirlos en el cuerpo de la página HTML que se va a servir. Así, por ejemplo, si la página que se bajó de Internet es como sigue:
\begin{verbatim}
<html>
<head> ... </head>
<body>
Text of the page
</body>
</html>
\end{verbatim}
Debería servirse anotada como sigue:
\begin{verbatim}
<html>
<head> ... </head>
<body>
<a href="original_url">Original webpage</a>
<a href="/recurso1">Reload</a>
<a href="/recurso2">Server-side HTTP</a>
<a href="/recurso3">Client-side HTTP</a></br>
Text of the page
</body>
</html>
\end{verbatim}
Para poder hacer esto, es necesario localizar el elemento $<body>$ en la página HTML que se está anotando. Hay que tener en cuenta que este elemento puede venir tal cual o con atributos, por ejemplo:
\begin{verbatim}
<body class="all" id="main">
\end{verbatim}
Por eso no basta con identificar dónde está la cadena ``$<body>$'' en la página, sino que habrá que identificar primero dónde está ``$<body$'' y, a partir de ahí, el cierre del elemento, ``$>$''. Será justo después de ese punto donde deberán colocarse las anotaciones. Para encontrar este punto puede usarse el método \texttt{find} de las variables de tipo \emph{string}, o expresiones regulares.
Para que los enlaces que se enlazan desde estas anotaciones funcionen, la aplicación tendrá que atender a tres nuevos recursos para cada página:
\begin{itemize}
\item /recurso1: Recarga de la página en la cache.
\item /recurso2: Devuelve el HTTP con el servidor (que tendrá que estar previamente almacenado en, por ejemplo, un diccionario).
\item /recurso3: Devuelve el HTTP con el navegador (que tendrá que estar previamente almacenado en, por ejemplo, un diccionario).
\end{itemize}
Naturalmente, cada página necesitará estos tres recursos, por lo tanto lo mejor será diseñar tres espacios de nombres donde estén los recursos correspondientes para cada una de las páginas. Por ejemplo, todos los recursos de recarga podrían comenzar por ``/reload/'', de forma que ``/reload/gsyc.es'' sería el recurso para recargar la página ``http://gsyc.es''.
Para poder almacenar el HTTP con el servidor, es importante darse cuenta de que el que se envía al servidor lo produce la propia aplicación. Si se usa \texttt{urllib}, no es posible acceder directamente a lo que se está enviando, pero se puede inferir a partir de lo que se indica a \texttt{urllib}. Por lo tanto, cualquier petición HTTP ``razonable'' para los parámetros dados será suficiente, aunque no sea exactamente lo que envíe \texttt{urllib}.
El HTTP que se recibe del servidor habrá que obtenerlo usando \texttt{urllib}, en la medida de lo posible.
Para poder almacenar el HTTP con el cliente, es importante darse cuenta de que el que se envía al navegador lo produce la propia aplicación, por lo que basta con almacenarlo antes de enviarlo. El que se recibe del navegador habrá que obtenerlo de la petición recibida.
%%-----------------------------------------------------------------------------
\subsection{Gestor de contenidos multilingüe versión REST}
\label{subsec:contentappmulti}
\textbf{Enunciado:}
Diseño y construcción de ``Gestor de contenidos miltilingüe versión REST''. Retomamos la aplicación ContentApp, pero ahora vamos a proporcionarle una interfaz multilingüe simple. Para empezar, trabajaremos con español (``es'') e inglés (``en''). Siguiendo la filosofía REST, cada recurso lo vamos a tener ahora disponible en dos URLs distintas, según en qué idioma esté. Los recursos en español empezarán por ``/es/'', y los recursos en inglés por ``/en/''. Además, si a un recurso no se le especifica de esta forma en qué idioma está, se servirá en el idioma por defecto (si está disponible), o en el otro idioma (si no está en el idioma por defecto, pero sí en el otro). Como siempre, los recursos que no estén disponibles en ningún idioma producirán un error ``Resource not available''.
\textbf{Comentarios:}
Para construir esta aplicación puedes usar dos diccionarios de contenidos (uno para cada idioma), o quizás mejor un diccionario de diccionarios, donde para cada recurso tengas como dato un diccionario con los idiomas en que está disponible, que tienen a su vez como dato la página HTML a servir.
%%-----------------------------------------------------------------------------
\subsection{Sistema de transferencias bancarias}
\label{subsec:transferencias-bancarias}
\textbf{Enunciado:}
Diseñar un sistema RESTful sobre HTTP fiable para realizar una transferencia bancaria vía HTTP.
\begin{itemize}
\item Debe poder confirmarse que la transferencia ha sido realizada.
\item Debe poder prevenirse que la transferencia se haga más de una vez.
\item Datos de la transferencia: cuenta origen, cuenta destino, cantidad.
\item También debe poder consultarse el saldo de la cuenta (datos: cuenta)
\item En un segundo escenario, puede suponerse todo lo anterior, pero considerando que hay una contraseña que protege el acceso a operaciones sobre una cuenta data (una contraseña por cuenta), tanto transferencias como consultas de saldo
.
\end{itemize}
Indica el esquema de recursos (URLs) que ofrecerá la aplicación, y los verbos (comandos) HTTP que aceptará para cada uno, y con qué semántica.
%%-----------------------------------------------------------------------------
\subsection{Gestor de contenidos multilingüe preferencias del navegador}
\label{subsec:contentappmulti-navegador}
\textbf{Enunciado:}
Diseñar y construir la aplicación web ``Gestor de contenidos multilingüe preferencias del navegador''. En la aplicación ``Gestor de contenidos multilingüe versión REST'' (ejercicio~\ref{subsec:contentappmulti}) se especificaban como parte del nombre e recurso el idioma en que se quiere recibir un recurso. Pero el navegador tiene habitualmente una forma de especificar en qué idioma quieres recibir las páginas cuando están disponibles en varios. Para ver cómo funciona esto, prueba a cambiar tus preferencias idiomáticas en Firefox, y consulta la página \url{http://debian.org}.