Apache 2.4 module to allow Pascal program to be executed just like scripting language
Apache 2.4 module implementation which is capable of executing Pascal program just like scripting language.
$ git clone https://github.com/zamronypj/mod_pascal.git
$ cd mod_pascal && ./setup.cfg.sh && ./build.sh
If compilation is successful, new executable binary will be created bin/mod_pascal.so
.
For example in Debian,
Create pascal.conf
file in /etc/apache2/mods-available
directory with content as follows,
<IfModule pascal_module>
# handle all files having .pas extension
AddHandler pascal-handler .pas
</IfModule>
Create pascal.load
file in /etc/apache2/mods-available
directory with content as follows,
LoadModule pascal_module /path/to/mod_pascal.so
Do not forget to replace /path/to/mod_pascal.so
with actual path of mod_pascal.so
. It is important that you use pascal_module
to identify mod_pascal module and
pascal-handler
to identify handler.
Create symlink to pascal.conf
and pascal.load
in /etc/apache2/mods-enabled
directory
$ cd /etc/apache2/mods-enabled
$ sudo ln -s /etc/apache2/mods-available/pascal.conf
$ sudo ln -s /etc/apache2/mods-available/pascal.load
Alternatively, you can also use a2enmod
command to enable mod_pascal.
$ sudo a2enmod pascal
$ sudo systemctl restart apache2
Create Pascal program, for example /var/www/html/test.pas
with content as follows,
begin
writeln('Hello from Pascal');
end.
Open URL http://localhost/test.pas from Internet browser, you should see text Hello from Pascal
printed in browser otherwise things may have gone wrong
When not set, Content-Type
response header is assumed text/html
.
To return response with header, add header line separated by newline
begin
writeln('Content-Type: text/html');
writeln();
writeln('<h1>Hello from Pascal</h1>');
end.
or as JSON
begin
writeln('Content-Type: application/json');
writeln();
writeln('{"message":"Hello from Pascal"}');
end.
Please note that, because blank newline is used to mark end of header parts of response, for safety, always add them even if you do not want to set response header. For example
begin
writeln();
writeln();
writeln('<h1>Hello from Pascal</h1>');
end.
Code below will cause incorrect response
begin
writeln('<h1>Hello from Pascal</h1>');
writeln();
writeln('test');
end.
To fix it, add blank newline at beginning,
begin
writeln();
writeln();
writeln('<h1>Hello from Pascal</h1>');
writeln();
writeln('test');
end.
Or replace first writeln()
with write
()`,
begin
write('<h1>Hello from Pascal</h1>');
writeln();
writeln('test');
end.
From inside pascal program, CGI environment variables can be read using getEnvironmentVariable()
, getEnvironmentVariableCount()
and getEnvironmentString()
functions which is declared in SysUtils
unit. For example,
uses sysutils;
var
i:integer;
begin
writeln('<ul>');
for i:= 1 to getEnvironmentVariableCount do
begin
writeln('<li>', getEnvironmentString(i), '</li>');
end;
writeln('</ul>');
end.
Any request body can be read from STDIN. CONTENT_LENGTH
environment variable will contains total bytes of request body. For example, if you send following request,
POST /test.pas HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Accept: */*
Cache-Control: no-cache
Host: localhost
Accept-Encoding: gzip, deflate, br
Content-Length: 45
Connection: keep-alive
test=hello&id=12345&user=myuser%40example.com
CONTENT_LENGTH
environment variable will contains string 45
which means there is 45 bytes of data in STDIN available to read which is equal to length of string,
test=hello&id=12345&user=myuser%40example.com
If content length is greater than 0, your application needs to read it even if you do not require it.
uses
sysutils;
var
contentLen : integer;
requestBody : string;
ch : char;
begin
writeln('Request body:');
contentLen := strToInt(getEnvironmentVariable('CONTENT_LENGTH'));
if contentLen <> 0 then
begin
requestBody := '';
repeat
read(ch);
requestBody := requestBody + ch;
dec(contentLen);
until contentLen = 0;
writeln(requestBody);
end;
end.
By default, when not set, it is assumed that Free Pascal compiler path is
/usr/local/bin/fpc
, InstantFPC path is /usr/local/bin/instantfpc
and cache directory
in /tmp
. You can set it to match your system as follows
<IfModule pascal_module>
AddHandler pascal-handler .pas
FpcBin /path/to/fpc
InstantFpcBin /path/to/instantfpc
InstantFpcCacheDir /path/to/cache/dir
</IfModule>
You need to make sure that cache directory is writeable by web server. After make any changes, restart Apache server.
You can set any compiler configurations by creating fpc.cfg
file in directory where pascal program resides. For example with content as follows,
# add configuration from default configuration
#INCLUDE /etc/fpc.cfg
# compile with level 3 optimization
-O3
This is experimental project. Using it in production setup should be avoided. Performance is not very good due to initial compilation task that is required when any of source codes are changed. When source codes are not changed, next execution will avoid compilation step thus give similar performance of CGI executable.
Make sure you set correct path to mod_pascal.so
in pascal.load
file.
If test.pas
is downloaded then you do not register mod_pascal
with Apache correctly. Make sure that you use correct name for handler and module which is pascal-handler
and pascal-module
respectively.
If browser reports “The connection to the server was reset while the page was loading.” check /var/log/apache/error.log
for error. If you get
An unhandled exception occurred at $00007FAB82297C74:
EProcess: Executable not found: "/usr/local/bin/instantfpc"
$00007FAB82297C74
Make sure you set correct path for Free Pascal compiler and InstantFpc binaries. You can either set FpcBin
and InstantFpcBin
in module configuration or create symlink to those binaries. If you set in module configuration, do not forget to restart Apache service after making changes.
You get error Undefined symbol "operatingsystem_parameter_envp"
# apachectl restart
Performing sanity check on apache24 configuration:
httpd: Syntax error on line 183 of /usr/local/etc/apache24/httpd.conf: Syntax error on line 9 of /usr/local/etc/apache24/modules.d/300_mod_pascal.conf: Cannot load libexec/apache24/mod_pascal.so into server: /usr/local/libexec/apache24/mod_pascal.so: Undefined symbol "operatingsystem_parameter_envp"