Solved: Cant get FPC fpweb Apache 2.4 module to work. Ubuntu 24.04,
Lazarus 4.0
lazarus / 38-Networking and Web Programming
----------------------------------------------------------------------
vangli · 2025-07-23 18:27
Hi. I am running:
Ubuntu 24.04 (64 bit)
Apache 2.4.54
Lazarus 4.0
FPC 3.2.2
Following the tutorial:
https://wiki.lazarus.freepascal.org/fpWeb_Tutorial
I started with creating new apache module application from Lazarus
list of new projects, just renaming some paramters.
I am not able to get this simple module (atached and showed below) to
work on an Apache 2.4 server installation. It seems to install
correctly, and are listed as shared installed module according to
apachectl -M. When module is disabled in apache configuration, a test
file is viewed in a connected browser. When activated I got a time out
with the following error in the apache error log:
An unhandled exception occurred at $00007690F2105239:
EHTTP: No REQUEST_METHOD passed from server.
$00007690F2105239
$00007690F20DEF8C
This message, as far as I can see and traced, is created by some
exception in the unit custapache24. So I am rather certain that the
module is called from Apache. But, what to do?
When compiling I got the the following messages from Lazarus:
Compile Project, Mode: Release, Target:
/home/username/Pascal/MyApacheModul/lib/x86_64-linux/libmod_bvweb.so:
Success, Hints: 2
mainunit.pas(15,50) Hint: Parameter "ARequest" not used
mod_bvweb.lpr(66,44) Hint: Variable "DefaultModule" does not seem to
be initialized
I think this is OK, however a little curious about the "DefaultModule"
not initialized.
My search has revealed that the same EHTTP error occured in reports
several years ago, in earlier versions of Lazarus. I wonder what I am
missing. Is it some initializing I have to do? Do I use the the
turorial in a wrong way? Am I missing some "special" setting in apache
configuration? Or am I a big bug myself? Does anyone know what to
do?
I am doing this as a learning session, and have earlier succesfully
created small CGI for apace, or http server applications using FPC.
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i Library
mod_bvweb; { Add Apache configuration to load module
---------------------------------------- Create bvweb.conf file in
/etc/apache2/mods-available directory with content as follows,
This module works!
'; Handled := True;end; initialization RegisterHTTPModule('BvFPWebModule', TBvFPWebModule);end. Bent, Oslo, Norway ---------------------------------------------------------------------- vangli · 2025-08-01 08:50 Hi I have not been able to find a solution yet, mostly caused by lack of knowledge. However, some observations had been done. The module seems to be correctly loaded and initialized seen from the Apache server side.Viewing Apaches error log show several attempts to call the module before timing out. No request method passed from server.Trying to do some older tricks found on different forums, doesn't work. The Apache server will then not load the module.Using Apache 2.2 and the units for this version, seems to work correctly according to reports on some forums.Could it be one or more of? The module is correctly loaded and initialized by Apache. However the request information, a rather huge record, is wrongly interpreted by the fpc lazweb units, thus giving empty request method.The module is correctly loaded and initialized by Apache. A hook internally in a lazweb unit isn't set or set incorrectly.The module is correctly loaded and initialized by Apache. Some extra user handling/hook/setup is needed for correct interaction with the lazweb units.The module is correctly loaded and initialized by Apache. Some undocumented setup in Apache configuration file is needed.The module is wrongly reported as correctly loaded and initialized by Apache.Personally I don't think 5. is plausible. Any opinions? ---------------------------------------------------------------------- Leledumbo · 2025-08-07 16:24 Use fpc main branch, you simply need to replace fpapache with fpapache24. The module interface between the two Apache versions have changed. ---------------------------------------------------------------------- vangli · 2025-08-07 17:17 Hi Leledumbo Thanks very much for answering. However, I already use fpapache24 as you can see in the example above. I know the original solution was working for Apache 2.2 modules. I also know, not in detail, that the module interface has changed from Apache version 2.2 to 2.4. I am now in process of using an alternative route using the unit apr24 directly. I found a description on Internet which I now try to fit. If I got this to work, I may be able to to trace down the original problem. The Apache module need a hook into the handler name with some type of active response. In version 2.2 you had some default behavior which is not longer implemented for version 2.4, if I correctly understand the API description on Apache.org. I like to have such problems, either it is me myself or in fact a real technical reason. Best regards Bent ---------------------------------------------------------------------- vangli · 2025-08-08 08:12 I found this on gitlab: https://gitlab.com/freepascal.org/fpc/source/- /blob/main/packages/httpd24/examples/mod_hello.pp?ref_type=heads When copying the above example and do some modifications, I got this working Linux (Ubuntu 24.04) example: Code: Pascal [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i library mod_bvweb2;{< Apache 2.4 module. Based uppon https://gitlab.com/fre epascal.org/fpc/source/- /blob/main/packages/httpd24/examples/mod_hello.pp?ref_type=heads } {$m ode ObjFPC}{$H+} uses Classes, SysUtils, httpd24, apr24; const AP24_MODULE_NAME = 'bvweb-module2'; AP24_HANDLER_NAME = 'bvweb- handler2'; var My_Module : module; {$ifdef unix} public name AP24_MODULE_NAME;{$endif} exports My_Module name AP24_MODULE_NAME; function MyHandler(r : Prequest_rec): Integer; cdecl;var RequestedHandler, onerow: ansistring;begin RequestedHandler := r^.handler; if not SameText(RequestedHandler, AP24_HANDLER_NAME) then { May have several handlers. } begin Result := DECLINED; Exit; // Do not handle end; { The following line just prints a message to the errorlog } ap_log_error(AP24_MODULE_NAME, // The file in which this function is called 40, // The line number on which this function is called 0, // The module_index of the module generating this message APLOG_NOERRNO or APLOG_NOTICE, // The level of this error message 0, // The status code from the previous command r^.server, // The server on which we are logging AP24_MODULE_NAME+': %s', // The format string [PAnsiChar('Handler: '+AP24_HANDLER_NAME+'. Before content is output!')]); //The arguments to use to fill out fmt. ap_set_content_type(r, 'text/html'); { If the request is for a header only, and not a request for the whole content, then return OK now. We don't have to do anything else. } if (r^.header_only <> 0) then begin Result := OK; Exit; end; { Now we just print the contents of the document using the ap_rputs and ap_rprintf functions. More information about the use of these can be found in http_protocol.inc } onerow := '' + LineEnding; ap_rwrite(PAnsiChar(onerow), length(onerow), r); onerow := '' + LineEnding; ap_rwrite(PAnsiChar(onerow), length(onerow), r); onerow := 'This is an Apache Module working with the binding from Free Pascal. Filename: ' + MyFileName + '.
' + LineEnding + 'Testing some norwegian special characters (2 byte sizes): ÆØÅ and æøå.
' + LineEnding + '' + LineEnding ;end; //*********** Example 2 *********************************************************//{ This is the second example of userfunction you define yourself. I may be wise to instead create an own unit collecting all proceduresm functions and handling you want to use. }procedure UserProcedure_2 (var S : string; r : Prequest_rec);var SL : TStringList; MyFileName : string;begin MyFileName := r^.filename; SL := TStringList.Create; try with SL do begin Append(''); Append(''); Append('This is an Apache Module working with the binding from Free Pascal. Filename: ' + MyFileName + '.
'); Append('Testing some norwegian special characters (2 byte sizes): ÆØÅ and æøå.
'); Append(''); end; S := SL.Text; finally SL.Free; end;end; //*********** Example 3 *********************************************************//{ This is the third example of userfunction you define yourself. It show using a directory has the triggering point. It also incorporates using parameters sent from the client. It may be wise to create an own unit collecting all procedures, functions and handling you want to use. }procedure UserProcedure_Func(var S : string; r : Prequest_rec);var MyFileName : string; MyArguments : string; MyGetParam : string; MyMethod : string; MyHeaders : papr_table_t; MyGetTable : papr_table_t; MyPostTable : papr_array_header_t; Fields : papr_array_header_t; E : papr_table_entry_t; N : Integer; // Helper variable. P : Pointer; // Helper variable. Used to help me understanding the castings done. And also used for loop count. Res : Integer; // Variable to keep status from parsing. KvpArray : TKeyValueArray;begin MyFileName := r^.filename; // Not working forThis is an Apache Module working with the binding from Free Pascal. URI: ' + MyFileName + '.
' + LineEnding + 'Testing some norwegian special characters (2 byte sizes): ÆØÅ and æøå.
' + LineEnding + 'Testing POST 1:
' + LineEnding + 'This is a function called from location configuration for testing parameters.
' + LineEnding + 'GET parameter: testparam=' + MyGetParam + '.
' + LineEnding + 'Arguments: ' + MyArguments + '.
' + LineEnding + 'Method: ' + MyMethod + '.
' + LineEnding + 'Header count: ' + IntToStr(N) + '.
' + LineEnding; for N := 0 to N - 1 do begin S := S + 'Header ' + IntToStr(N) + ': ' + E[N].key + ' = ' + E[N].val + 'Found ' + IntToStr(MyPostTable^.nelts) + ' POST parameter(s)!
' + LineEnding; S := S + 'Length of POST section: ' + IntToStr(MemSize(MyPostTable)) + '.
' + LineEnding; // Wonder if this is correct! Seems a bit strange. S := S + 'Found the following POST parameter(s):
' + LineEnding; if (Res = OK) or (MyPostTable <> nil) then begin KvpArray := readPost(MyPostTable); for N := 0 to Length(KvpArray) - 1 do begin S := S + 'Key ' + IntToStr(N) + ': ' + KvpArray[N].key + ', Value ' + IntToStr(N) + ': ' + KvpArray[N].value + '.
' + LineEnding; end; end; end; S := S + '' + LineEnding;end; { This is the function that handles requests from the Pache server. The apache server will call every module in turn until one module handles the request represented by the handler name. }function MyHandler(r : Prequest_rec): Integer; cdecl;var RequestedHandler : string; S : string = '';begin RequestedHandler := r^.handler; if not (SameText(RequestedHandler, AP24_HANDLER_NAME) or SameText(RequestedHandler, AP24_HANDLER_NAME2) or SameText(RequestedHandler, AP24_HANDLER_NAME_FUNC) ) then // May have several handlers. Then several tests. If no match, exit imidiate. begin Result := DECLINED; Exit; // Do not handle and return to the Apache server. end; { The following line just prints a message to the errorlog } ap_log_error(AP24_MODULE_NAME, // The file in which this function is called 40, // The line number on which this function is called 0, // The module_index of the module generating this message APLOG_NOERRNO or APLOG_NOTICE, // The level of this error message 0, // The status code from the previous command r^.server, // The server on which we are logging AP24_MODULE_NAME+': %s', // The format string [PAnsiChar('Handler: '+RequestedHandler+'. Before content is output!')]); //The arguments to use to fill out fmt. ap_set_content_type(r, 'text/html;charset=utf8'); // Set page character encoding to UTF8. { If the request is for a header only, and not a request for the whole content, then return OK now. We don't have to do anything else. According to the Apache documentation, setting Result := DONE the server will not further continue to process the request. The result OK may let the server to do more processing in other handlers, typically the logging handle.} if (r^.header_only <> 0) then begin Result := OK; Exit; end; { Now we just print the contents of the document using the ap_rwrite. More information about the use of these can be found in http_protocol.inc. Sometimes you will prefere using ap_rputs() function, like ap_rputs('A text string',r). A simple case statement is useful for selecting correct process based upon the handler name.} case RequestedHandler of AP24_HANDLER_NAME : UserProcedure_1(S,r); AP24_HANDLER_NAME2 : UserProcedure_2(S,r); AP24_HANDLER_NAME_FUNC : UserProcedure_Func(S,r); end; ap_rwrite(PUTF8String(S),Length(S), r); { We can either return OK, DONE or DECLINED at this point. If we return DONE, then no other modules will attempt to process this request } Result := OK;end; {**************************************** **************************** Registers the hooks********************* **********************************************}procedure RegisterHooks(p: Papr_pool_t); cdecl;begin ap_hook_handler(@MyHandler, nil, nil, APR_HOOK_MIDDLE);end; {********* *********************************************************** Library initialization code*************************************************** ****************}begin Initialize(My_Module); FillChar(My_Module, SizeOf(My_Module),0); // Will test if only Initialize() is enough STANDARD20_MODULE_STUFF(My_Module); // Yes, same structure as Apache 2.4. with My_Module do begin name := AP24_MODULE_NAME; register_hooks := @RegisterHooks; end;end. On my server I got this html output from the webserver using example three in above code.This is an Apache Module working with the binding from Free Pascal. URI: /func/test.bv2.
Testing some norwegian special characters (2 byte sizes): ÆØÅ and æøå.
Testing POST 1:
This is a function called from location configuration for testing parameters.
GET parameter: testparam=.
Arguments: testparam1=charlie.
Method: POST.
Header count: 11.
Header 0: Host = ServerNameFound 2 POST parameter(s)!
Length of POST section: 2136.
Found the following POST parameter(s):
Key 0: data2, Value 0: sdfsf.
Key 1: data1, Value 1: abcf.