This file is indexed.

/usr/share/doc/libapache2-mod-perl2-doc/docs/2.0/user/handlers/http.html is in libapache2-mod-perl2-doc 2.0.8+httpd24-r1449661-6ubuntu2.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

   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
<?xml version="1.0" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<link rev="made" href="mailto:root@localhost" />
</head>

<body style="background-color: white">



<ul id="index">
  <li><a href="#NAME">NAME</a></li>
  <li><a href="#Description">Description</a></li>
  <li><a href="#HTTP-Request-Handler-Skeleton">HTTP Request Handler Skeleton</a></li>
  <li><a href="#HTTP-Request-Cycle-Phases">HTTP Request Cycle Phases</a>
    <ul>
      <li><a href="#PerlPostReadRequestHandler">PerlPostReadRequestHandler</a></li>
      <li><a href="#PerlTransHandler1">PerlTransHandler</a></li>
      <li><a href="#PerlMapToStorageHandler1">PerlMapToStorageHandler</a></li>
      <li><a href="#PerlHeaderParserHandler">PerlHeaderParserHandler</a></li>
      <li><a href="#PerlInitHandler">PerlInitHandler</a></li>
      <li><a href="#PerlAccessHandler1">PerlAccessHandler</a></li>
      <li><a href="#PerlAuthenHandler1">PerlAuthenHandler</a></li>
      <li><a href="#PerlAuthzHandler1">PerlAuthzHandler</a></li>
      <li><a href="#PerlTypeHandler1">PerlTypeHandler</a></li>
      <li><a href="#PerlFixupHandler1">PerlFixupHandler</a></li>
      <li><a href="#PerlResponseHandler1">PerlResponseHandler</a></li>
      <li><a href="#PerlLogHandler1">PerlLogHandler</a></li>
      <li><a href="#PerlCleanupHandler1">PerlCleanupHandler</a>
        <ul>
          <li><a href="#Possible-Caveats">Possible Caveats</a></li>
        </ul>
      </li>
    </ul>
  </li>
  <li><a href="#Miscellaneous-Issues">Miscellaneous Issues</a>
    <ul>
      <li><a href="#Handling-HEAD-Requests">Handling HEAD Requests</a></li>
      <li><a href="#Content-Length-Response-Header">Content-Length Response Header</a></li>
    </ul>
  </li>
  <li><a href="#Misc-Notes">Misc Notes</a></li>
  <li><a href="#Extending-HTTP-Protocol">Extending HTTP Protocol</a></li>
  <li><a href="#HTTP-Status-Codes">HTTP Status Codes</a>
    <ul>
      <li><a href="#HTTP-1.0-Status-Codes">HTTP 1.0 Status Codes</a></li>
      <li><a href="#HTTP-1.1-Status-Codes">HTTP 1.1 Status Codes</a></li>
      <li><a href="#References">References</a></li>
    </ul>
  </li>
  <li><a href="#Maintainers">Maintainers</a></li>
  <li><a href="#Authors">Authors</a></li>
</ul>

<h1 id="NAME">NAME</h1>

<p>HTTP Handlers</p>

<h1 id="Description">Description</h1>

<p>This chapter explains how to implement the HTTP protocol handlers in mod_perl.</p>

<h1 id="HTTP-Request-Handler-Skeleton">HTTP Request Handler Skeleton</h1>

<p>All HTTP Request handlers have the following structure:</p>

<pre><code>  package MyApache2::MyHandlerName;

  # load modules that are going to be used
  use ...;

  # compile (or import) constants
  use Apache2::Const -compile =&gt; qw(OK);

  sub handler {
      my $r = shift;
      
      # handler code comes here
      
      return Apache2::Const::OK; # or another status constant
  }
  1;</code></pre>

<p>First, the package is declared. Next, the modules that are going to be used are loaded and constants compiled.</p>

<p>The handler itself coming next and usually it receives the only argument: the <code><a>Apache2::RequestRec</a></code> object. If the handler is declared as <a>a method handler </a>:</p>

<pre><code>  sub handler : method {
      my ($class, $r) = @_;</code></pre>

<p>the handler receives two arguments: the class name and the <code><a>Apache2::RequestRec</a></code> object.</p>

<p>The handler ends with <a>a return code</a> and the file is ended with <code>1;</code> to return true when it gets loaded.</p>

<h1 id="HTTP-Request-Cycle-Phases">HTTP Request Cycle Phases</h1>

<p>Those familiar with mod_perl 1.0 will find the HTTP request cycle in mod_perl 2.0 to be almost identical to the mod_perl 1.0&#39;s model. The different things are:</p>

<ul>

<li><p>a new directive <code><a href="#PerlMapToStorageHandler">PerlMapToStorageHandler</a></code> was added to match the new phase <i>map_to_storage</i> added by Apache 2.0.</p>

</li>
<li><p>the <code>PerlHandler</code> directive has been renamed to <code>PerlResponseHandler</code> to better match the corresponding Apache phase name (<i>response</i>).</p>

</li>
<li><p>the <i>response</i> phase now includes filtering.</p>

</li>
</ul>

<p>The following diagram depicts the HTTP request life cycle and highlights which handlers are available to mod_perl 2.0:</p>




<img src="http_cycle.gif" width="600" height="560" 
 align="middle" alt="HTTP cycle"><br><br>

<p>From the diagram it can be seen that an HTTP request is processed by 12 phases, executed in the following order:</p>

<dl>

<dt id="PerlPostReadRequestHandler-PerlInitHandler">1 PerlPostReadRequestHandler (PerlInitHandler)</dt>
<dd>

</dd>
<dt id="PerlTransHandler">2 PerlTransHandler</dt>
<dd>

</dd>
<dt id="PerlMapToStorageHandler">3 PerlMapToStorageHandler</dt>
<dd>

</dd>
<dt id="PerlHeaderParserHandler-PerlInitHandler">4 PerlHeaderParserHandler (PerlInitHandler)</dt>
<dd>

</dd>
<dt id="PerlAccessHandler">5 PerlAccessHandler</dt>
<dd>

</dd>
<dt id="PerlAuthenHandler">6 PerlAuthenHandler</dt>
<dd>

</dd>
<dt id="PerlAuthzHandler">7 PerlAuthzHandler</dt>
<dd>

</dd>
<dt id="PerlTypeHandler">8 PerlTypeHandler</dt>
<dd>

</dd>
<dt id="PerlFixupHandler">9 PerlFixupHandler</dt>
<dd>

</dd>
<dt id="PerlResponseHandler">10 PerlResponseHandler</dt>
<dd>

</dd>
<dt id="PerlLogHandler">11 PerlLogHandler</dt>
<dd>

</dd>
<dt id="PerlCleanupHandler">12 PerlCleanupHandler</dt>
<dd>

</dd>
</dl>

<p>It&#39;s possible that the cycle will not be completed if any of the phases terminates it, usually when an error happens. In that case Apache skips to the logging phase (mod_perl executes all registered <code>PerlLogHandler</code> handlers) and finally the cleanup phase happens.</p>

<p>Notice that when the response handler is reading the input data it can be filtered through request input filters, which are preceded by connection input filters if any. Similarly the generated response is first run through request output filters and eventually through connection output filters before it&#39;s sent to the client. We will talk about filters in detail later in <a>the dedicated to filters chapter</a>.</p>

<p>Before discussing each handler in detail remember that if you use <a>the stacked handlers feature</a> all handlers in the chain will be run as long as they return <code>Apache2::Const::OK</code> or <code>Apache2::Const::DECLINED</code>. Because stacked handlers is a special case. So don&#39;t be surprised if you&#39;ve returned <code>Apache2::Const::OK</code> and the next handler was still executed. This is a feature, not a bug.</p>

<p>Now let&#39;s discuss each of the mentioned handlers in detail.</p>

<h2 id="PerlPostReadRequestHandler">PerlPostReadRequestHandler</h2>

<p>The <i>post_read_request</i> phase is the first request phase and happens immediately after the request has been read and HTTP headers were parsed.</p>

<p>This phase is usually used to do processing that must happen once per request. For example <code>Apache2::Reload</code> is usually invoked at this phase to reload modified Perl modules.</p>

<p>This phase is of type <code><a>RUN_ALL</a></code>.</p>

<p>The handler&#39;s configuration scope is <code><a>SRV</a></code>, because at this phase the request has not yet been associated with a particular filename or directory.</p>

<p><b>Arguments</b></p>

<p>See the <a>HTTP Request Handler Skeleton</a> for a description of handler arguments.</p>

<p><b>Return</b></p>

<p>See <a>Stacked Handlers</a> for a description of handler return codes.</p>

<p><b>Examples</b></p>

<p>Now, let&#39;s look at an example. Consider the following registry script:</p>

<pre><code>  #file:touch.pl
  #-------------
  use strict;
  use warnings;
  
  use Apache2::ServerUtil ();
  use Apache2::RequestIO ();
  use File::Spec::Functions qw(catfile);
  
  my $r = shift;
  $r-&gt;content_type(&#39;text/plain&#39;);
  
  my $conf_file = catfile Apache2::ServerUtil::server_root,
    &quot;conf&quot;, &quot;httpd.conf&quot;;
  
  printf &quot;$conf_file is %0.2f minutes old\n&quot;, 60*24*(-M $conf_file);</code></pre>

<p>This registry script is supposed to print when the last time <i>httpd.conf</i> has been modified, compared to the start of the request process time. If you run this script several times you might be surprised that it reports the same value all the time. Unless the request happens to be served by a recently started child process which will then report a different value. But most of the time the value won&#39;t be reported correctly.</p>

<p>This happens because the <code>-M</code> operator reports the difference between file&#39;s modification time and the value of a special Perl variable <code>$^T</code>. When we run scripts from the command line, this variable is always set to the time when the script gets invoked. Under mod_perl this variable is getting preset once when the child process starts and doesn&#39;t change since then, so all requests see the same time, when operators like <code>-M</code>, <code>-C</code> and <code>-A</code> are used.</p>

<p>Armed with this knowledge, in order to make our code behave similarly to the command line programs we need to reset <code>$^T</code> to the request&#39;s start time, before <code>-M</code> is used. We can change the script itself, but what if we need to do the same change for several other scripts and handlers? A simple <code>PerlPostReadRequestHandler</code> handler, which will be executed as the very first thing of each requests, comes handy here:</p>

<pre><code>  #file:MyApache2/TimeReset.pm
  #--------------------------
  package MyApache2::TimeReset;
  
  use strict;
  use warnings;
  
  use Apache2::RequestRec ();
  
  use Apache2::Const -compile =&gt; &#39;OK&#39;;
  
  sub handler {
      my $r = shift;
      $^T = $r-&gt;request_time;
      return Apache2::Const::OK;
  }
  1;</code></pre>

<p>We could do:</p>

<pre><code>  $^T = time();</code></pre>

<p>But to make things more efficient we use <code>$r-&gt;request_time</code> since the request object <code>$r</code> already stores the request&#39;s start time, so we get it without performing an additional system call.</p>

<p>To enable it just add to <i>httpd.conf</i>:</p>

<pre><code>  PerlPostReadRequestHandler MyApache2::TimeReset</code></pre>

<p>either to the global section, or to the <code>&lt;VirtualHost&gt;</code> section if you want this handler to be run only for a specific virtual host.</p>

<h2 id="PerlTransHandler1">PerlTransHandler</h2>

<p>The <i>translate</i> phase is used to perform the manipulation of a request&#39;s URI. If no custom handler is provided, the server&#39;s standard translation rules (e.g., <code>Alias</code> directives, mod_rewrite, etc.) will be used. A <code>PerlTransHandler</code> handler can alter the default translation mechanism or completely override it. This is also a good place to register new handlers for the following phases based on the URI. <code><a href="#PerlMapToStorageHandler">PerlMapToStorageHandler</a></code> is to be used to override the URI to filename translation.</p>

<p>This phase is of type <code><a>RUN_FIRST</a></code>.</p>

<p>The handler&#39;s configuration scope is <code><a>SRV</a></code>, because at this phase the request has not yet been associated with a particular filename or directory.</p>

<p><b>Arguments</b></p>

<p>See the <a>HTTP Request Handler Skeleton</a> for a description of handler arguments.</p>

<p><b>Return</b></p>

<p>See <a>Stacked Handlers</a> for a description of handler return codes.</p>

<p><b>Examples</b></p>

<p>There are many useful things that can be performed at this stage. Let&#39;s look at the example handler that rewrites request URIs, similar to what mod_rewrite does. For example, if your web-site was originally made of static pages, and now you have moved to a dynamic page generation chances are that you don&#39;t want to change the old URIs, because you don&#39;t want to break links for those who link to your site. If the URI:</p>

<pre><code>  http://example.com/news/20021031/09/index.html</code></pre>

<p>is now handled by:</p>

<pre><code>  http://example.com/perl/news.pl?date=20021031;id=09;page=index.html</code></pre>

<p>the following handler can do the rewriting work transparent to <i>news.pl</i>, so you can still use the former URI mapping:</p>

<pre><code>  #file:MyApache2/RewriteURI.pm
  #---------------------------
  package MyApache2::RewriteURI;
  
  use strict;
  use warnings;
  
  use Apache2::RequestRec ();
  
  use Apache2::Const -compile =&gt; qw(DECLINED);
  
  sub handler {
      my $r = shift;
  
      my ($date, $id, $page) = $r-&gt;uri =~ m|^/news/(\d+)/(\d+)/(.*)|;
      $r-&gt;uri(&quot;/perl/news.pl&quot;);
      $r-&gt;args(&quot;date=$date;id=$id;page=$page&quot;);
  
      return Apache2::Const::DECLINED;
  }
  1;</code></pre>

<p>The handler matches the URI and assigns a new URI via <code>$r-&gt;uri()</code> and the query string via <code>$r-&gt;args()</code>. It then returns <code>Apache2::Const::DECLINED</code>, so the next translation handler will get invoked, if more rewrites and translations are needed.</p>

<p>Of course if you need to do a more complicated rewriting, this handler can be easily adjusted to do so.</p>

<p>To configure this module simply add to <i>httpd.conf</i>:</p>

<pre><code>  PerlTransHandler +MyApache2::RewriteURI</code></pre>

<h2 id="PerlMapToStorageHandler1">PerlMapToStorageHandler</h2>

<p>The <i>map_to_storage</i> phase is used to perform the translation of a request&#39;s URI into a corresponding filename. If no custom handler is provided, the server will try to walk the filesystem trying to find what file or directory corresponds to the request&#39;s URI. Since usually mod_perl handler don&#39;t have corresponding files on the filesystem, you will want to shortcut this phase and save quite a few CPU cycles.</p>

<p>This phase is of type <code><a>RUN_FIRST</a></code>.</p>

<p>The handler&#39;s configuration scope is <code><a>SRV</a></code>, because at this phase the request has not yet been associated with a particular filename or directory.</p>

<p><b>Arguments</b></p>

<p>See the <a>HTTP Request Handler Skeleton</a> for a description of handler arguments.</p>

<p><b>Return</b></p>

<p>See <a>Stacked Handlers</a> for a description of handler return codes.</p>

<p><b>Examples</b></p>

<p>For example if you don&#39;t want Apache to try to attempt to translate URI into a filename, just add a handler:</p>

<pre><code>  PerlMapToStorageHandler MyApache2::NoTranslation</code></pre>

<p>using the following code:</p>

<pre><code>  #file:MyApache2/NoTranslation.pm
  #------------------------------
  package MyApache2::NoTranslation;
  
  use strict;
  use warnings FATAL =&gt; &#39;all&#39;;
  
  use Apache2::Const -compile =&gt; qw(OK);
  
  sub handler {
      my $r = shift;
  
      # skip ap_directory_walk stat() calls
      return Apache2::Const::OK;
  }
  1;</code></pre>

<p>But this can be done from <i>httpd.conf</i> too!</p>

<pre><code>  PerlMapToStorageHandler Apache2::Const::OK</code></pre>

<p>If you haven&#39;t already compiled <code>Apache2::Const::OK</code> elsewhere, you should add:</p>

<pre><code>  &lt;Perl&gt;
      use Apache2::Const -compile =&gt; qw(OK);
  &lt;/Perl&gt;</code></pre>

<p>Apache also uses this phase to handle <code>TRACE</code> requests. So if you shortcut it, <code>TRACE</code> calls will be not handled. In case you need to handle such, you may rewrite it as:</p>

<pre><code>  #file:MyApache2/NoTranslation2.pm
  #-------------------------------
  package MyApache2::NoTranslation2;
  
  use strict;
  use warnings FATAL =&gt; &#39;all&#39;;
  
  use Apache2::RequestRec ();

  use Apache2::Const -compile =&gt; qw(DECLINED OK M_TRACE);
  
  sub handler {
      my $r = shift;
  
      return Apache2::Const::DECLINED
          if $r-&gt;method_number == Apache2::Const::M_TRACE;
  
      # skip ap_directory_walk stat() calls
      return Apache2::Const::OK;
  }
  1;</code></pre>

<p>BTW, the HTTP TRACE method asks a web server to echo the contents of the request back to the client for debugging purposes. i.e., the complete request, including HTTP headers, is returned in the entity-body of a TRACE response. Attackers may abuse HTTP TRACE functionality to gain access to information in HTTP headers such as cookies and authentication data. In the presence of other cross-domain vulnerabilities in web browsers, sensitive header information could be read from any domains that support the HTTP TRACE method.</p>

<p>Another way to prevent the core translation is to set <code>$r-&gt;filename()</code> to some value, which can also be done in the <code><a href="#PerlTransHandler">PerlTransHandler</a></code>, if you are already using it.</p>

<h2 id="PerlHeaderParserHandler">PerlHeaderParserHandler</h2>

<p>The <i>header_parser</i> phase is the first phase to happen after the request has been mapped to its <code>&lt;Location&gt;</code> (or an equivalent container). At this phase the handler can examine the request headers and to take a special action based on these. For example this phase can be used to block evil clients targeting certain resources, while little resources were wasted so far.</p>

<p>This phase is of type <code><a>RUN_ALL</a></code>.</p>

<p>The handler&#39;s configuration scope is <code><a>DIR</a></code>.</p>

<p><b>Arguments</b></p>

<p>See the <a>HTTP Request Handler Skeleton</a> for a description of handler arguments.</p>

<p><b>Return</b></p>

<p>See <a>Stacked Handlers</a> for a description of handler return codes.</p>

<p><b>Examples</b></p>

<p>This phase is very similar to <code><a href="#PerlPostReadRequestHandler">PerlPostReadRequestHandler</a></code>, with the only difference that it&#39;s run after the request has been mapped to the resource. Both phases are useful for doing something once per request, as early as possible. And usually you can take any <code><a href="#PerlPostReadRequestHandler">PerlPostReadRequestHandler</a></code> and turn it into <code><a href="#PerlHeaderParserHandler">PerlHeaderParserHandler</a></code> by simply changing the directive name in <i>httpd.conf</i> and moving it inside the container where it should be executed. Moreover, because of this similarity mod_perl provides a special directive <code><a href="#PerlInitHandler">PerlInitHandler</a></code> which if found outside resource containers behaves as <code><a href="#PerlPostReadRequestHandler">PerlPostReadRequestHandler</a></code>, otherwise as <code><a href="#PerlHeaderParserHandler">PerlHeaderParserHandler</a></code>.</p>

<p>You already know that Apache handles the <code>HEAD</code>, <code>GET</code>, <code>POST</code> and several other HTTP methods. But did you know that you can invent your own HTTP method as long as there is a client that supports it. If you think of emails, they are very similar to HTTP messages: they have a set of headers and a body, sometimes a multi-part body. Therefore we can develop a handler that extends HTTP by adding a support for the <code>EMAIL</code> method. We can enable this protocol extension and push the real content handler during the <code><a href="#PerlHeaderParserHandler">PerlHeaderParserHandler</a></code> phase:</p>

<pre><code>  &lt;Location /email&gt;
      PerlHeaderParserHandler MyApache2::SendEmail
  &lt;/Location&gt;</code></pre>

<p>and here is the <code>MyApache2::SendEmail</code> handler:</p>

<pre><code>  #file:MyApache2/SendEmail.pm
  #--------------------------
  package MyApache2::SendEmail;
  
  use strict;
  use warnings;
  
  use Apache2::RequestRec ();
  use Apache2::RequestIO ();
  use Apache2::RequestUtil ();
  use Apache2::ServerUtil ();
  use Apache2::ServerRec ();
  use Apache2::Process ();
  use APR::Table ();
  
  use Apache2::Const -compile =&gt; qw(DECLINED OK);
  
  use constant METHOD        =&gt; &#39;EMAIL&#39;;
  use constant SMTP_HOSTNAME =&gt; &quot;localhost&quot;;
  
  sub handler {
      my $r = shift;
  
      return Apache2::Const::DECLINED unless $r-&gt;method eq METHOD;
  
      $r-&gt;server-&gt;method_register(METHOD);
      $r-&gt;handler(&quot;perl-script&quot;);
      $r-&gt;push_handlers(PerlResponseHandler =&gt; \&amp;send_email_handler);
  
      return Apache2::Const::OK;
  }
  
  sub send_email_handler {
      my $r = shift;
  
      my %headers = map {$_ =&gt; $r-&gt;headers_in-&gt;get($_)} 
                qw(To From Subject);
      
          my $content = content($r);
  
      my $status = send_email(\%headers, \$content);
  
      $r-&gt;content_type(&#39;text/plain&#39;);
      $r-&gt;print($status ? &quot;ACK&quot; : &quot;NACK&quot;);
      return Apache2::Const::OK;
  }
  
  sub send_email {
      my ($rh_headers, $r_body) = @_;
  
      require MIME::Lite;
      MIME::Lite-&gt;send(&quot;smtp&quot;, SMTP_HOSTNAME, Timeout =&gt; 60);
  
      my $msg = MIME::Lite-&gt;new(%$rh_headers, Data =&gt; $$r_body);
      #warn $msg-&gt;as_string;
      $msg-&gt;send;
  }
  
  use APR::Brigade ();
  use APR::Bucket ();
  
  use Apache2::Const -compile =&gt; qw(MODE_READBYTES);
  use APR::Const    -compile =&gt; qw(SUCCESS BLOCK_READ);
  
  use constant IOBUFSIZE =&gt; 8192;
  
  sub content {
      my $r = shift;
  
      my $bb = APR::Brigade-&gt;new($r-&gt;pool, $r-&gt;connection-&gt;bucket_alloc);
  
      my $data = &#39;&#39;;
      my $seen_eos = 0;
      do {
          $r-&gt;input_filters-&gt;get_brigade($bb, 
                          Apache2::Const::MODE_READBYTES,
              APR::Const::BLOCK_READ, IOBUFSIZE);
  
          for (my $b = $bb-&gt;first; $b; $b = $bb-&gt;next($b)) {
              if ($b-&gt;is_eos) {
                  $seen_eos++;
                  last;
              }
  
              if ($b-&gt;read(my $buf)) {
                  $data .= $buf;
              }
  
              $b-&gt;remove; # optimization to reuse memory
          }
      } while (!$seen_eos);
  
      $bb-&gt;destroy;
  
      return $data;
  }
  
  1;</code></pre>

<p>Let&#39;s get the less interesting code out of the way. The function content() grabs the request body. The function send_email() sends the email over SMTP. You should adjust the constant <code>SMTP_HOSTNAME</code> to point to your outgoing SMTP server. You can replace this function with your own if you prefer to use a different method to send email.</p>

<p>Now to the more interesting functions. The function <code>handler()</code> returns immediately and passes the control to the next handler if the request method is not equal to <code>EMAIL</code> (set in the <code>METHOD</code> constant):</p>

<pre><code>      return Apache2::Const::DECLINED unless $r-&gt;method eq METHOD;</code></pre>

<p>Next it tells Apache that this new method is a valid one and that the <code>perl-script</code> handler will do the processing.</p>

<pre><code>      $r-&gt;server-&gt;method_register(METHOD);
      $r-&gt;handler(&quot;perl-script&quot;);</code></pre>

<p>Finally it pushes the function <code>send_email_handler()</code> to the <code>PerlResponseHandler</code> list of handlers:</p>

<pre><code>      $r-&gt;push_handlers(PerlResponseHandler =&gt; \&amp;send_email_handler);</code></pre>

<p>The function terminates the header_parser phase by:</p>

<pre><code>      return Apache2::Const::OK;</code></pre>

<p>All other phases run as usual, so you can reuse any HTTP protocol hooks, such as authentication and fixup phases.</p>

<p>When the response phase starts <code>send_email_handler()</code> is invoked, assuming that no other response handlers were inserted before it. The response handler consists of three parts. Retrieve the email headers <code>To</code>, <code>From</code> and <code>Subject</code>, and the body of the message:</p>

<pre><code>      my %headers = map {$_ =&gt; $r-&gt;headers_in-&gt;get($_)} 
            qw(To From Subject);
      my $content = $r-&gt;content;</code></pre>

<p>Then send the email:</p>

<pre><code>      my $status = send_email(\%headers, \$content);</code></pre>

<p>Finally return to the client a simple response acknowledging that email has been sent and finish the response phase by returning <code>Apache2::Const::OK</code>:</p>

<pre><code>      $r-&gt;content_type(&#39;text/plain&#39;);
      $r-&gt;print($status ? &quot;ACK&quot; : &quot;NACK&quot;);
      return Apache2::Const::OK;</code></pre>

<p>Of course you will want to add extra validations if you want to use this code in production. This is just a proof of concept implementation.</p>

<p>As already mentioned when you extend an HTTP protocol you need to have a client that knows how to use the extension. So here is a simple client that uses <code>LWP::UserAgent</code> to issue an <code>EMAIL</code> method request over HTTP protocol:</p>

<pre><code>  #file:send_http_email.pl
  #-----------------------
  #!/usr/bin/perl
  
  use strict;
  use warnings;
  
  require LWP::UserAgent;
  
  my $url = &quot;http://localhost:8000/email/&quot;;
  
  my %headers = (
      From    =&gt; &#39;example@example.com&#39;,
      To      =&gt; &#39;example@example.com&#39;,
      Subject =&gt; &#39;3 weeks in Tibet&#39;,
  );
  
  my $content = &lt;&lt;EOI;
  I didn&#39;t have an email software,
  but could use HTTP so I&#39;m sending it over HTTP
  EOI
  
  my $headers = HTTP::Headers-&gt;new(%headers);
  my $req = HTTP::Request-&gt;new(&quot;EMAIL&quot;, $url, $headers, $content);
  my $res = LWP::UserAgent-&gt;new-&gt;request($req);
  print $res-&gt;is_success ? $res-&gt;content : &quot;failed&quot;;</code></pre>

<p>most of the code is just a custom data. The code that does something consists of four lines at the very end. Create <code>HTTP::Headers</code> and <code>HTTP::Request</code> object. Issue the request and get the response. Finally print the response&#39;s content if it was successful or just <i>&quot;failed&quot;</i> if not.</p>

<p>Now save the client code in the file <i>send_http_email.pl</i>, adjust the <i>To</i> field, make the file executable and execute it, after you have restarted the server. You should receive an email shortly to the address set in the <i>To</i> field.</p>

<h2 id="PerlInitHandler">PerlInitHandler</h2>

<p>When configured inside any container directive, except <code>&lt;VirtualHost&gt;</code>, this handler is an alias for <code><a href="#PerlHeaderParserHandler">PerlHeaderParserHandler</a></code> described earlier. Otherwise it acts as an alias for <code><a href="#PerlPostReadRequestHandler">PerlPostReadRequestHandler</a></code> described earlier.</p>

<p>It is the first handler to be invoked when serving a request.</p>

<p>This phase is of type <code><a>RUN_ALL</a></code>.</p>

<p><b>Arguments</b></p>

<p>See the <a>HTTP Request Handler Skeleton</a> for a description of handler arguments.</p>

<p><b>Return</b></p>

<p>See <a>Stacked Handlers</a> for a description of handler return codes.</p>

<p><b>Examples</b></p>

<p>The best example here would be to use <code><a>Apache2::Reload</a></code> which takes the benefit of this directive. Usually <code><a>Apache2::Reload</a></code> is configured as:</p>

<pre><code>  PerlInitHandler Apache2::Reload
  PerlSetVar ReloadAll Off
  PerlSetVar ReloadModules &quot;MyApache2::*&quot;</code></pre>

<p>which during the current HTTP request will monitor and reload all <code>MyApache2::*</code> modules that have been modified since the last HTTP request. However if we move the global configuration into a <code>&lt;Location&gt;</code> container:</p>

<pre><code>  &lt;Location /devel&gt;
      PerlInitHandler Apache2::Reload
      PerlSetVar ReloadAll Off
      PerlSetVar ReloadModules &quot;MyApache2::*&quot;
      SetHandler perl-script
      PerlResponseHandler ModPerl::Registry
      Options +ExecCGI
  &lt;/Location&gt;</code></pre>

<p><code><a>Apache2::Reload</a></code> will reload the modified modules, only when a request to the <i>/devel</i> namespace is issued, because <code><a href="#PerlInitHandler">PerlInitHandler</a></code> plays the role of <code><a href="#PerlHeaderParserHandler">PerlHeaderParserHandler</a></code> here.</p>

<h2 id="PerlAccessHandler1">PerlAccessHandler</h2>

<p>The <i>access_checker</i> phase is the first of three handlers that are involved in what&#39;s known as AAA: Authentication, Authorization, and Access control.</p>

<p>This phase can be used to restrict access from a certain IP address, time of the day or any other rule not connected to the user&#39;s identity.</p>

<p>This phase is of type <code><a>RUN_ALL</a></code>.</p>

<p>The handler&#39;s configuration scope is <code><a>DIR</a></code>.</p>

<p><b>Arguments</b></p>

<p>See the <a>HTTP Request Handler Skeleton</a> for a description of handler arguments.</p>

<p><b>Return</b></p>

<p>See <a>Stacked Handlers</a> for a description of handler return codes.</p>

<p><b>Examples</b></p>

<p>The concept behind access checker handler is very simple, return <code>Apache2::Const::FORBIDDEN</code> if the access is not allowed, otherwise return <code>Apache2::Const::OK</code>.</p>

<p>The following example handler denies requests made from IPs on the blacklist.</p>

<pre><code>  #file:MyApache2/BlockByIP.pm
  #--------------------------
  package MyApache2::BlockByIP;
  
  use strict;
  use warnings;
  
  use Apache2::RequestRec ();
  use Apache2::Connection ();
  
  use Apache2::Const -compile =&gt; qw(FORBIDDEN OK);
  
  my %bad_ips = map {$_ =&gt; 1} qw(127.0.0.1 10.0.0.4);
  
  sub handler {
      my $r = shift;
  
      return exists $bad_ips{$r-&gt;connection-&gt;remote_ip}
          ? Apache2::Const::FORBIDDEN
          : Apache2::Const::OK;
  }
  
  1;</code></pre>

<p>The handler retrieves the connection&#39;s IP address, looks it up in the hash of blacklisted IPs and forbids the access if found. If the IP is not blacklisted, the handler returns control to the next access checker handler, which may still block the access based on a different rule.</p>

<p>To enable the handler simply add it to the container that needs to be protected. For example to protect an access to the registry scripts executed from the base location <i>/perl</i> add:</p>

<pre><code>  &lt;Location /perl/&gt;
      SetHandler perl-script
      PerlResponseHandler ModPerl::Registry
      PerlAccessHandler MyApache2::BlockByIP
      Options +ExecCGI
  &lt;/Location&gt;</code></pre>

<p>It&#39;s important to notice that <code>PerlAccessHandler</code> can be configured for any subsection of the site, no matter whether it&#39;s served by a mod_perl response handler or not. For example to run the handler from our example for all requests to the server simply add to <i>httpd.conf</i>:</p>

<pre><code>  &lt;Location /&gt;
      PerlAccessHandler MyApache2::BlockByIP
  &lt;/Location&gt;</code></pre>

<h2 id="PerlAuthenHandler1">PerlAuthenHandler</h2>

<p>The <i>check_user_id</i> (<i>authen</i>) phase is called whenever the requested file or directory is password protected. This, in turn, requires that the directory be associated with <code>AuthName</code>, <code>AuthType</code> and at least one <code>require</code> directive.</p>

<p>This phase is usually used to verify a user&#39;s identification credentials. If the credentials are verified to be correct, the handler should return <code>Apache2::Const::OK</code>. Otherwise the handler returns <code>Apache2::Const::HTTP_UNAUTHORIZED</code> to indicate that the user has not authenticated successfully. When Apache sends the HTTP header with this code, the browser will normally pop up a dialog box that prompts the user for login information.</p>

<p>This phase is of type <code><a>RUN_FIRST</a></code>.</p>

<p>The handler&#39;s configuration scope is <code><a>DIR</a></code>.</p>

<p><b>Arguments</b></p>

<p>See the <a>HTTP Request Handler Skeleton</a> for a description of handler arguments.</p>

<p><b>Return</b></p>

<p>See <a>Stacked Handlers</a> for a description of handler return codes.</p>

<p><b>Examples</b></p>

<p>The following handler authenticates users by asking for a username and a password and lets them in only if the length of a string made from the supplied username and password and a single space equals to the secret length, specified by the constant <code>SECRET_LENGTH</code>.</p>

<pre><code>  #file:MyApache2/SecretLengthAuth.pm
  #---------------------------------
  package MyApache2::SecretLengthAuth;
  
  use strict;
  use warnings;
  
  use Apache2::Access ();
  use Apache2::RequestUtil ();
  
  use Apache2::Const -compile =&gt; qw(OK DECLINED HTTP_UNAUTHORIZED);
  
  use constant SECRET_LENGTH =&gt; 14;
  
  sub handler {
      my $r = shift;
  
      my ($status, $password) = $r-&gt;get_basic_auth_pw;
      return $status unless $status == Apache2::Const::OK;
  
      return Apache2::Const::OK 
          if SECRET_LENGTH == length join &quot; &quot;, $r-&gt;user, $password;
  
      $r-&gt;note_basic_auth_failure;
      return Apache2::Const::HTTP_UNAUTHORIZED;
  }
  
  1;</code></pre>

<p>First the handler retrieves the status of the authentication and the password in plain text. The status will be set to <code>Apache2::Const::OK</code> only when the user has supplied the username and the password credentials. If the status is different, we just let Apache handle this situation for us, which will usually challenge the client so it&#39;ll supply the credentials.</p>

<p>Note that <code>get_basic_auth_pw()</code> does a few things behind the scenes, which are important to understand if you plan on implementing your own authentication mechanism that does not use <code>get_basic_auth_pw()</code>. First, is checks the value of the configured <code>AuthType</code> for the request, making sure it is <code>Basic</code>. Then it makes sure that the Authorization (or Proxy-Authorization) header is formatted for <code>Basic</code> authentication. Finally, after isolating the user and password from the header, it populates the <i>ap_auth_type</i> slot in the request record with <code>Basic</code>. For the first and last parts of this process, mod_perl offers an API. <code>$r-&gt;auth_type</code> returns the configured authentication type for the current request - whatever was set via the <code>AuthType</code> configuration directive. <code>$r-&gt;ap_auth_type</code> populates the <i>ap_auth_type</i> slot in the request record, which should be done after it has been confirmed that the request is indeed using <code>Basic</code> authentication. (Note: <code>$r-&gt;ap_auth_type</code> was <code>$r-&gt;connection-&gt;auth_type</code> in the mod_perl 1.0 API.)</p>

<p>Once we know that we have the username and the password supplied by the client, we can proceed with the authentication. Our authentication algorithm is unusual. Instead of validating the username/password pair against a password file, we simply check that the string built from these two items plus a single space is <code>SECRET_LENGTH</code> long (14 in our example). So for example the pair <i>mod_perl/rules</i> authenticates correctly, whereas <i>secret/password</i> does not, because the latter pair will make a string of 15 characters. Of course this is not a strong authentication scheme and you shouldn&#39;t use it for serious things, but it&#39;s fun to play with. Most authentication validations simply verify the username/password against a database of valid pairs, usually this requires the password to be encrypted first, since storing passwords in clear is a bad idea.</p>

<p>Finally if our authentication fails the handler calls note_basic_auth_failure() and returns <code>Apache2::Const::HTTP_UNAUTHORIZED</code>, which sets the proper HTTP response headers that tell the client that its user that the authentication has failed and the credentials should be supplied again.</p>

<p>It&#39;s not enough to enable this handler for the authentication to work. You have to tell Apache what authentication scheme to use (<code>Basic</code> or <code>Digest</code>), which is specified by the <code>AuthType</code> directive, and you should also supply the <code>AuthName</code> -- the authentication realm, which is really just a string that the client usually uses as a title in the pop-up box, where the username and the password are inserted. Finally the <code>Require</code> directive is needed to specify which usernames are allowed to authenticate. If you set it to <code>valid-user</code> any username will do.</p>

<p>Here is the whole configuration section that requires users to authenticate before they are allowed to run the registry scripts from <i>/perl/</i>:</p>

<pre><code>  &lt;Location /perl/&gt;
      SetHandler perl-script
      PerlResponseHandler ModPerl::Registry
      PerlAuthenHandler MyApache2::SecretLengthAuth
      Options +ExecCGI
  
      AuthType Basic
      AuthName &quot;The Gate&quot;
      Require valid-user
  &lt;/Location&gt;</code></pre>

<p>Just like <code>PerlAccessHandler</code> and other mod_perl handlers, <code>PerlAuthenHandler</code> can be configured for any subsection of the site, no matter whether it&#39;s served by a mod_perl response handler or not. For example to use the authentication handler from the last example for any requests to the site, simply use:</p>

<pre><code>  &lt;Location /&gt;
      PerlAuthenHandler MyApache2::SecretLengthAuth
      AuthType Basic
      AuthName &quot;The Gate&quot;
      Require valid-user
  &lt;/Location&gt;</code></pre>

<h2 id="PerlAuthzHandler1">PerlAuthzHandler</h2>

<p>The <i>auth_checker</i> (<i>authz</i>) phase is used for authorization control. This phase requires a successful authentication from the previous phase, because a username is needed in order to decide whether a user is authorized to access the requested resource.</p>

<p>As this phase is tightly connected to the authentication phase, the handlers registered for this phase are only called when the requested resource is password protected, similar to the auth phase. The handler is expected to return <code>Apache2::Const::DECLINED</code> to defer the decision, <code>Apache2::Const::OK</code> to indicate its acceptance of the user&#39;s authorization, or <code>Apache2::Const::HTTP_UNAUTHORIZED</code> to indicate that the user is not authorized to access the requested document.</p>

<p>This phase is of type <code><a>RUN_FIRST</a></code>.</p>

<p>The handler&#39;s configuration scope is <code><a>DIR</a></code>.</p>

<p><b>Arguments</b></p>

<p>See the <a>HTTP Request Handler Skeleton</a> for a description of handler arguments.</p>

<p><b>Return</b></p>

<p>See <a>Stacked Handlers</a> for a description of handler return codes.</p>

<p><b>Examples</b></p>

<p>Here is the <code>MyApache2::SecretResourceAuthz</code> handler which grants access to certain resources only to certain users who have already properly authenticated:</p>

<pre><code>  #file:MyApache2/SecretResourceAuthz.pm
  #------------------------------------
  package MyApache2::SecretResourceAuthz;
  
  use strict;
  use warnings;
  
  use Apache2::Access ();
  use Apache2::RequestUtil ();
  
  use Apache2::Const -compile =&gt; qw(OK HTTP_UNAUTHORIZED);
  
  my %protected = (
      &#39;admin&#39;  =&gt; [&#39;stas&#39;],
      &#39;report&#39; =&gt; [qw(stas boss)],
  );
  
  sub handler {
      my $r = shift;
  
      my $user = $r-&gt;user;
      if ($user) {
          my ($section) = $r-&gt;uri =~ m|^/company/(\w+)/|;
          if (defined $section &amp;&amp; exists $protected{$section}) {
              my $users = $protected{$section};
              return Apache2::Const::OK if grep { $_ eq $user } @$users;
          }
          else {
              return Apache2::Const::OK;
          }
      }
  
      $r-&gt;note_basic_auth_failure;
      return Apache2::Const::HTTP_UNAUTHORIZED;
  }
  
  1;</code></pre>

<p>This authorization handler is very similar to the authentication handler <a href="#PerlAuthenHandler">from the previous section</a>. Here we rely on the previous phase to get users authenticated, and now as we have the username we can make decisions whether to let the user access the resource it has asked for or not. In our example we have a simple hash which maps which users are allowed to access what resources. So for example anything under <i>/company/admin/</i> can be accessed only by the user <i>stas</i>, <i>/company/report/</i> can be accessed by users <i>stas</i> and <i>boss</i>, whereas any other resources under <i>/company/</i> can be accessed by everybody who has reached so far. If for some reason we don&#39;t get the username, we or the user is not authorized to access the resource the handler does the same thing as it does when the authentication fails, i.e, calls:</p>

<pre><code>      $r-&gt;note_basic_auth_failure;
      return Apache2::Const::HTTP_UNAUTHORIZED;</code></pre>

<p>The configuration is similar to the one in <a href="#PerlAuthenHandler">the previous section</a>, this time we just add the <code>PerlAuthzHandler</code> setting. The rest doesn&#39;t change.</p>

<pre><code>  Alias /company/ /home/httpd/httpd-2.0/perl/
  &lt;Location /company/&gt;
      SetHandler perl-script
      PerlResponseHandler ModPerl::Registry
      PerlAuthenHandler MyApache2::SecretLengthAuth
      PerlAuthzHandler  MyApache2::SecretResourceAuthz
      Options +ExecCGI
  
      AuthType Basic
      AuthName &quot;The Secret Gate&quot;
      Require valid-user
  &lt;/Location&gt;</code></pre>

<p>And if you want to run the authentication and authorization for the whole site, simply add:</p>

<pre><code>  &lt;Location /&gt;
      PerlAuthenHandler MyApache2::SecretLengthAuth
      PerlAuthzHandler  MyApache2::SecretResourceAuthz
      AuthType Basic
      AuthName &quot;The Secret Gate&quot;
      Require valid-user
  &lt;/Location&gt;</code></pre>

<h2 id="PerlTypeHandler1">PerlTypeHandler</h2>

<p>The <i>type_checker</i> phase is used to set the response MIME type (<code>Content-type</code>) and sometimes other bits of document type information like the document language.</p>

<p>For example <code>mod_autoindex</code>, which performs automatic directory indexing, uses this phase to map the filename extensions to the corresponding icons which will be later used in the listing of files.</p>

<p>Of course later phases may override the mime type set in this phase.</p>

<p>This phase is of type <code><a>RUN_FIRST</a></code>.</p>

<p>The handler&#39;s configuration scope is <code><a>DIR</a></code>.</p>

<p><b>Arguments</b></p>

<p>See the <a>HTTP Request Handler Skeleton</a> for a description of handler arguments.</p>

<p><b>Return</b></p>

<p>See <a>Stacked Handlers</a> for a description of handler return codes.</p>

<p><b>Examples</b></p>

<p>The most important thing to remember when overriding the default <i>type_checker</i> handler, which is usually the mod_mime handler, is that you have to set the handler that will take care of the response phase and the response callback function or the code won&#39;t work. mod_mime does that based on <code>SetHandler</code> and <code>AddHandler</code> directives, and file extensions. So if you want the content handler to be run by mod_perl, set either:</p>

<pre><code>  $r-&gt;handler(&#39;perl-script&#39;);
  $r-&gt;set_handlers(PerlResponseHandler =&gt; \&amp;handler);</code></pre>

<p>or:</p>

<pre><code>  $r-&gt;handler(&#39;modperl&#39;);
  $r-&gt;set_handlers(PerlResponseHandler =&gt; \&amp;handler);</code></pre>

<p>depending on which type of response handler is wanted.</p>

<p>Writing a <code>PerlTypeHandler</code> handler which sets the content-type value and returns <code>Apache2::Const::DECLINED</code> so that the default handler will do the rest of the work, is not a good idea, because mod_mime will probably override this and other settings.</p>

<p>Therefore it&#39;s the easiest to leave this stage alone and do any desired settings in the <i>fixups</i> phase.</p>

<h2 id="PerlFixupHandler1">PerlFixupHandler</h2>

<p>The <i>fixups</i> phase is happening just before the content handling phase. It gives the last chance to do things before the response is generated. For example in this phase <code>mod_env</code> populates the environment with variables configured with <i>SetEnv</i> and <i>PassEnv</i> directives.</p>

<p>This phase is of type <code><a>RUN_ALL</a></code>.</p>

<p>The handler&#39;s configuration scope is <code><a>DIR</a></code>.</p>

<p><b>Arguments</b></p>

<p>See the <a>HTTP Request Handler Skeleton</a> for a description of handler arguments.</p>

<p><b>Return</b></p>

<p>See <a>Stacked Handlers</a> for a description of handler return codes.</p>

<p><b>Examples</b></p>

<p>The following fixup handler example tells Apache at run time which handler and callback should be used to process the request based on the file extension of the request&#39;s URI.</p>

<pre><code>  #file:MyApache2/FileExtDispatch.pm
  #--------------------------------
  package MyApache2::FileExtDispatch;
  
  use strict;
  use warnings;
  
  use Apache2::RequestIO ();
  use Apache2::RequestRec ();
  use Apache2::RequestUtil ();
  
  use Apache2::Const -compile =&gt; &#39;OK&#39;;
  
  use constant HANDLER  =&gt; 0;
  use constant CALLBACK =&gt; 1;
  
  my %exts = (
      cgi =&gt; [&#39;perl-script&#39;,     \&amp;cgi_handler],
      pl  =&gt; [&#39;modperl&#39;,         \&amp;pl_handler ],
      tt  =&gt; [&#39;perl-script&#39;,     \&amp;tt_handler ],
      txt =&gt; [&#39;default-handler&#39;, undef        ],
  );
  
  sub handler {
      my $r = shift;
  
      my ($ext) = $r-&gt;uri =~ /\.(\w+)$/;
      $ext = &#39;txt&#39; unless defined $ext and exists $exts{$ext};
  
      $r-&gt;handler($exts{$ext}-&gt;[HANDLER]);
  
      if (defined $exts{$ext}-&gt;[CALLBACK]) {
          $r-&gt;set_handlers(PerlResponseHandler =&gt; $exts{$ext}-&gt;[CALLBACK]);
      }
  
      return Apache2::Const::OK;
  }
  
  sub cgi_handler { content_handler($_[0], &#39;cgi&#39;) }
  sub pl_handler  { content_handler($_[0], &#39;pl&#39;)  }
  sub tt_handler  { content_handler($_[0], &#39;tt&#39;)  }
  
  sub content_handler {
      my ($r, $type) = @_;
  
      $r-&gt;content_type(&#39;text/plain&#39;);
      $r-&gt;print(&quot;A handler of type &#39;$type&#39; was called&quot;);
  
      return Apache2::Const::OK;
  }
  
  1;</code></pre>

<p>In the example we have used the following mapping.</p>

<pre><code>  my %exts = (
      cgi =&gt; [&#39;perl-script&#39;,     \&amp;cgi_handler],
      pl  =&gt; [&#39;modperl&#39;,         \&amp;pl_handler ],
      tt  =&gt; [&#39;perl-script&#39;,     \&amp;tt_handler ],
      txt =&gt; [&#39;default-handler&#39;, undef        ],
  );</code></pre>

<p>So that <i>.cgi</i> requests will be handled by the <code>perl-script</code> handler and the <code>cgi_handler()</code> callback, <i>.pl</i> requests by <code>modperl</code> and <code>pl_handler()</code>, <i>.tt</i> (template toolkit) by <code>perl-script</code> and the <code>tt_handler()</code>, finally <i>.txt</i> request by the <code>default-handler</code> handler, which requires no callback.</p>

<p>Moreover the handler assumes that if the request&#39;s URI has no file extension or it does, but it&#39;s not in its mapping, the <code>default-handler</code> will be used, as if the <i>txt</i> extension was used.</p>

<p>After doing the mapping, the handler assigns the handler:</p>

<pre><code>      $r-&gt;handler($exts{$ext}-&gt;[HANDLER]);</code></pre>

<p>and the callback if needed:</p>

<pre><code>      if (defined $exts{$ext}-&gt;[CALLBACK]) {
          $r-&gt;set_handlers(
                          PerlResponseHandler =&gt; $exts{$ext}-&gt;[CALLBACK]);
      }</code></pre>

<p>In this simple example the callback functions don&#39;t do much but calling the same content handler which simply prints the name of the extension if handled by mod_perl, otherwise Apache will serve the other files using the default handler. In real world you will use callbacks to real content handlers that do real things.</p>

<p>Here is how this handler is configured:</p>

<pre><code>  Alias /dispatch/ /home/httpd/httpd-2.0/htdocs/
  &lt;Location /dispatch/&gt;
      PerlFixupHandler MyApache2::FileExtDispatch
  &lt;/Location&gt;</code></pre>

<p>Notice that there is no need to specify anything, but the fixup handler. It applies the rest of the settings dynamically at run-time.</p>

<h2 id="PerlResponseHandler1">PerlResponseHandler</h2>

<p>The <i>handler</i> (<i>response</i>) phase is used for generating the response. This is arguably the most important phase and most of the existing Apache modules do most of their work at this phase.</p>

<p>This is the only phase that requires two directives under mod_perl. For example:</p>

<pre><code>  &lt;Location /perl&gt;
     SetHandler perl-script
     PerlResponseHandler MyApache2::WorldDomination
  &lt;/Location&gt;</code></pre>

<p><code>SetHandler</code> set to <code><a>perl-script</a></code> or <code><a>modperl</a></code> tells Apache that mod_perl is going to handle the response generation. <code>PerlResponseHandler</code> tells mod_perl which callback is going to do the job.</p>

<p>This phase is of type <code><a>RUN_FIRST</a></code>.</p>

<p>The handler&#39;s configuration scope is <code><a>DIR</a></code>.</p>

<p><b>Arguments</b></p>

<p>See the <a>HTTP Request Handler Skeleton</a> for a description of handler arguments.</p>

<p><b>Return</b></p>

<p>See <a>Stacked Handlers</a> for a description of handler return codes.</p>

<p><b>Examples</b></p>

<p>Most of the <code>Apache::</code> modules on CPAN are dealing with this phase. In fact most of the developers spend the majority of their time working on handlers that generate response content.</p>

<p>Let&#39;s write a simple response handler, that just generates some content. This time let&#39;s do something more interesting than printing <i>&quot;Hello world&quot;</i>. Let&#39;s write a handler that prints itself:</p>

<pre><code>  #file:MyApache2/Deparse.pm
  #------------------------
  package MyApache2::Deparse;
  
  use strict;
  use warnings;
  
  use Apache2::RequestRec ();
  use Apache2::RequestIO ();
  use B::Deparse ();
  
  use Apache2::Const -compile =&gt; &#39;OK&#39;;
  
  sub handler {
      my $r = shift;
  
      $r-&gt;content_type(&#39;text/plain&#39;);
      $r-&gt;print(&#39;sub handler &#39;, B::Deparse-&gt;new-&gt;coderef2text(\&amp;handler));
  
      return Apache2::Const::OK;
  }
  1;</code></pre>

<p>To enable this handler add to <i>httpd.conf</i>:</p>

<pre><code>  &lt;Location /deparse&gt;
      SetHandler modperl
      PerlResponseHandler MyApache2::Deparse
  &lt;/Location&gt;</code></pre>

<p>Now when the server is restarted and we issue a request to <i>http://localhost/deparse</i> we get the following response:</p>

<pre><code>  sub handler {
      package MyApache2::Deparse;
      use warnings;
      use strict &#39;refs&#39;;
      my $r = shift @_;
      $r-&gt;content_type(&#39;text/plain&#39;);
      $r-&gt;print(&#39;sub handler &#39;, &#39;B::Deparse&#39;-&gt;new-&gt;coderef2text(\&amp;handler));
      return 0;
  }</code></pre>

<p>If you compare it to the source code, it&#39;s pretty much the same code. <code>B::Deparse</code> is fun to play with!</p>

<h2 id="PerlLogHandler1">PerlLogHandler</h2>

<p>The <i>log_transaction</i> phase happens no matter how the previous phases have ended up. If one of the earlier phases has aborted a request, e.g., failed authentication or 404 (file not found) errors, the rest of the phases up to and including the response phases are skipped. But this phase is always executed.</p>

<p>By this phase all the information about the request and the response is known, therefore the logging handlers usually record this information in various ways (e.g., logging to a flat file or a database).</p>

<p>This phase is of type <code><a>RUN_ALL</a></code>.</p>

<p>The handler&#39;s configuration scope is <code><a>DIR</a></code>.</p>

<p><b>Arguments</b></p>

<p>See the <a>HTTP Request Handler Skeleton</a> for a description of handler arguments.</p>

<p><b>Return</b></p>

<p>See <a>Stacked Handlers</a> for a description of handler return codes.</p>

<p><b>Examples</b></p>

<p>Imagine a situation where you have to log requests into individual files, one per user. Assuming that all requests start with <i>/~username/</i>, so it&#39;s easy to categorize requests by the username. Here is the log handler that does that:</p>

<pre><code>  #file:MyApache2/LogPerUser.pm
  #---------------------------
  package MyApache2::LogPerUser;
  
  use strict;
  use warnings;
  
  use Apache2::RequestRec ();
  use Apache2::Connection ();
  
  use Fcntl qw(:flock);
  use File::Spec::Functions qw(catfile);
  
  use Apache2::Const -compile =&gt; qw(OK DECLINED);
  
  sub handler {
      my $r = shift;
  
      my ($username) = $r-&gt;uri =~ m|^/~([^/]+)|;
      return Apache2::Const::DECLINED unless defined $username;
  
      my $entry = sprintf qq(%s [%s] &quot;%s&quot; %d %d\n),
          $r-&gt;connection-&gt;remote_ip, scalar(localtime),
          $r-&gt;uri, $r-&gt;status, $r-&gt;bytes_sent;
  
      my $log_path = catfile Apache2::ServerUtil::server_root,
          &quot;logs&quot;, &quot;$username.log&quot;;
      open my $fh, &quot;&gt;&gt;$log_path&quot; or die &quot;can&#39;t open $log_path: $!&quot;;
      flock $fh, LOCK_EX;
      print $fh $entry;
      close $fh;
  
      return Apache2::Const::OK;
  }
  1;</code></pre>

<p>First the handler tries to figure out what username the request is issued for, if it fails to match the URI, it simply returns <code>Apache2::Const::DECLINED</code>, letting other log handlers to do the logging. Though it could return <code>Apache2::Const::OK</code> since all other log handlers will be run anyway.</p>

<p>Next it builds the log entry, similar to the default <i>access_log</i> entry. It&#39;s comprised of remote IP, the current time, the uri, the return status and how many bytes were sent to the client as a response body.</p>

<p>Finally the handler appends this entry to the log file for the user the request was issued for. Usually it&#39;s safe to append short strings to the file without being afraid of messing up the file, when two files attempt to write at the same time, but just to be on the safe side the handler exclusively locks the file before performing the writing.</p>

<p>To configure the handler simply enable the module with the <code>PerlLogHandler</code> directive, for the desired URI namespace (starting with : <i>/~</i> in our example):</p>

<pre><code>  &lt;LocationMatch &quot;^/~&quot;&gt;
      SetHandler perl-script
      PerlResponseHandler ModPerl::Registry
      PerlLogHandler MyApache2::LogPerUser
      Options +ExecCGI
  &lt;/LocationMatch&gt;</code></pre>

<p>After restarting the server and issuing requests to the following URIs:</p>

<pre><code>  http://localhost/~stas/test.pl
  http://localhost/~eric/test.pl
  http://localhost/~stas/date.pl</code></pre>

<p>The <code>MyApache2::LogPerUser</code> handler will append to <i>logs/stas.log</i>:</p>

<pre><code>  127.0.0.1 [Sat Aug 31 01:50:38 2002] &quot;/~stas/test.pl&quot; 200 8
  127.0.0.1 [Sat Aug 31 01:50:40 2002] &quot;/~stas/date.pl&quot; 200 44</code></pre>

<p>and to <i>logs/eric.log</i>:</p>

<pre><code>  127.0.0.1 [Sat Aug 31 01:50:39 2002] &quot;/~eric/test.pl&quot; 200 8</code></pre>

<p>It&#39;s important to notice that <code>PerlLogHandler</code> can be configured for any subsection of the site, no matter whether it&#39;s served by a mod_perl response handler or not. For example to run the handler from our example for all requests to the server, simply add to <i>httpd.conf</i>:</p>

<pre><code>  &lt;Location /&gt;
      PerlLogHandler MyApache2::LogPerUser
  &lt;/Location&gt;</code></pre>

<p>Since the <code>PerlLogHandler</code> phase is of type <code><a>RUN_ALL</a></code>, all other logging handlers will be called as well.</p>

<h2 id="PerlCleanupHandler1">PerlCleanupHandler</h2>

<p>There is no <i>cleanup</i> Apache phase, it exists only inside mod_perl. It is used to execute some code immediately after the request has been served (the client went away) and before the request object is destroyed.</p>

<p>There are several usages for this use phase. The obvious one is to run a cleanup code, for example removing temporarily created files. The less obvious is to use this phase instead of <code><a href="#PerlLogHandler">PerlLogHandler</a></code> if the logging operation is time consuming. This approach allows one to free the client as soon as the response is sent.</p>

<p>This phase is of type <code><a>RUN_ALL</a></code>.</p>

<p>The handler&#39;s configuration scope is <code><a>DIR</a></code>.</p>

<p><b>Arguments</b></p>

<p>See the <a>HTTP Request Handler Skeleton</a> for a description of handler arguments.</p>

<p><b>Return</b></p>

<p>See <a>Stacked Handlers</a> for a description of handler return codes.</p>

<p><b>Examples</b></p>

<p>There are two ways to register and run cleanup handlers:</p>

<dl>

<dt id="Using-the-PerlCleanupHandler-phase">1 Using the <code>PerlCleanupHandler</code> phase</dt>
<dd>

<pre><code>  PerlCleanupHandler MyApache2::Cleanup</code></pre>

<p>or:</p>

<pre><code>  $r-&gt;push_handlers(PerlCleanupHandler =&gt; \&amp;cleanup);</code></pre>

<p>This method is identical to all other handlers.</p>

<p>In this technique the <code>cleanup()</code> callback accepts <code>$r</code> as its only argument.</p>

</dd>
<dt id="Using-cleanup_register-acting-on-the-request-objects-pool">2 Using <code>cleanup_register()</code> acting on the request object&#39;s pool</dt>
<dd>

<p>Since a request object pool is destroyed at the end of each request, we can use <code><a>cleanup_register</a></code> to register a cleanup callback which will be executed just before the pool is destroyed. For example:</p>

<pre><code>    $r-&gt;pool-&gt;cleanup_register(\&amp;cleanup, $arg);</code></pre>

<p>The important difference from using the <code>PerlCleanupHandler</code> handler, is that here you can pass an optional arbitrary argument to the callback function, and no <code>$r</code> argument is passed by default. Therefore if you need to pass any data other than <code>$r</code> you may want to use this technique.</p>

</dd>
</dl>

<p>Here is an example where the cleanup handler is used to delete a temporary file. The response handler is running <code>ls -l</code> and stores the output in temporary file, which is then used by <code>$r-&gt;sendfile</code> to send the file&#39;s contents. We use <code>push_handlers()</code> to push <code>PerlCleanupHandler</code> to unlink the file at the end of the request.</p>

<pre><code>  #file:MyApache2/Cleanup1.pm
  #-------------------------
  package MyApache2::Cleanup1;
  
  use strict;
  use warnings FATAL =&gt; &#39;all&#39;;
  
  use File::Spec::Functions qw(catfile);
  
  use Apache2::RequestRec ();
  use Apache2::RequestIO ();
  use Apache2::RequestUtil ();
  
  use Apache2::Const -compile =&gt; qw(OK DECLINED);
  use APR::Const    -compile =&gt; &#39;SUCCESS&#39;;
  
  my $file = catfile &quot;/tmp&quot;, &quot;data&quot;;
  
  sub handler {
      my $r = shift;
  
      $r-&gt;content_type(&#39;text/plain&#39;);
  
      local @ENV{qw(PATH BASH_ENV)};
      qx(/bin/ls -l &gt; $file);
  
      my $status = $r-&gt;sendfile($file);
      die &quot;sendfile has failed&quot; unless $status == APR::Const::SUCCESS;
  
      $r-&gt;push_handlers(PerlCleanupHandler =&gt; \&amp;cleanup);
  
      return Apache2::Const::OK;
  }
  
  sub cleanup {
      my $r = shift;
  
      die &quot;Can&#39;t find file: $file&quot; unless -e $file;
      unlink $file or die &quot;failed to unlink $file&quot;;
  
      return Apache2::Const::OK;
  }
  1;</code></pre>

<p>Next we add the following configuration:</p>

<pre><code>  &lt;Location /cleanup1&gt;
      SetHandler modperl
      PerlResponseHandler MyApache2::Cleanup1
  &lt;/Location&gt;</code></pre>

<p>Now when a request to <i>/cleanup1</i> is made, the contents of the current directory will be printed and once the request is over the temporary file is deleted.</p>

<p>This response handler has a problem of running in a multi-process environment, since it uses the same file, and several processes may try to read/write/delete that file at the same time, wrecking havoc. We could have appended the process id <code>$$</code> to the file&#39;s name, but remember that mod_perl 2.0 code may run in the threaded environment, meaning that there will be many threads running in the same process and the <code>$$</code> trick won&#39;t work any longer. Therefore one really has to use this code to create unique, but predictable, file names across threads and processes:</p>

<pre><code>  sub unique_id {
      require Apache2::MPM;
      require APR::OS;
      return Apache2::MPM-&gt;is_threaded
          ? &quot;$$.&quot; . ${ APR::OS::current_thread_id() }
          : $$;
  }</code></pre>

<p>In the threaded environment it will return a string containing the process ID, followed by a thread ID. In the non-threaded environment only the process ID will be returned. However since it gives us a predictable string, they may still be a non-satisfactory solution. Therefore we need to use a random string. We can either either Perl&#39;s <code>rand</code>, some CPAN module or the APR&#39;s <code>APR::UUID</code>:</p>

<pre><code> sub unique_id {
  require APR::UUID;
  return APR::UUID-&gt;new-&gt;format;
 }</code></pre>

<p>Now the problem is how do we tell the cleanup handler what file should be cleaned up? We could have stored it in the <code>$r-&gt;notes</code> table in the response handler and then retrieve it in the cleanup handler. However there is a better way - as mentioned earlier, we can register a callback for request pool cleanup, and when using this method we can pass an arbitrary argument to it. Therefore in our case we choose to pass the file name, based on random string. Here is a better version of the response and cleanup handlers, that uses this technique:</p>

<pre><code> #file:  MyApache2/Cleanup2.pm
 #-------------------------
 package MyApache2::Cleanup2;
  
 use strict;
 use warnings FATAL =&gt; &#39;all&#39;;
  
 use File::Spec::Functions qw(catfile);
  
 use Apache2::RequestRec ();
 use Apache2::RequestIO ();
 use Apache2::RequestUtil ();
 use APR::UUID ();
 use APR::Pool ();
  
 use Apache2::Const -compile =&gt; qw(OK DECLINED);
 use APR::Const    -compile =&gt; &#39;SUCCESS&#39;;
  
 my $file_base = catfile &quot;/tmp&quot;, &quot;data-&quot;;
  
 sub handler {
         my $r = shift;
  
     $r-&gt;content_type(&#39;text/plain&#39;);
     my $file = $file_base . APR::UUID-&gt;new-&gt;format;
  
     local @ENV{qw(PATH BASH_ENV)};
     qx(/bin/ls -l &gt; $file);
  
     my $status = $r-&gt;sendfile($file);
     die &quot;sendfile has failed&quot; unless $status == APR::Const::SUCCESS;
  
     $r-&gt;pool-&gt;cleanup_register(\&amp;cleanup, $file);
  
     return Apache2::Const::OK;
 }
  
 sub cleanup {
     my $file = shift;
  
     die &quot;Can&#39;t find file: $file&quot; unless -e $file;
     unlink $file or die &quot;failed to unlink $file&quot;;
  
     return Apache2::Const::OK;
 }
 1;</code></pre>

<p>Similarly to the first handler, we add the configuration:</p>

<pre><code> &lt;Location /cleanup2&gt;
     SetHandler modperl
     PerlResponseHandler MyApache2::Cleanup2
 &lt;/Location&gt;</code></pre>

<p>And now when requesting <i>/cleanup2</i> we still get the same output -- the listing of the current directory -- but this time this code will work correctly in the multi-processes/multi-threaded environment and temporary files get cleaned up as well.</p>

<h3 id="Possible-Caveats">Possible Caveats</h3>

<p><code>PerlCleanupHandler</code> may fail to be completed on server shutdown/graceful restart since Apache will kill the registered handlers via SIGTERM, before they had a chance to run or even in the middle of its execution. See: http://marc.theaimsgroup.com/?t=106387845200003&amp;r=1&amp;w=2 http://marc.theaimsgroup.com/?l=apache-modperl-dev&amp;m=106427616108596&amp;w=2</p>

<h1 id="Miscellaneous-Issues">Miscellaneous Issues</h1>

<h2 id="Handling-HEAD-Requests">Handling HEAD Requests</h2>

<p>In order to avoid the overhead of sending the data to the client when the request is of type HEAD in mod_perl 1.0 we <a>used to return early</a> from the handler:</p>

<pre><code> return Apache2::Const::OK if $r-&gt;header_only;</code></pre>

<p>This logic should not be used in mod_perl 2.0, because Apache 2.0 automatically discards the response body for HEAD requests. It expects the full body to generate the correct set of response headers, if you don&#39;t send the body you may encounter problems.</p>

<p>(You can also read the comment in for <code>ap_http_header_filter()</code> in <i>modules/http/http_protocol.c</i> in the Apache 2.0 source.)</p>

<h2 id="Content-Length-Response-Header"><code>Content-Length</code> Response Header</h2>

<p>You may encounter some issues with the C-L (<code>Content-Length</code>) header. Some of them are discussed here.</p>

<ul>

<li><p>The special case of <code>Content-Length: 0</code></p>

<p>Since Apache proclaims itself governor of the C-L header via the C-L filter (ap_content_length_filter at <i>httpd-2.0/server/protocol.c</i>), for the most part <code>GET</code> and <code>HEAD</code> behave exactly the same. However, when Apache sees a <code>HEAD</code> request with a C-L header of zero it takes special action and removes the C-L header. This is done to protect against handlers that called <code>$r-&gt;header_only</code> (<a href="#Handling_HEAD_Requests">which was ok in 1.3 but is not in 2.0</a>). Therefore, <code>GET</code> and <code>HEAD</code> behave identically, except when the content handler (and/or filters) end up sending no content. For more details refer to the lengthy comments in <code>ap_http_header_filter()</code> in <i>httpd-2.0/modules/http/http_protocol.c</i>).</p>

<p>For more discussion on why it is important to get HEAD requests right, see these threads from the mod_perl list:</p>

<pre><code> http://marc.theaimsgroup.com/?l=apache-modperl&amp;m=108647669726915&amp;w=2
 http://marc.theaimsgroup.com/?t=109122984600001&amp;r=1&amp;w=2</code></pre>

<p>as well as this bug report from mozilla, which shows how <code>HEAD</code> requests are used in the wild:</p>

<pre><code> http://bugzilla.mozilla.org/show_bug.cgi?id=245447</code></pre>

</li>
<li><p>Not getting <code>Content-Length</code> header with <code>HEAD</code> requests</p>

<p>Even though the spec says that content handlers should send an identical response for GET and HEAD requests, some folks try to <a href="#Handling_HEAD_Requests">avoid the overhead of generating the response body</a>, which Apache is going to discard anyway for HEAD requests. The following discussion assumes that we deal with a HEAD request.</p>

<p>When Apache sees EOS and no headers and no response body were sent, <code>ap_content_length_filter()</code> (<i>httpd-2.0/server/protocol.c</i>) sets C-L to 0. Later on <code>ap_http_header_filter()</code> (<i>httpd-2.0/modules/http/http_protocol.c</i>) removes the C-L header for the HEAD requests.</p>

<p>The workaround is to force the sending of the response headers, before <code>EOS</code> was sent (which happens when the response handler returns). The simplest solution is to use rflush():</p>

<pre><code> if ($r-&gt;header_only) { # HEAD
     $body_len = calculate_body_len();
     $r-&gt;set_content_length($body_len);
     $r-&gt;rflush;
 }
 else {                 # GET
     # generate and send the body
 }</code></pre>

<p>now if the handler sets the C-L header it&#39;ll be delivered to the client unmodified.</p>

</li>
</ul>

<h1 id="Misc-Notes">Misc Notes</h1>

<p>These items will need to be extended and integrated in this or other HTTP related documents:</p>

<ul>

<li><p>front-end back-end setup: mod_proxy+X-Forwarded-For</p>

<p>apache-1.3:</p>

<p>frontend: mod_proxy_add_forward http://develooper.com/code/mpaf/</p>

<p>backend: mod_rpaf (reverse proxy add forward): http://stderr.net/apache/rpaf/</p>

<p>apache-2.x:</p>

<p>frontend: mod_proxy</p>

<p>backend: mod_rpaf: http://stderr.net/apache/rpaf/</p>

</li>
</ul>

<h1 id="Extending-HTTP-Protocol">Extending HTTP Protocol</h1>

<p>Extending HTTP under mod_perl is a trivial task. Look at <a href="#PerlHeaderParserHandler">the example of adding a new method <code>EMAIL</code></a> for details.</p>

<h1 id="HTTP-Status-Codes">HTTP Status Codes</h1>

<p>The Hypertext Transfer Protocol (HTTP) is an application-level protocol for distributed, collaborative, hypermedia information systems. It is a generic, stateless, protocol which can be used for many tasks beyond its use for hypertext, such as name servers and distributed object management systems, through extension of its request methods, error codes and headers. A feature of HTTP is the typing and negotiation of data representation, allowing systems to be built independently of the data being transferred.</p>

<p>HTTP 1.0 is described in Requests For Comments (RFC) 1945. HTTP 1.1 is the latest version of the specifications and as of this writing HTTP 1.1 is covered in RFC 2616.</p>

<p>When writing mod_perl applications, usually only a small subset of HTTP response codes is used, but sometimes you need to know others as well. We will give a short description of each code and you will find the extended explanation in the appropriate RFC. (Section 9 in RFC 1945 and section 10 in RFC 2616). You can always find the latest link to these RFCs at the Web Consortium site, <i>http://www.w3.org/Protocols/</i>.</p>

<p>While HTTP 1.1 is widely supported, HTTP 1.0 still remains the mainstream standard. Therefore we will supply a summary of the both versions including the corresponding Apache constants.</p>

<p>In mod_perl these constants can be accessed the <code><a>Apache::Constants</a></code> package (e.g., to access the HTTP_OK constant use <code>Apache::Constants::HTTP_OK</code>). See the <code><a>Apache::Constants</a></code> manpage for more information.</p>

<p>In mod_perl2 these constants can be accessed the <code><a>Apache2::Const</a></code> package (e.g., to access the HTTP_OK constant use <code>Apache2::Const::HTTP_OK</code>). See the <code><a>Apache2::Const</a></code> manpage for more information.</p>

<h2 id="HTTP-1.0-Status-Codes">HTTP 1.0 Status Codes</h2>

<ul>

<li><p>Successful 2xx:</p>

<pre><code> 200 HTTP_OK                    OK
 201 HTTP_CREATED               Created
 202 HTTP_ACCEPTED              Accepted
 204 HTTP_NO_CONTENT            No Content</code></pre>

</li>
<li><p>Redirection 3xx:</p>

<pre><code> 301 HTTP_MOVED_PERMANENTLY     Multiple Choices
 302 HTTP_MOVED_TEMPORARILY     Moved Permanently
 303 HTTP_SEE_OTHER             Moved Temporarily
 304 HTTP_NOT_MODIFIED          Not Modified</code></pre>

</li>
<li><p>Client Error 4xx:</p>

<pre><code> 400 HTTP_BAD_REQUEST           Bad Request
 401 HTTP_UNAUTHORIZED          Unauthorized
 403 HTTP_FORBIDDEN             Forbidden
 404 HTTP_NOT_FOUND             Not Found</code></pre>

</li>
<li><p>Server Error 5xx:</p>

<pre><code> 500 HTTP_INTERNAL_SERVER_ERROR Internal Server Error
 501 HTTP_NOT_IMPLEMENTED       Not Implemented
 502 HTTP_BAD_GATEWAY           Bad Gateway
 503 HTTP_SERVICE_UNAVAILABLE   Service UnavailableStatus Codes</code></pre>

</li>
</ul>

<h2 id="HTTP-1.1-Status-Codes">HTTP 1.1 Status Codes</h2>

<ul>

<li><p>Informational 1xx:</p>

<pre><code> 100 HTTP_CONTINUE                        Continue
 101 HTTP_SWITCHING_PROTOCOLS             Switching Protocols</code></pre>

</li>
<li><p>Successful 2xx:</p>

<pre><code> 200 HTTP_OK                              OK
 201 HTTP_CREATED                         Created
 202 HTTP_ACCEPTED                        Accepted
 203 HTTP_NON_AUTHORITATIVE               Non-Authoritative Information
 204 HTTP_NO_CONTENT                      No Content
 205 HTTP_RESET_CONTENT                   Reset Content
 206 HTTP_PARTIAL_CONTENT                 Partial Content</code></pre>

</li>
<li><p>Redirection 3xx:</p>

<pre><code> 300 HTTP_MULTIPLE_CHOICES                Multiple Choices
 301 HTTP_MOVED_PERMANENTLY               Moved Permanently
 302 HTTP_MOVED_TEMPORARILY               Found
 303 HTTP_SEE_OTHER                       See Other
 304 HTTP_NOT_MODIFIED                    Not Modified
 305 HTTP_USE_PROXY                       Use Proxy
 306                                      (Unused)
 307 HTTP_TEMPORARY_REDIRECT              Temporary Redirect</code></pre>

</li>
<li><p>Client Error 4xx:</p>

<pre><code> 400 HTTP_BAD_REQUEST                     Bad Request
 401 HTTP_UNAUTHORIZED                    Unauthorized
 402 HTTP_PAYMENT_REQUIRED                Payment Required
 403 HTTP_FORBIDDEN                       Forbidden
 404 HTTP_NOT_FOUND                       Not Found
 405 HTTP_METHOD_NOT_ALLOWED              Method Not Allowed
 406 HTTP_NOT_ACCEPTABLE                  Not Acceptable
 407 HTTP_PROXY_AUTHENTICATION_REQUIRED   Proxy Authentication Required
 408 HTTP_REQUEST_TIMEOUT                 Request Timeout
 409 HTTP_CONFLICT                        Conflict
 410 HTTP_GONE                            Gone
 411 HTTP_LENGTH REQUIRED                 Length Required
 412 HTTP_PRECONDITION_FAILED             Precondition Failed
 413 HTTP_REQUEST_ENTITY_TOO_LARGE        Request Entity Too Large
 414 HTTP_REQUEST_URI_TOO_LARGE           Request-URI Too Long
 415 HTTP_UNSUPPORTED_MEDIA_TYPE          Unsupported Media Type
 416 HTTP_RANGE_NOT_SATISFIABLE           Requested Range Not Satisfiable
 417 HTTP_EXPECTATION_FAILED              Expectation Failed</code></pre>

</li>
<li><p>Server Error 5xx:</p>

<pre><code> 500 HTTP_INTERNAL_SERVER_ERROR           Internal Server Error
 501 HTTP_NOT IMPLEMENTED                 Not Implemented
 502 HTTP_BAD_GATEWAY                     Bad Gateway
 503 HTTP_SERVICE_UNAVAILABLE             Service Unavailable
 504 HTTP_GATEWAY_TIME_OUT                Gateway Timeout
 505 HTTP_VERSION_NOT_SUPPORTED           HTTP Version Not Supported</code></pre>

</li>
</ul>

<h2 id="References">References</h2>

<p>All the information related to web protocols can be found at the World Wide Web Consortium site, <i>http://www.w3.org/Protocols/</i>.</p>

<p>There are many mirrors of the RFCs all around the world. One of the good starting points might be <i>http://www.rfc-editor.org/</i>.</p>

<p>The Eagle Book provided much of the HTTP constants material shown here <i>http://www.modperl.com/book/chapters/ch9.html#The_Apache_Constants_Class</i></p>

<h1 id="Maintainers">Maintainers</h1>

<p>Maintainer is the person(s) you should contact with updates, corrections and patches.</p>

<ul>

<li><p><a>The mod_perl development team and numerous contributors</a>.</p>

</li>
</ul>

<h1 id="Authors">Authors</h1>

<ul>

<li><p>Stas Bekman [http://stason.org/]</p>

</li>
</ul>

<p>Only the major authors are listed above. For contributors see the Changes file.</p>


</body>

</html>