Next I will share with you some notes on Perl + FastCGI for web development and learning. I hope to share some references with you.
Hello World
A simple hello world example:
The Code is as follows: |
Copy code |
#! /Usr/bin/env perl Use strict; Use warnings; Use CGI: Fast; While (my $ q = new CGI: Fast) { Print $ q-> header ("text/plain "); Print "Hello World "; } |
The difference with CGI is that there is only one loop to accept requests. The CGI: Fast object and CGI interface are the same, and the script can also be used as a CGI script.
Build nginx + FastCGI Environment
Perl uses the CGI: Fast package to provide the FastCGI service. This package provides two methods to start the FastCGI process. One is to directly use the service provided by this package to change the current process to the FastCGI process, the other is to use the third-party tool spawn-fcgi for startup.
Nginx configuration example:
The Code is as follows: |
Copy code |
Location /{ Fastcgi_pass 127.0.0.1: 8184; Fastcgi_param SCRIPT_FILENAME/scripts $ fastcgi_script_name; Include fastcgi_params; } |
After nginx is configured, use spawn-fcgi to start the preceding Hello World:
The Code is as follows: |
Copy code |
$ Spawn-fcgi-n-a 127.0.0.1-p 8184-f./main. pl |
Debugging support
In the preceding command line, the parameter-n is used to prevent spawn-fcgi from fork from producing multiple processes and blocking them. You can press Ctrl + C to close them, the product server can remove this parameter to make full use of the server's multi-core to provide a higher concurrency. I have previously written a bash script that allows you to restart the service when the file is changed to facilitate debugging of the perl program. The Code is as follows:
The Code is as follows: |
Copy code |
#! /Bin/bash # PID file and script to be started PID_FILE = service. pid MAIN = main. pl # Shut down the previously started Process Term (){ Test-e $ PID_FILE | return Pid = 'cat $ PID_FILE' Kill-s-0 $ pid | return Echo "Terminating $ MAIN $ pid" Rm-f $ PID_FILE Kill $ pid Wait $ pid } # The FastCGI process started when the current script exits Trap "term; exit" SIGINT SIGTERM While true Do # The previous process must be closed after the first startup or file change Term # Start script debugging in the no fork mode and write the PID to the file Spawn-fcgi-n-a 127.0.0.1-p 8184-f./$ MAIN & Pid = $! Echo $ pid> $ PID_FILE Echo "My Perl service started, pid = $ pid" # Monitoring file changes Files = 'Find.-name' *. pl '-o-name' *. M'-o-name '*. html'' Md5 = 'md5sum $ files | md5sum' # Wait for file change While [['md5sum $ files | md5sum' = "$ md5"] Do Sleep 1 Done Echo "File changes detected, restarting service" |
Done: the script has been tested in Mac OSX and Linux.
Routing System
Web development requires routing implementation to make specific responses to different requests.
The routing request depends on the HTTP Method and URI. Therefore, the routing request must be distributed.
In CGI, you can obtain the Request Method and URI through the Environment Variables REQUEST_METHOD and REQUEST_URI.
Therefore, a simple routing system can actually be broken down into a second-level map. Registering a route is actually putting the corresponding processing function of the rule into this map, the dispatch request is to obtain the corresponding processing function from the map according to the rule. A simple example is as follows:
The Code is as follows: |
Copy code |
My % routers = (); Sub not_found { Print "Status: 404n "; Print "Content-Type: text/htmlnn "; Print <EOF <Html> <Body> <H1> 404 Not found Cannot find $ ENV {REQUEST_PATH }. </Body> </Html> EOF } Sub add_rule { My ($ method, $ path, $ callback) = @_; My $ handlers = $ routers {$ method }; $ Handlers = $ routers {$ method }={} if not $ handlers; $ Handlers-> {$ path} = $ callback; }
Sub dispatch { My $ q = shift; My $ method = $ ENV {REQUEST_METHOD }; My $ uri = $ ENV {REQUEST_URI }; $ Uri = ~ S /?. * $ //; My $ handler = ($ routers {$ method} | |{})-> {$ uri} | not_found; Eval { & $ Handler ($ q ); }; Print STDERR "Failed to handle $ method $ uri: $ @ n" if $ @; } |
Example of using this routing system:
The Code is as follows: |
Copy code |
Sub index { My ($ q) = @_; Print $ q-> header ('text/plain '); Print "Hello World! "; } Router: add_rule ('get', '/', & index ); |
Template System
Perl provides a lot of Template system implementation, my personal favorite is Template Toolkit, documentation is also very rich, the website is http://www.template-toolkit.org /.
Example of modifying the previous index to a template:
The Code is as follows: |
Copy code |
Use Template; My $ tt = new Template ({INCLUDE_PATH => 'templates', INTERPOLATE => 1 }); Sub index { My ($ q) = @_; My $ output = ''; Print $ q-> header ('text/html ');
$ Tt-> process('index.html ', {world => 'World'}, $ output) | die $ tt-> error (); Print $ output; } |
The content of the templates/index.html file is as follows:
The Code is as follows: |
Copy code |
<Html> <Head> <title> Demo </title> <Body> Hello $ {world} </Body> </Html> |