File: high_level_services.rst

package info (click to toggle)
libaws 3.3.2-2
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 15,780 kB
  • ctags: 648
  • sloc: ada: 87,379; python: 1,914; ansic: 929; makefile: 842; xml: 235; java: 112; sh: 105
file content (1617 lines) | stat: -rw-r--r-- 50,333 bytes parent folder | download | duplicates (2)
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
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
.. _High_level_services:

.. highlight:: ada

*******************
High level services
*******************

Here you will find a description of high level services. These services are
ready to use with AWS and can be used together with user's callbacks.

Refer to the Ada spec for a complete API and usage description.

.. _Directory_browser:

Directory browser
=================

.. index:: Directory browser

This service will help building a Web directory browser. It has a lot
of options to sort directory entries and is based on the templates
interface :ref:`AWS.Templates`. This means that you can use the
default directory template or provide your own.

see :ref:`AWS.Services.Directory` for complete spec and services descriptions.

.. _Dispatchers:

Dispatchers
===========

.. index:: Dispatchers

In many AWS applications it is needed to check the URI to give the
right answer. This means that part of the application is a big
**if/elsif** procedure. Also, in standard callback it is not possible
to have user data. Both of these restrictions are addressed with the
Dispatchers facilities.

Working with a dispatcher is quite easy:

* Create a new dispatcher by inheriting from the service you want
  to build.
* Register a set of action based on rules (strings, regular
  expressions depending on the service)

.. _Callback_dispatcher:

Callback dispatcher
-------------------

.. index:: Dispatchers callback
.. index:: Callback, dispatcher

This is a wrapper around the standard callback procedure. It is needed
to mix dispatcher based callback and access to procedure
callback. Note that it is not in the `AWS.Services.Dispatchers`
hierarchy but in `AWS.Dispatchers.Callback` because this is a
basic service needed for the server itself. It is referenced here for
documentation purpose but an AWS server can be built with using it.

see :ref:`AWS.Dispatchers.Callback` for complete spec description.

.. _Method_dispatcher:

Method dispatcher
-----------------

.. index:: Dispatchers method
.. index:: method, dispatcher

This is a dispatcher based on the request method. A different callback
procedure can be registered for the supported request methods: GET,
POST, PUT, HEAD.

see :ref:`AWS.Services.Dispatchers.Method` for complete spec description.

.. _URI_dispatcher:

URI dispatcher
--------------

.. index:: Dispatchers URI
.. index:: URI, dispatcher

This is a dispatcher based on the request resource. A different callback
procedure can be registered for specific resources. The resource is
described either by its full name (string) or a regular expression.

see :ref:`AWS.Services.Dispatchers.URI` for complete spec description.

.. _Virtual_host_dispatcher:

Virtual host dispatcher
-----------------------

.. index:: Dispatchers virtual host
.. index:: virtual host, dispatcher

This is a dispatcher based on the host name. A different callback
procedure can be registered for specific host. This is also known as
virtual hosting.

The same computer can be registered into the DNS with different
names. So all names point to the same machine. But in fact you want
each name to be seen as a different Web server. This is called virtual
hosting. This service will just do that, call different **callback**
procedures or redirect to some **machine/port** based on the host name
in the client's request.

see :ref:`AWS.Services.Dispatchers.Virtual_Host` for complete spec description.

.. _Transient_pages_dispatcher:

Transient pages dispatcher
--------------------------

.. index:: Dispatchers Transient pages
.. index:: transient pages, dispatcher

This is a dispatcher that calls a user's callback and if the resource
requested is not found (i.e. the user's callback returns status code
404) it checks if this resource is known as a transient
page. see :ref:`Transient_Pages`.

.. _Timer_dispatcher:

Timer dispatcher
----------------

.. index:: Dispatchers Timer
.. index:: timer, dispatcher

A timer dispatcher can be used to call different callback routines
depending on the current date and time. Such dispatcher is composed of
a set of `Period` activated. When the current date and time is
inside a `Period` the corresponding callback is called. A
`Period` can eventually be repeated. Here are the different kind
of `Period` supported by `AWS`:

*Once*
  A unique period in time. The boundaries are fully described using a
  year, month, day, hour, minute and second.

*Yearly*
  A period that repeats each year. The boundaries are described using a
  month, day, hour, minute and second.

*Monthly*
  A period that repeats each month. The boundaries are described using a
  day, hour, minute and second.

*Weekly*
  A period that repeats each week. The boundaries are described using a
  day name, hour, minute and second.

*Daily*
  A period that repeats each day. The boundaries are described using an
  hour, minute and second.

*Hourly*
  A period that repeats each hour. The boundaries are described using a
  minute and second.

*Minutely*
  A period that repeats each minute. The boundaries are described using
  a second.

.. _Linker_dispatcher:

Linker dispatcher
-----------------

.. index:: Dispatchers Linker
.. index:: linker, dispatcher

A dispatcher that can be used to chain two dispatchers. The response
of the first dispatcher is returned except if it is a 404 (Not Found)
error. In this case, the response of the second dispatcher is returned.

.. _SOAP_dispatcher:

SOAP dispatcher
---------------

.. index:: Dispatchers SOAP
.. index:: SOAP, dispatcher

`AWS` provides also a `SOAP` specific dispatcher. This is a way to
automatically route HTTP requests or `SOAP` requests to different
callback routines.

see :ref:`SOAP_helpers` for more information.
see :ref:`SOAP.Dispatchers.Callback` for complete spec description.

.. _Static_Page_server:

Static Page server
==================

.. index:: Static Page server
.. index:: Simple Page server
.. index:: Page server

This service is a ready to use static page server callback. Using it
is possible to build a simple static page server, as simple as::

 with AWS.Server;
 with AWS.Services.Page_Server;

 procedure WPS is
    WS : AWS.Server.HTTP;
 begin
    AWS.Server.Start
      (WS, "Simple Page Server demo",
       Port           => 8080,
       Callback       => AWS.Services.Page_Server.Callback'Access,
       Max_Connection => 5);

    AWS.Server.Wait (AWS.Server.Q_Key_Pressed);

    AWS.Server.Shutdown (WS);
 end WPS;

Build this program and launch it, it will server `HTML` pages and images
in the current directory.

It is possible to activate the directory browsing facility of this
simple page server. This is not activated by default. This feature
is based on the directory browsing service see :ref:`Directory_browser`.

Note that this service uses two template files:

*aws_directory.thtml*
  The template page used for directory browsing. See
  see :ref:`AWS.Services.Directory` for a full description of this
  template usage.

*404.thtml*
  The Web page returned if the requested page is not found. This is a
  template with a single tag variable named PAGE. It will be replaced by
  the ressource which was not found.

  Note that on Microsoft IE this page will be displayed only if the total
  page size is bigger than 512 bytes or it includes at least one image.

see :ref:`AWS.Services.Page_Server` for a complete spec description.

.. _Transient_Pages:

Transient Pages
===============

.. index:: transient pages
.. index:: pages, transient

A transient page is a resource that has a certain life time on the
server. After this time the resource will be released and will not be
accessible anymore.

Sometimes you want to reference, in a Web page, a resource that is built
in memory by the server. This resource can be requested by the client (by
clicking on the corresponding link) or not, in both cases the page must
be released after a certain amount of time to free the associated memory.

This is exactly what the transient pages high level service do
automatically. Each transient page must be registered into the
service, a specific routine named `Get_URI` can be used to create
a unique `URI` on this server. see :ref:`AWS.Services.Transient_Pages`.

A transient pages dispatcher can be used to build a transient pages
aware server. see :ref:`Transient_pages_dispatcher`.

.. _Split_pages:

Split pages
===========

.. index:: split pages
.. index:: pages, split

It not not very convenient to send back a Web page with a large
table. In such a case it is better to split the table in chunks (20
lines or so) and to send only the first page. This page reference the
next pages and can also contains an index of the pages.

The `AWS`'s split page feature can automatically do that for
you. Given template `Translate_Table` or `Translate_Set` and the
max line per page it returns the first page and create a set of
transient pages for all other pages. A set of template tags are used
to reference the previous and next page and also to build the page index.

There is different ways to split a set of pages and ready-to-use
splitters are available:

*Alpha*
  Split in (at most) 28 pages, one for empty fields, one for all fields
  that start with a digit, and one for each different initial letter.
  see :ref:`AWS.Services.Split_Pages.Alpha`.

*Alpha.Bounded*
  Same as the alpha splitter, but pages larger than a Max_Per_Page value
  are further splitted.
  A secondary index is generated that gives the various pages for a given
  letter. see :ref:`AWS.Services.Split_Pages.Alpha.Bounded`.

*Uniform*
  Split in pages of length Max_Per_Page (except the last one). This
  corresponds to the default service in Split_Pages package.
  see :ref:`AWS.Services.Split_Pages.Uniform`.

*Uniform.Alpha*
  Same as the uniform splitter, but builds in addition an alphabetical
  secondary index from a key field.
  see :ref:`AWS.Services.Split_Pages.Uniform.Alpha`.

*Uniform.Overlapping*
  Same as the uniform splitter, but pages (except the first one)
  repeat Overlap lines from the previous page in addition to the
  Max_Per_Page lines. see :ref:`AWS.Services.Split_Pages.Uniform.Overlapping`.

Using the spliter abstract interface it is possible to build a
customized splitter algorithm. see :ref:`AWS.Services.Split_Pages`.

.. _Download_Manager:

Download Manager
================

.. index:: Download Manager

A server that need to handle lot of large downloads can run out of
connection to answer the standard Web pages. A solution is to increase the
number of simultaneous connections, but this is not really efficient
as a task is created for each connection and does not ensure that all
the connections will be used for the downloads anyway.

The download manager can be used for that, and provides the following
feature:

* use a single task for all downloads
* can be configured to limit the number of simultaneous connections
* downloads past this limit are queued
* send messages to the client with the position in the waiting line
* send messages to the client when the download is about to start

The server must be configured to use dispatchers (standard callbacks
are not supported, note that it is possible to create a dispatcher for
standard callbacks. see :ref:`AWS.Dispatchers.Callback`).

To start the download manager you need to pass the main server
dispatcher object. The start routine will return a new dispatcher,
linked with the download server specific dispatcher, that must be used
to start the standard Web server. See comment in
see :ref:`AWS.Services.Download`.

To queue a download request in the download manager you just need to
create a stream object (can be any kind of stream, see
`AWS.Resources.Streams.*`) for the resource to download.

The download manager needs two templates files:

*aws_download_manager_waiting.thtml*
  This template is used for sending a message to the client when the
  request is on the waiting line. The tags defined in this template file
  are:

  *NAME*
    the name of the resource to download (the filename), this is the
    default filename used for the client side save dialog.

  *RES_URI*
    the URI used to access the resource.

  *POSITION*
    the position in the waiting line (not counting the current served clients).

*aws_download_manager_start.thtml*
  This template is used for sending a message to the client when the
  download is about to start (the request is out of the waiting
  line). The tags defined in this template file are:

  *NAME*
    as above

  *RES_URI*
    as above

.. highlight:: xml

It is important to note that those templates must be reloaded
periodically. The best way to do that in the context of an `HTML`
document is to use a meta-tag. For example to refresh the page every
two seconds::

 <meta http-equiv="refresh" content="2">

The templates could look like:

*aws_download_manager_waiting.thtml*

::

  <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
   "http://www.w3.org/TR/html4/strict.dtd">
    <html>
      <head>
        <meta http-equiv="refresh" content="2">
        <title>Download Manager - waiting</title>
      </head>
      <body>
        <p>Waiting for downloading @_NAME_@
        <p>Position in the waiting line @_POSITION_@
      </body>
    </html>

*aws_download_manager_start.thtml*

::

  <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
   "http://www.w3.org/TR/html4/strict.dtd">
    <html>
      <head>
        <meta http-equiv="refresh" content="2">
        <title>Download Manager - waiting</title>
      </head>
      <body>
        <p>Waiting for downloading @_NAME_@
        <p>The download will start in a moment
      </body>
    </html>

.. _Web_Elements:

Web Elements
============

.. index:: Web Elements

`AWS` provides some components to help creating nice looking Web
interfaces. It is possible to browse those Web Elements using the
`web_elements` demo. Just launch this Web application from the
demos directory and turn your Web browser to
`http://localhost:2400 <http://localhost:2400>`_.

Currently `AWS` provides:

* Notebooks (based on CSS)
* CSS Menu
* Rounded boxes
* Ajax

All of them are based on templates to be easily reused in other
applications. The three first are best described by the Web Elements
demos as they are 100% design. The `Ajax` one is a bit more complex, we
will present its use in the following section.

.. _Installation:

Installation
------------

.. index:: we_icons
.. index:: we_js

To ease integration we have used the following design:

* Sub-directories found in the `AWS`'s web_elements directory
  are self contained. The content must be copied into the project. Note
  that the icons and javascripts directories contain the
  icons and javascripts code shared by all web elements and must also be
  copied, see below.

* Each graphic elements (icons) is referenced into the templates with the
  alias `/we_icons/<icon_name>`. So users must provide the right alias
  ("`/we_icons/`") in the  Web server.

* Each JavaScripts code is referenced into the templates with the
  alias `/we_js/<script>`. So users must provide the right alias
  (`"/we_js/"`) in the  Web server.

.. _Ajax:

Ajax
----

.. index:: Ajax
.. index:: aws_action_replace.tjs
.. index:: aws_action_clear.tjs

First of all, `Ajax` stand for
*Asynchronous JavaScript language and XML*, and is not well defined
at the moment. `Ajax` is on one side able to send HTTP requests
to the Web server and on the other side able to manipulate directly the Web
browser's `DOM` tree. On the `DOM` it can add, remove or
replace `XML` nodes. So, it is possible to change the content of
a Web page without reloading it from the server.

Most importantly, `Ajax` changes the way Web applications are
thought from **page** based to **event** based.

As implemented into `AWS`, `Ajax` support comes as a set of
`JavaScript` templates. Using those templates there is no need to
know `JavaScript` (except for the `JavaScript` event names) and it
makes `Ajax` programming lot easier. Two actions are provided,
one for replacing another for clearing part of the web page content.

.. _Steps_to_do_Ajax:

Steps to do Ajax
^^^^^^^^^^^^^^^^

What are the steps to do `Ajax` ?

Remember, do not think about the Web page but about a specific widget
(`HTML` fragments) with the associated event and action.

* Include the AWS/Ajax support file

  This is the `AWS/Ajax` runtime, it contains `JavaScript`
  code needed for the `AWS/Ajax` support.

* Create the Web widgets/forms

  There is nothing special here, use your favorite Web designer tool.

* Create Web area

  Using some `HTML` <div> tags we create areas where we will place
  `HTML` fragments later. For example when clicking on a button
  (described above) in our Web interface we want to display a new form
  in this area.

* Name the widgets/forms/area using id="name" attribute

  Give a different name to the widgets using id="name". This name will
  be later used to identify the widgets on which the envent and
  corresponding action must be placed. We do not want to clutter the Web
  design with `JavaScript` code like `onclick="dothis()"` or
  `onchange="dothat()"`.

* Add the proper event/action to the widgets using the AWS/Ajax templates

  This is the interresting part. At this point we link events/actions
  to the widgets and specify in which area the results sent by the
  server will be placed.

This is not the only way to do `Ajax`, we just presented here a simple
approach that works well with the `AWS/Ajax` templates.

.. _Basic_Ajax_support:

Basic Ajax support
^^^^^^^^^^^^^^^^^^

This section describes the `AWS/Ajax` support where the answer from the
server is an `HTML` fragment. This basic support is designed to
be used for migration of a Web server to `Ajax`. For new
applications, it is worth considering using the XML based Ajax support,
see :ref:`XML_based_Ajax`.

Let's have a very simple example:

* The AWS/Ajax runtime support

  ::

   @@INCLUDE@@@ aws.tjs

  Must be included in every Web pages into the `<head>` tag.

* The widget: a button

  ::

   <input id="clickme" type="button" value="Clik Me">

* The result area: a div

  ::

   <div id="placeholder">... result here ...</div>

* The AWS/Ajax

  ::

   @@INCLUDE@@ aws_action_replace.tjs onclick clickme placeholder

  Basically it places an **onclick** attribute (the event) in the `HTML`
  `<input>` identified as **clickme** (the action) above. Here is
  what happen when the button is clicked:

  * send the "/onclick$clickme" HTTP request to the server
  * asynchronously wait for the answer, when received place the
    message body into the `<div>` **placeholder**.

.. highlight:: ada

On the server side the code would look like this::

 function Callback (Request : in Status.Data) return Response.Data is
    URI : constant String := Status.URI (Request);
 begin
    if URI = "/clickme" then
       return Response.Build (MIME.Text_HTML, "you click me!");
    ...

So when the button is clicked the string **"you click me!"** will replace
the **"... result here ..."** string of the place holder div above.

This is a simple and very limited example as there is no parameter
passed to the `HTTP` request. In real Web applications it is necessary
to send a context with the request. This can be either the value of
other widgets or all values of widgets' form.

.. highlight:: xml

References to widgets or forms can be passed to the
:file:`aws_action_replace.tjs` template starting with the 5th
parameter::

 <input id="field" type="text" value="default value">

 ...

 @@INCLUDE@@ aws_action_replace.tjs (onclick clickme placeholder 5=>field)

or::

 <form id="small_form" name="small_form">
 ...
 </form>

 @@INCLUDE@@ aws_action_replace.tjs (onclick clickme placeholder 5=>*mall_form)

Note that the `onclick` event is only one of the possible
`JavaScript` event on a `button`. It is possible to used
any supported event, for example on an `HTML` `<select>` widget
it is common to map the action to the `onchange` event.

`AWS` also provides support for clearing an area or a widget
content (like an input)::

 @@INCLUDE@@ aws_action_clear.tjs (onclick, clear, field)

This simple action adds the **onclick** event to the **clear** button
to erase the content of the **field** widget.

.. _XML_based_Ajax:

XML based Ajax
^^^^^^^^^^^^^^

In many cases you'll like to update and/or clear multiple areas in your
Web interface. With the templates above only a single action is
possible. `AWS` provides support for `XML` based answers. In
this `XML` documents it is possible to:

* replace an area with a new content::

   <replace id="item_id">new text</replace>

* clear an area::

   <clear id="item_id"/>

* add an item into a select widget::

   <select action="add" id="item_id"
           option_value="value" option_content="content"/>

* remove an item from a select widget::

   <select action="delete" id="item_id" option_value="value"/>

* select a specific item in a select widget::

   <select action="select" id="item_id" option_value="value"/>

* clear a select widget (remove all items)::

   <select action="clear" id="item_id"/>

* select a radio button::

   <radio action="select" id="item_id"/>

* check a checkbox::

   <check action="select" id="item_id"/>

* clear a checkbox::

   <check action="clear" id="item_id"/>

* call another URL::

   <get url="http://thishost/action">
     <parameters value="name=Ajax"/>
     <field id="input1"/>
   </get>

  This will send the following request::

   http://thishost/action?name=Ajax&input1=<val_input1>

  Where **val_input1** is the current value of the **input1** input
  widget. The result must be an `XML/Ajax` document that will be parsed.

* make a list sortable::

   <make_sortable>
     <list id="firstlist"/>
     <list id="secondlist"/>
   </make_sortable>

  Here **firstlist** and **secondlist** are **id** of `UL` elements. It is
  possible to specified as many list id as needed. A drag and drop is
  then possible for all elements in those lists. It is then possible to
  reference such list by passing the list id as a field to the
  template. Items on those list will be serialized and passed to the `AWS`
  callback. Note that for the serialization to work properly, each
  `LI` elements must be given the id of the list and then the value
  we want to pass::

   <ul id="firstlist">
     <li id="firstlist_red">Red</li>
     <li id="firstlist_green">Green</li>
     <li id="firstlist_blue">Blue</li>
   </ul>

  The serialization will send each value on this list using a
  multi-valued parameter named **firstlist[]**::

   http://server?firstlist[]=red&firstlist[]=green&firstlist[]=blue

* make a list not sortable::

   <destroy_sortable>
     <list id="firstlist"/>
     <list id="secondlist"/>
   </destroy_sortable>

  Remove the sortable properly from the specified lists.

* redirect to another URL::

   <location url="http://thishost/go_there"/>

  Redirect the browser to the specified URL.

* refresh the current page::

   <refresh/>

  Refresh the current page as if the Web Browser refresh button was pressed.

* add a CSS style to a given node::

   <apply_style id="node_id">
     <attribute id="display" value="none"/>
   </apply_style>

  Add the CSS style `display:none` to the **node_id** element. It
  is possible to specify multiple attributes if needed.

* make an entry disabled or enabled::

   <disabled id="item_id" value="true/false"/>

* make an entry read-only or writable::

   <read_only id="item_id" value="true/false"/>

* reset a form::

   <reset id="form_id"/>

Here is an example of such XML document::

 <?xml version="1.0" encoding="UTF-8" ?>
 <response>
   <replace id="xml_status_bar">Fill Widgets...</replace>
   <replace id="text1">Response from XML</replace>
   <replace id="text2">Another response for text2</replace>
   <replace id="input1">tag is input1</replace>
   <replace id="input2">tag is input2</replace>
   <select action="add" id="xmlsel" option_value="one" option_content="1"/>
   <select action="add" id="xmlsel" option_value="two" option_content="2"/>
   <select action="add" id="xmlsel" option_value="three" option_content="3"/>
   <select action="select" id="xmlsel" option_value="two"/>
   <radio action="select" id="radio1"/>
   <check action="select" id="check1"/>
   <check action="select" id="check3"/>
   <check action="clear" id="check2"/>
 </response>

To register an `Ajax` action to a specific tag id a macro can be
used. It is named `JS_ACTION` and defined in :file:`ajax_api.tjs`.
The usage is similar to what is described in the previous section
(see :ref:`Basic_Ajax_support`) except that in this case we use a macron
instead of an include file and we do not have to pass the placeholder.

Let's revisit the first example above to use the `XML`
`Ajax` support.

* The AWS/Ajax runtime support::

   @@INCLUDE@@@ aws.tjs

  Must be included in every Web pages into the `<head>` tag.

* The AWS/Ajax API::

   @@INCLUDE@@@ ajax_api.tjs

  Must be included at least once during an application life-time. It
  gives access to the `JS_ACTION` macro.

* The widget: a button::

   <input id="clickme" type="button" value="Clik Me">

* The result area: a div::

   <div id="placeholder">... result here ...</div>

* The AWS/Ajax::

   @_JS_ACTION(onclick, clickme)_@

  Basically it places an **onclick** attribute (the event) in the `HTML`
  `<input>` identified as **clickme** (the action) above. Here is
  what happen when the button is clicked:

  * send the "/onclick$clickme" HTTP request to the server
  * asynchronously wait for the XML answer, when received parse the
    answer and perform the actions according to the `XML` content.

To set the placeholder with "**new text**", the `XML` document
returned by the server must be::

 <?xml version="1.0" encoding="UTF-8" ?>
 <response>
   <replace id="placeholder">new text</replace>
 </response>

If we want also to clear the input field named **field** and to select the
radio button named **radio1** we must return::

 <?xml version="1.0" encoding="UTF-8" ?>
 <response>
   <replace id="placeholder">new text</replace>
   <clear id="field"/>
   <radio action="select" id="radio1"/>
 </response>

This is by far the most flexible solution as it is possible to return, from the
server, a structured answer.

A final comment, if the text returned by the server to replace a
specific area is an `HTML` fragment, the content must be placed into a
`CDATA` tag::

 <?xml version="1.0" encoding="UTF-8" ?>
 <response>
   <replace id="item_id">
     <![CDATA[ *HTML CODE HERE* ]]>
   </replace>
 </response>

.. _Advanced_Ajax:

Advanced Ajax
^^^^^^^^^^^^^

Finally, if this is not enough because you need to use some specific
`JavaScript` code, `AWS` provides a macro named
`BIND_JS` to add an event to a specific widget, the action being
the name of a `JavaScript` routine.

This macro together with the :file:`aws_func_replace.tjs`,
:file:`aws_func_clear.tjs` templates and the :file:`JS_ACTION` macro can
be used to chain multiple actions. Those templates are the function
body used by the corresponding templates :file:`aws_action_replace.tjs`,
:file:`aws_action_clear.tjs`.

Let say you want to clear a widget, change the content of another one
and calling one of your specific `JavaScript` routine when clicking on
a button. It is not possible to have mutiple `onclick` events on
the same widget, the solution is the following:

* Create the JavaScript routine to do the job

  For this in the the body of the `clear_replace()` JavaScript
  routine we place::

   function clear_replace()
   {
     @@INCLUDE@@ aws_func_replace.tjs (clickme placeholder 4=>field)
     @@INCLUDE@@ aws_func_clear.tjs (area)
     call_this_routine();
   }

  Then to add the event on the widget::

   @_BIND_JS(onclick, clickme clear_replace)_@

Furthermore, it is possible to pass (as the parameter number 20) a
routine to call after a specific action to all templates and to the
`JS_ACTION` macro. This is another way to chain multiple actions
for a single event.

Note that all `AWS/Ajax` templates and the :file:`ajax_api.tjs`
file have a set of comments at the start explaining in details the
usage of each parameter.

.. _Web_Blocks:

Web Blocks
==========

.. index:: Web Blocks

The `AWS.Services.Web_Block` hierarchy contains an API useful for
keeping context on Web pages. It has been designed to be able to split
a Web application into a set of independent blocks that can be put
together in the same Web page. The context is then useful as it is
passed and known by each individual block. Note that this is different
than the session as a session is global to the current Web browser
whereas the context can be different for each individual web pages
opened.

Instead of parsing a whole page using `AWS.Templates` API the web blocks
are registered independently using `AWS.Services.Web_Block.Registry`.
The block is registered together with its templates and a callback to use
to get user's data for this specific block with the given context.

So using this API, instead of having a set of callbacks returning an
`AWS.Response.Data` and where the final rendering is to be done
by the client code, we have a set of callbacks that returns a
`Translate_Set`. The client just have to fill the set with the
data corresponding to the actual request and possibly using the
context. The final rendering is done by the provided services in
`Web_Block.Registry`.

Note that all Web pages must also be registered into the registry
to ensure that the context identification is properly kept. The context
identification is injected into the Web pages transparently for the
end-user when using `Ajax`.

.. _Web_Block_example:

Web Block example
-----------------

Let's have a simple example, a page containing a single block with a
tag (@_COUNTER_@) which is incremented by one each time it is
used. The code can be found in :file:`demos/web_block`.

First create the following HTML fragment and place it into
:file:`counter.thtml`::

 <p>@_COUNTER_@</p>

Then create the main page and place it into :file:`page.thtml`. The
important part is the @_CTX_WB_@ tag which is passed to the link. This
tag is the context identifier, it must be passed to each request. Note
that this is automatically done when using the `Ajax` framework
(see :ref:`Web_Block_and_Ajax`)::

 <html>
   <head>
     <title>Main Page</title>
   </head>
   <body>
     <p>This is the main page, bellow is a simple counter</p>
     <p>@_COUNTER_@</p>
     <a href="/?CTX_WB=@_CTX_WB_@>Next</a>
   </body>
 </html>

.. highlight:: ada

The `Web_Callbacks` package contains the application callbacks::

 with AWS.Response;
 with AWS.Status;
 with AWS.Templates;
 with AWS.Services.Web_Block.Context;

 package Web_Callbacks is

    use AWS;
    use AWS.Services;

    function Main (Request : in Status.Data) return Response.Data;
    --  Main callback which handle the home page

    procedure Counter
      (Request      : in              Status.Data;
       Context      : not null access Web_Block.Context.Object;
       Translations : in out          Templates.Translate_Set);
    --  The callback handling the counter web block

 end Web_Callbacks;

Last part is to actually implement the `Counter` callback. Here
is a possible implementation making use of the context to keep the
counter state::

 with AWS.Utils;
 with AWS.Messages;
 with AWS.MIME;
 with AWS.Services.Web_Block.Registry;

 package body Web_Callbacks is

    -------------
    -- Counter --
    -------------

    procedure Counter
      (Request      : in              Status.Data;
       Context      : not null access Web_Block.Context.Object;
       Translations : in out          Templates.Translate_Set)
    is
       N : Natural := 0;
    begin
       if Context.Exist ("N") then
          N := Natural'Value (Context.Get_Value ("N"));
       end if;

       N := N + 1;
       Context.Set_Value ("N", Utils.Image (N));

       Templates.Insert
         (Translations, AWS.Templates.Assoc ("COUNTER", N));
    end Counter;

    ----------
    -- Main --
    ----------

    function Main (Request : in Status.Data) return Response.Data is
       URI : constant String := Status.URI (Request);
    begin
       return Web_Block.Registry.Build
         (Key          => URI,
          Request      => Request,
          Translations => Set);
    end Main;

 end Web_Callbacks;

Finally, we write the main procedure::

 with Ada.Text_IO;

 with AWS.Server;
 with AWS.Services.Web_Block.Registry;

 with Web_Callbacks;

 procedure Web_Block is

    use Ada;
    use AWS;
    use AWS.Services;

    HTTP : AWS.Server.HTTP;

 begin
    --  First we register the main page and the counter block

    Services.Web_Block.Registry.Register ("/", "page.thtml", null);

    Services.Web_Block.Registry.Register
      ("COUNTER", "counter.thtml",
       Web_Callbacks.Counter'Access, Context_Required => True);

    --  Then we just start the server

    Server.Start (HTTP, "web_block", Web_Callbacks.Main'Access);

    Text_IO.Put_Line ("Press Q to terminate.");

    Server.Wait (Server.Q_Key_Pressed);

    Server.Shutdown (HTTP);
 end Web_Block;

Compile and run the server. Then connect to the server and click on
next. The counter will be incremented by one each time.

.. _Web_Block_and_Ajax:

Web Block and Ajax
------------------

The Web Block framework has really been designed to be used with
`Ajax`. It is the only way to gain the full power of the Web Block
framework.

For the complete code, see `demos/web_block_ajax`.

.. highlight:: xml

When using `Ajax` it is not needed to explicitly pass the context
identification to every link. This is done automatically by the
framework. So the main page will look like this::

 @@INCLUDE@@ ../../web_elements/javascripts/ajax_api.tjs
 <html>
   <head>
     <title>Main Page</title>
     @@INCLUDE@@ ../../web_elements/javascripts/aws.tjs
   </head>
   <body>
     <p>This is the main page, bellow is a simple counter</p>
     @_WIDGET_COUNTER_@
   </body>
 </html>

The counter widget is on :file:`widget_counter.thtml`::

 <!-- implementation of a simple counter widget -->
 <p><div id="counter">@_COUNTER_@</div></p>
 <a id="next" href="/">Next</a>
 @_JS_ACTION(onclick, next)_@

For the `Ajax` part, see :ref:`Ajax`.

.. highlight:: ada

We now have one more register call for registering the `next` button
`Ajax` callback, and a callback named `Widget_Counter` for
displaying the block::

 Services.Web_Block.Registry.Register
   ("WIDGET_COUNTER", "widget_counter.thtml",
    Web_Callbacks.Widget_Counter'Access);

 Services.Web_Block.Registry.Register
   ("/onclick$next", "r_widget_counter.txml",
    Web_Callbacks.Onclick_Next'Access,
    Content_Type     => MIME.Text_XML,
    Context_Required => True);

.. highlight:: xml

The `next` `Ajax` button is using an XML based response which
is defined in :file:`r_widget_counter.txml`::

 <?xml version="1.0" encoding="UTF-8" ?>
 <response>
   <replace id="counter">@_COUNTER_@</replace>
 </response>

.. highlight:: ada

The `Widget_Counter` callbacks just have to set the
`COUNTER` tag variable to the corresponding value. This is used to
display the block. The `Ajax` callback `Onclick_Next` has to
increment the counter and set the `COUNTER` tag variable, a simple
implementation is::

 procedure Onclick_Next
   (Request      : in              Status.Data;
    Context      : not null access Web_Block.Context.Object;
    Translations : in out          Templates.Translate_Set)
 is
    N : Natural := 0;
 begin
    if Context.Exist ("N") then
       N := Natural'Value (Context.Get_Value ("N"));
    end if;

    N := N + 1;

    Context.Set_Value ("N", Utils.Image (N));

    Templates.Insert
      (Translations, Templates.Assoc ("COUNTER", N));
 end Onclick_Next;

The framework will then call `Onclick_Next` when pressing the
`Next` button. This routine increments N by one sending back a
response based on `r_widget_counter.txml`. Finally, the client
browser will parse this XML response and do the corresponding actions.

.. _Web_Block_and_templates2ada:

Web Block and templates2ada
---------------------------

For the complete code, see `demos/web_block_ajax_templates`.

It is possible to use the `Templates_Parser's templates2ada` tool for
generating the callbacks register calls. This ensures that all tags on the
application Web Pages have a corresponding callback.

.. highlight:: xml

The code is almost identical to the standard `Ajax` example above. The
main difference is that we need to use a naming convention for the
blocks. This way we can generate automatically the corresponding
callbacks using a template. A common convention is to add `LAZY_` as
prefix for the name of the blocks. With this convention the main page
template is::

 @@INCLUDE@@ ../../web_elements/javascripts/ajax_api.tjs
 <html>
   <head>
     <title>Main Page</title>
     @@INCLUDE@@ ../../web_elements/javascripts/aws.tjs
   </head>
   <body>
     <p>This is the main page, bellow is a simple counter</p>
     @_LAZY_WIDGET_COUNTER_@
   </body>
 </html>

.. highlight:: ada

We need also modify the standard :file:`templates.tads` as distributed
with the `Templates_Parser`. Here is the interesting part::

 @@SET@@ PACKAGE = WBlocks

 ...

 with AWS.MIME;
 with AWS.Services.Web_Block.Registry;
 with Web_Callbacks;

 @@TABLE@@
 with @_PACKAGE_@.@_CAPITALIZE:REPLACE_ALL(\\./_):BASENAME_@;
 @@END_TABLE@@

 package body @_PACKAGE_@ is

    use AWS;

    package body Lazy is

       --------------
       -- Register --
       --------------

       procedure Register is
          use AWS.Services;
       begin
          --  Register blocks
          @@TABLE@@
          @@IF@@ @_UPPER:SLICE(1..5):VARIABLE_LIST_@ = "LAZY_"
          Web_Block.Registry.Register
            ("@_VARIABLE_LIST_@",
             "@_LOWER:REPLACE_ALL(LAZY_/):VARIABLE_LIST_@.thtml",
             Web_Callbacks.@_CAPITALIZE:REPLACE_ALL(LAZY_/):VARIABLE_LIST_@'Access);
          @@END_IF@@
          @@END_TABLE@@

          --  Register Ajax
          @@TABLE@@
          @@TABLE@@
            @@IF@@ not @_IS_EMPTY:AJAX_EVENT_@
          Services.Web_Block.Registry.Register
            ("/@_AJAX_EVENT_@$@_AJAX_ACTION_@",
             @_PACKAGE_@.R_@_CAPITALIZE:REPLACE_ALL(\\./_):AJAX_FILE_@.Template,
             Web_Callbacks.@_CAPITALIZE:AJAX_EVENT_@@_UNDERSCORE_@@_CAPITALIZE:AJAX_ACTION_@'Access,
             Content_Type     => MIME.Text_XML,
             Context_Required => True);
            @@END_IF@@
          @@END_TABLE@@
          @@END_TABLE@@
       end Register;
    end Lazy;
 end @_PACKAGE_@;

Basically this is to write a register call for every template's
tag starting with `LAZY_`. The second section is to write a
register call for every `Ajax` event. All callbacks are expected to be in
a package named `Web_Callbacks`. It is of course possible to change
this template to reference callbacks for blocks and `Ajax` in separate
packages. The use of a template here is very flexible.

Now let's parse the application HTML and XML templates and create the
corresponding Ada specs and register calls::

 $ templates2ada -d . -o code.ada -t templates.tada -e .thtml -e .txml
 $ gnatchop code.ada

Look at the generated code below, it properly register the
`Widget_Counter` callback to be used for rendering
`LAZY_WIDGET_COUNTER` using the :file:`widget_counter.thtml`. So
we have a tight coupling between the code and the template file. If
the tag is renamed in the template file the application will not
compile anymore. The same is true for `Ajax` callbacks, every
`Ajax` action put in a template file needs a corresponding
callback in Ada. This greatly helps keeping the application code
synchronized::

 procedure Register is
    use AWS.Services;
 begin
    Web_Block.Registry.Register
      ("LAZY_WIDGET_COUNTER",
       "widget_counter.thtml",
       Web_Callbacks.Widget_Counter'Access);
    Services.Web_Block.Registry.Register
      ("/onclick$next",
       WBlocks.R_Widget_Counter.Template,
       Web_Callbacks.Onclick_Next'Access,
       Content_Type     => MIME.Text_XML,
       Context_Required => True);
 end Register;

In the main, it is just now required to register the Web pages and to
call the generated `Register` procedure::

 Services.Web_Block.Registry.Register ("/", "page.thtml", null);

 WBlocks.Lazy.Register;

Moreover, an Ada spec containing reference for the tag names is
generated for every HTML and XML template file. All tags can be
referenced using those specs, it is not needed to use string
literal in the application. Again, this ensures that a tag which is
renamed or deleted is detected at compilation time. For example the
`Widget_Counter` callback can be rewritten as follow::

 procedure Widget_Counter
   (Request      : in              Status.Data;
    Context      : not null access Web_Block.Context.Object;
    Translations : in out          Templates.Translate_Set)
 is
    N : Natural := 0;
 begin
    if Context.Exist ("N") then
       N := Natural'Value (Context.Get_Value ("N"));
    end if;

    Templates.Insert
      (Translations, Templates.Assoc (WBlocks.Widget_Counter.COUNTER, N));
 end Widget_Counter;

.. _Web_Cross-References:

Web Cross-References
====================

.. index:: webxref
.. index:: web cross-references

When building an `Ajax` Web applications it is required to give ids to
web elements to be able to reference them. It is also quite common to
use CSS to give such and such item a specific style. After some time
it is quite difficult to keep track of all those ids. Are they all
used ? Don't we reference an id that does not exist anymore ?

`webxref` has been designed to help finding such problems.

The files kinds handled are:

*.css*, *.tcss*
  A CSS (or template CSS file). Ids and classes inside are recorded as
  CSS definitions.

*.xml*, *.html*, *.thtml*
  A meta-language document. Ids and classes inside are recorded as
  referencing a CSS definition and meta-language definition.

*.txml*
  An `Ajax` response file. Ids declared inside are recorded as referencing
  a meta-language definition.

The features are:

*cross-references*
  By default `webxref` output all the references to ids and classes.

*finding unused items*
  Output the ids/classes that are defined but not used. For example an
  id declared in a CSS but never referenced into an HTML document or an
  HTML id never referenced in an `Ajax` response file :file:`.txml` document.

*finding undeclared items*
  Output ids/classes that are referenced but never defined. This is for
  example an id inside an `Ajax` response file which is never defined into
  an HTML document.

*enforcing a naming scheme for ids and classes*
  It can enforce a specific prefix for ids and classes. The id prefix
  can be based on the filename (using filename's first character and all
  character before an underscore). This make it less likely to find the
  same id on multiple files.

Note that all references are in a format recognized by tools like `GPS`
and `Emacs`. It is then possible to navigate inside them easily.

All `webxref` options are listed using the `-h` option.

.. _WebSockets:

WebSockets
==========

.. index:: websockets
.. index:: web sockets

.. _Introduction_to_WebSockets:

Introduction to WebSockets
--------------------------

WebSockets are part of HTML5, the API is being standardized by the W3C
and the protocol by the IETF (see RFC-6455). It is a bidirectional and
full-duplex communication channel between the client and the
server. Most Web Browsers are now supporting (at least part) of the
WebSocket recommendation. On the client side, the WebSockets are
programmed in JavaScript as done for Ajax for example.

A WebSocket is always opened at the request of a client. This can be
done on the same port as the main HTTP protocol. This is possible because
the initial handshake to open a WebSocket is done in pure HTTP protocol. Past
this initial handshake the socket is switching protocol from HTTP to the one
called WebSocket protocol.

It is not needed to know the protocol to use the WebSockets, AWS comes with
some high level services on the server side and also on the client side.

.. _WebSockets_on_the_client:

WebSockets on the client
------------------------

The WebSocket is created on the client side. As there is some differences
between Web browsers, AWS provides a wrapper routine to create a
WebSocket::

 ws = AWS.WebSocket.open('ws://localhost:8080/echo');

This basically create a WebSocket and contact the local server using
port 8080.

This method is declared into :file:`aws.tjs` which must be included::

 @@INCLUDE@@@ aws.tjs

A WebSocket Javascript's object has four method's callbacks:

*onopen*
  Called when the WebSocket has been opened. This means that the
  initial handshake with the server has been accepted. At this point the
  WebSocket is ready to send and received messages.

*onmessage*
  Called for every incoming message. This callback receive a single
  parameter which is the event. The actual message data can be found in
  **e.data**.

*onclose*
  Called when the WebSocket is closing. This means that the server has
  sent a close request. After this event it is not possible to send nor
  receive messages through this WebSocket.

*onerror*
  Called when an error has occurred. This can be a lost connection for
  example. This callback takes a single parameter which is the error
  message.

AWS comes with default implementation of those callbacks. With the
two optional WebSocket constructor parameters it can be configured to
fit most needs::

 ws = AWS.WebSocket.open('ws://localhost:8080/echo', message_id, status_id);

*message_id*
  The id of the HTML element which will be used to display the incoming
  messages. This is most of the time the id of a `p` or `div` HTML
  element.

*status_id*
  The id of the HTML element which will be used to display the status
  and error messages. For example when a connection is closed.

When those default callbacks are not what is needed it is always
possible to redefine them::

 ws.onmessage = function (e) {
   code there
 };

Likewise for the other events.

.. _WebSockets_on_the_server:

WebSockets on the server
------------------------

The first step is to setup the server to dispatch the incoming
messages to the proper WebSocket object. For this one needs to inherit
from `AWS.Net.WebSocket.Object` and redefine at least two methods
`Create` and `On_Message`:

*Create*
  This is the constructor that will be used by the server to handle some
  WebSockets. This constructor will be associated to some URI, see below::

   function Create
     (Socket  : Socket_Access;
      Request : AWS.Status.Data) return Object'Class;

  The default constructor creates a WebSocket of type
  `AWS.Net.WebSocket.Object`. It is not possible to receive events
  (close, open, error) using such object it is only possible to
  send messages to the clients.

  Here is an example on a custom socket::

   type MySocket is new Net.WebSocket.Object with null record;

   function Create
     (Socket  : Socket_Access;
      Request : AWS.Status.Data) return MySocket'Class
   is
      --  Note the call to the other version of Create*
     return
       (AWS.Net.WebSocket.Object
         (AWS.Net.WebSocket.Create (Socket, Request)) with null record);
   end Create;

  It is also possible to deny the handshake by returning an object from
  AWS.Net.WebSocket.Handshake_Error.

*On_Open*
  This is the callback that will be called when the WebSocket is opened::

   procedure On_Open
     (Socket : in out Object; Message : String) is null;

*On_Message*
  This is the callback that will be called for every message sent by the
  client on the corresponding WebSocket::

   procedure On_Message
     (Socket : in out Object; Message : String);

  The first parameter is the WebSocket itself, it is possible to send a
  message directly by using the associated `Send` method. Note that
  the default implementation supports the XML based Ajax actions.
  See see :ref:`XML_based_Ajax` and can be used to redirect simple message
  to an HTML widget given it's id.

*On_Close*
  This is the callback that will be called when the WebSocket is closed::

   procedure On_Close
     (Socket : in out Object; Message : String) is null;

*On_Error*
  This is the callback that will be called when an error occurs on the
  WebSocket::

   procedure On_Error
     (Socket : in out Object; Message : String) is null;

When this is done, the constructor declared above needs to be
registered to handle some WebSocket designated by the URI. For example
to have this WebSocket handling all URI named `/echo`::

 Net.WebSocket.Registry.Register ("/echo", CB.Create'Access);

Where `CB.Create` is the constructor redefined for the new
WebSocket class.

The last step is to start the WebSocket server which are needed to
handle the incoming messages::

 Net.WebSocket.Registry.Control.Start;

At this point all is setup to have AWS supports WebSockets. Sending
messages can be done to a single client or by broadcasting to all
clients for a specific URI. To send a message one need to create a
`Net.WebSocket.Registry.Recipient` object. For example to
broadcast a message to all Web clients having opened the `/echo`
WebSocket::

 Rcp : Net.WebSocket.Registry.Recipient :=
         Net.WebSocket.Registry.Create (URI => "/echo");

 Net.WebSocket.Registry.Send (Rcp, "A simple message");

As we have seen before, this will send a message to clients which will
in turn trigger the `onmessage` Javascript method.

It is also possible to send a message to clients from a specific
origin by using the `Origin` information::

 Rcp : Net.WebSocket.Registry.Recipient :=
         Net.WebSocket.Registry.Create (URI => "/echo"; Origin => ".*\\.fr");

 Net.WebSocket.Registry.Send (Rcp, "A simple message");

The above recipent targets all WebSockets whose URI is `"/echo"`
and that have been created from a Web page originating from a Web server
running in the `.fr` domain. Note that `URI` and the
`Origin` are regular expressions.

The `Origin` value can be used by a server to handle only
WebSockets originating from it's own domain. Restricting the origin of
the WebSockets can be done with the `WEBSOCKET_ORIGIN` config
parameter, see :ref:`WebSocket_Origin`.