CGIApache
Background
Euphoria, from Rapid Deployment Software, is a programming language that allows rapid development of almost any kind of application. A natural extension of this is server side scripting. This HOWTO explains how to use the Linux version of Euphoria with Apache version 2.
Various methods
Presented are two methods of accomplishing enabling Euphoria CGI support on Apache2, there are no doubt other methods.
ScriptAlias method
Prerequisites
- A working installation of Euphoria (/usr/local/euphoria is assumed)
- A working installation of Apache2
- Root access to your server (ie total control).
Method
1. Make sure that mod_actions is loaded in your installation of Apache. On Debian the relevant information is:
look under /etc/apache2/mods-enabled for actions.load, eg
myhost:~# ls -l /etc/apache2/mods-enabled/ total 0 lrwxrwxrwx 1 root root 30 Jul 25 14:57 actions.load -> '''../mods-available/actions.load''' lrwxrwxrwx 1 root root 26 Oct 7 2003 cgi.load -> ../mods-available/cgi.load lrwxrwxrwx 1 root root 30 Apr 11 2004 deflate.load -> ../mods-available/deflate.load lrwxrwxrwx 1 root root 30 Oct 28 2003 include.load -> ../mods-available/include.load lrwxrwxrwx 1 root root 27 Apr 11 2004 perl.load -> ../mods-available/perl.load lrwxrwxrwx 1 root root 30 Oct 20 2004 rewrite.load -> ../mods-available/rewrite.load lrwxrwxrwx 1 root root 26 Sep 15 2004 ssl.load -> ../mods-available/ssl.load
If you do not see actions.load you have to enable it, thus:
myhost:~# cd /etc/apache2/mods-enabled myhost:/etc/apache2/mods-enabled# ln -s ../mods-available/actions.load
RESTART APACHE (Debian: /etc/init.d/apache2 restart)
2. Configure Apache to run .exu type files. The method here is to use a wrapper script to run .exu files using the Actions module.
This assumes the following, YMMV.
- cgi-bin is /usr/local/cgi-bin
- exu is at /usr/local/euphoria/bin/exu
- Simple server setup, no virtual hosts.
2a. Apache configuration Edit /etc/apache2/apache2.conf and look for the ScriptAlias directive defining your cgi-bin directory. This should have an AddHandler directive nearby which defines what CGI script extension are allowed on your system, otherwise find this AddHandler directive, ie:
ScriptAlias /cgi-bin/ /usr/lib/cgi-bin AddHandler cgi-script .cgi .plAdd after these lines:
AddHandler exu-file .exu Action exu-file /cgi-bin/runexu.cgi(You can add .ex to AddHandler as well, eg AddHandler exu-file .exu .ex)
2b. Create /cgi-bin/runexu.cgi This is a simple example, you may want to create a more elaborate wrapper, maybe in a shebanged Euphoria program itself. This example uses the bash shell.
runexu.cgi goes in the location identified by the ScriptAlias directive above. eg /usr/lib/cgi-bin/runexu.cgi
#!/bin/sh #runexu.cgi - wrapper to run a euphoria program without the need for #! # Naturally, use the path to YOUR exu on your system /usr/local/euphoria/bin/exu $PATH_TRANSLATED # END of runexu.cgi
RESTART APACHE to get the Action directive to take effect.
3. Test setup You can use this Euphoria program to test whether this works. Create the file as test.exu in your cgi-bin directory:
Test
-- test program for euphoria cgi -- comment/uncomment the following to test the EUINC variable -- include misc.e -- or whatever sequence cmd -- if val is a string, return it, otherwise "Undefined" function test_val(object val) if atom(val) then return "Undefined" elsif object(val) then for i = 1 to length(val) do if not atom(val[i]) then return "Invalid string sequence" end if end for return val else return "Invalid type for string" end if return "foozle" -- never reached end function procedure env_dump(sequence val) printf(1, "%s: %s\n", {val, test_val(getenv(val))} ) end procedure puts(1, "Content-Type: text/plain\n\n") puts(1, "Hello!\n\n") puts(1, "COMMAND LINE\n============\n\n") cmd = command_line() for i = 1 to length(cmd) do printf(1, "%d: %s\n", {i, cmd[i]} ) end for puts(1, "\n\nREMOTE INFO\n===========\n") env_dump("REMOTE_IDENT") env_dump("REMOTE_USER") env_dump("REMOTE_HOST") env_dump("REMOTE_ADDR") puts(1, "\n\nSERVER INFO\n===========\n") env_dump("SERVER_SOFTWARE") env_dump("SERVER_NAME") env_dump("GATEWAY_INTERFACE") env_dump("SERVER_PROTOCOL") env_dump("SERVER_PORT") env_dump("REQUEST_METHOD") env_dump("PATH_INFO") env_dump("PATH_TRANSLATED") env_dump("SCRIPT_NAME") env_dump("QUERY_STRING") env_dump("AUTH_TYPE") env_dump("CONTENT_TYPE") env_dump("CONTENT_LENGTH") puts(1, "\n\nBROWSER INFO\n=============\n") env_dump("HTTP_ACCEPT") env_dump("HTTP_USER_AGENT")
Open the URL http://yourserver.com/cgi-bin/test.exu and you should get something like:
Hello! COMMAND LINE ============ 1: /usr/local/euphoria/bin/exu 2: /usr/lib/cgi-bin/test.exu REMOTE INFO =========== REMOTE_IDENT: Undefined REMOTE_USER: Undefined REMOTE_HOST: Undefined REMOTE_ADDR: XXX.XXX.XXX.XXX SERVER INFO =========== SERVER_SOFTWARE: Apache/2.0.47 (Debian GNU/Linux) mod_perl/1.99_13 Perl/v5.8.7 PHP/5.0.2 mod_ssl/2.0.47 OpenSSL/0.9.7b SERVER_NAME: yourserver.com GATEWAY_INTERFACE: CGI/1.1 SERVER_PROTOCOL: HTTP/1.1 SERVER_PORT: 80 REQUEST_METHOD: GET PATH_INFO: /cgi-bin/test.exu PATH_TRANSLATED: /usr/lib/cgi-bin/test.exu SCRIPT_NAME: /cgi-bin/runexu.cgi QUERY_STRING: test%20query%20string AUTH_TYPE: Undefined CONTENT_TYPE: Undefined CONTENT_LENGTH: Undefined BROWSER INFO ============= HTTP_ACCEPT: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/x-gsarcade-launch, application/vnd.ms-powerpoint, application/vnd.ms-excel, application/msword, */* HTTP_USER_AGENT: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.40607; .NET CLR 1.1.4322)
Caveats
Note that SCRIPT_NAME is the name of the wrapper not your script at all. You need to use PATH_TRANSLATED to get the name of your script.
runexu.cgi should be secure as it can't be supplied with a command line from the web browser, but you should look into this for yourself and never trust anyone else's opinion about security.
Hosted environment
Getting the interpreter to work on a hosted environment can be tricky. Presented below is a tested method on a server running Linux and Apache2 (a cpanel based system). This is only a guideline, as your hosted account may be behave differently or have different restrictions.
This method relies on a shebang line in your Euphoria code to help run the interpreter. Euphoria supports this method by ignoring the shebang line when it is irrelevant. The shebang line uses a Perl interpreter to run the Euphoria script.
Overview
The following outline may help you diagnose problems if following this method does not work.
- The Euphoria script is loaded by Apache, and being in the cgi-bin directory or associated with a cgi-script handler will look for the shebang line in the Euphoria script.
- It will then call this script with the standard Common Gateway Interface environment variables set, eg REMOTE_ADDR, SCRIPT_FILENAME, etc.
- The runexu script will use the SCRIPT_FILENAME variable to launch exu with the path to your script as an argument.
- The runexu script captures STDOUT (the output) of your script and passes this straight to the web browser.
Method
- Create a folder '''outside''' your html document root folder, eg called 'bin'.
- Upload the unix exectuables (I think only exu is needed). You probably need to use the uncompressed versions.
- Make sure the Euphoria executables are executable, use whatever method you have available (eg FTP, or cpanel filemanager) to chmod 755 the files.
- Make another folder somewhere '''outside''' your document root for the Euphoria include files you will be using, eg 'include'
- Upload the standard include files to that location. This is also a good place to keep other user contributed includes.
- Create the following perl script in the 'bin' directory:
#!/usr/bin/perl # ### Perl wrapper script for running the Euphoria interpreter www.rapidephoria.com ## use #!/path/to/runexu as the first line of your Euphoria script # use CGI::Carp qw(fatalsToBrowser); # optional # Tell this script where things are $exu_path = "/path/to/bin/exu"; $euinc_path = "/path/to/include"; # This relies on /bin/env being available (generally is) $cmdline = "/bin/env EUINC=$euinc_path $exu_path $ENV{'SCRIPT_FILENAME'}"; # Capture STDOUT from $cmdline $test = `$cmdline`; # Ouput raw STDOUT from Euphoria program print $test; ### Debug code. Use this to track down problems, eg SCRIPT_FILENAME etc ## Comment out the above two statements ($test=.. and print..) and uncomment the following. # #print "Content-Type: text/plain\n\n"; # #foreach $key (keys %ENV) { # print "$key: $ENV{$key}\n"; #}
- Make sure runexu is executable (you may have to make sure it is not executable by group or others as well)
- Use the above test program to test your setup, but you will have to add as the first line #!/path/to/runexu
Possible problems
- It is possible that /bin/env is not available. In that case modify $cmdline so that it just reads $exu_path $ENV{'SCRIPT_FILENAME'}. You won't be able to rely on shared include files and will have to put the include file in the same folder as your script (UNTESTED: should they be in the 'bin' folder?)
- You might not be able to upload executables to your host.
- I used cpanel to set a handler for .exu files as 'cgi-script'. If you are unable to do this then you might have to name your files .cgi. In general though, any file in a ScriptAlias directory can be run (eg in the cgi-bin directory).
Method comments
- If you are familiar with Perl you might be able to use exec instead of the backticks. This will replace the Perl interpreter with the Euphoria interpreter and should pass it things like the environment, STDOUT, STDERR etc. This means that the output won't be buffered by the perl script resulting in slightly snappier execution.
- It is unknown what will happen with arguments to the script. Anything after a ? should be in QUERY_STRING, but how POST data will work is unknown at this stage.
- history, backlinks
- Last modified Apr 19, 2016 by CraigWelch