Perl Development Manual

Contents:

  1. Introduction
    1. Helper
    2. Accessor
    3. CGI Script
    4. Database Methods
  2. Model
    1. Genelet::Model
    2. Add Class Method
    3. Project
    4. Component
    5. Pagination
    6. JOIN Tables
    7. Triggers
  3. Filter
    1. Accessors and ACL
    2. File Uploading
    3. RLS
    4. Get Action
    5. Preset
    6. Before
    7. After
    8. Sending Email

 

Download

The Perl Framework can be downloaded from GitHub:
git clone git@github.com:genelet/perl.git YOUR_DIRECTORY

 

Best Practice

Here is the list of few guidelines you should follow in design of classes.

  • Class attributes are always expressed in upper-cases.
  • In class methods, always return nothing from a successful run, otherwise, return an error code or error string.
  • Use setup_accessors to build Getter, Setter for attributes and to initialize them.

 

For Experienced Developers

The Perl version of Genelet is nothing more than a collection of well-thought CGI/FCGI packages to develop large-scale web project in a convenience, fast and organized way. While you are still be able to do everything in your own style, the packages are aimed nevertheless to be the most efficient and elegant solutions.

Genelet will force you, and guarantee you, to have a clean set-up and development foundation that would grow linearly, not exponentially with the size of project. Instead of digging into legacy code and debugging, you could gain more time in designing business logic, data model, or planning future growth.

Genelet has little dependence on 3rd party packages. The list is very short. They are: JSON (for JSON), XML::LibXML (for XML), DBI (for database), LWP::UserAgent (for OAuth etc.), URI and URI::Escape (for URL manipulation), Digest::HMAC_SHA1 and MIME::Base64 (for security), Net::SMTP (for email), Template (for HTML5 templates), and Test::More (for unit testing). The minimal Perl version it works with is 8.10.

Future more, Genelet is a protocol. You can easily switch from Perl to GO or Java, or vice versa, with only a minimal effort. In particular, your database and public APIs will be kept the same.

 

For Novice Users

Genelet is in Object-Oriented Perl. It follows strict MVC pattern and provides full RESTful API access. Popular services like OAuth login, SMS and mobile push notifications etc. are built-in and ready to use. It has also a debugging tool to find problems. As an add-on, there is a bridge Javascript file for you to develop one-page website using Angular 1.3 web framework.

While Genelet is as powerful as, if not more powerful than, other frameworks, it is definitely a lot easier to learn and takes much shorter development circle to finish web project.

The only major idea that has not been incorporated into Genelet is ORM, Objected Relational Mapping. Alternatively, Genelet has its own packages to operate on database, include a complete set of CRUD/REST subroutines to run raw SQLs and stored procedures. However, you can always bring in your favored ORM. Genelet works with every CPAN module in the same way as a normal Perl program.

 

Virtual Hosting

For those working under a virtual hosting environment, Genelet is always able to run in the CGI mode. It would be very likely to run in the Fast CGI mode too, as far as the virtual hosting provider runs PHP under Apache’s mod_fcgid.  You can develop in CGI, and switch to Fast CGI anytime to gain the PHP speed.

 

Config 5.5: Google Push Notification

To send Google Cloud Message, define the service in Blk:

"Google" : {
  "Api_key": string,
  "Collapse_key": string,
  "Delay_while_idle": string,
  "Time_to_live": int
}

where the parameters are described here. Then in the request where you want to send APNS, define key _gapple in the output data structure other:

"_ggoogle": {
  "To": string,
  "Title": string,
  "Content": string,
  "File": string,
  "Extra": {key: value, key: value, ...},
  key, value,
  key, value
}

Again, Content is the notification body which can be constructed from File and Extra too.

Config 5.4: Apple Push Notification

To send APNS, define the service in Blk:

"Apple" : {
  "Cert": string
  "Key": string
  "Passphrase": string
}

where the parameters are described here. Then in the request where you want to send APNS, define key _gapple in the output data structure other:

"_gapple": {
  "Device_token": string,
  "Badge": int,
  "Sound": string,
  "Content": string,
  "File": string,
  "Extra": {key: value, key: value, ...},
  key, value,
  key, value
}

Again, Content is the alert body which can constructed from File and Extra too.

Config 5.3: Sending Emails

The Blk Block

Genelet has built-in services to send email, push notification and SMS. To use them, define the following keys in Blk, with values for system and connection parameters.

  • Mail: sending emails using SMTP.
  • Apple: sending APNS.
  • Google: sending GCM.
  • Sms: sending SMS text messages.

It is important to note that the services, if enabled, run in a sequence at the end of request. It blocks each other, as well as the original web request. If your web server has a slow or unreliable connection to the service providers, you should look for non-blocking solutions such as message queue service.

Email Service

The Mail configuration is:

"Mail": {
  "Username": string (optional),
  "Password": string (optional),
  "SSL": bool (optional),
  "Address": string,
  "From": string,
  "Headers": {key:value, key:value}
}

where Address is the internet address of the SMTP host; Username and Password are the SMTP user account; and From is the generic email address of the sender belonging to this project. All the other system and connection parameters are put in Headers as key-value pairs.

Sending Email

You should send email at the end of a request, e.g. after a successful member signup. Just to add key _gmail to the output data structure other (see Developer Manual in each language):

"_gmail": {
  "To"     : string,
  "Subject": string,
  "Content": string,
  "File"   : string,
  "Extra"  : {key: value, key: value, ...},
  key, value,
  key, value
}

where To is the recipient email address, Subject the subject and Content the body. If Content is not given, Genelet will use the value of File, the template located under the same directory as HTML templates, and optionally, extra key-values Extra, to construct the message body. For any other possible extra key-value pairs required by the SMTP service, put them directly into _gmail.

Config 5.2: File Uploading

The steps to implement file uploading are

  • Define a proper directory called Uploaddir in config.json that is readable and writable by the server.
    "Uploaddir"       default: "/tmp"
  • In your web uploading form, define a uploading input field with type=file and name=xxx.
  • Receive the information of uploaded files in Controller.

You may upload multiple files at once, just to make sure they are assigned different names. For security reason, Uploaddir should not be open to online. After the upload, you can manually move the uploaded file to wherever you’d like.

 

Config 5.1: CORS

Genelet supports a weak CORS policy, that every browser with a proper Origin request header is allowed to retrieve API data even it is cross domain. We may modify it or allow you to customize the policy in future releases.

Another way to make cross domain API access is to use JSONP, see Section 2.3.

Config 4.3: Caching

The Cache case lies between Static and Reroute,

  • It will look at the static file pointed by the URL. If it exists and is validate, serve it (including a proper authentication).
  • If it is expired as indicated by the Expire parameter, the stale cache will be deleted.
  • If it is deleted, or not existing, an internal URL will be rewritten in the same way as Case=Reroute.
  • At the end of standard serving, a new cache will be written onto disk.

Because the cached page is unknown beforehand, and its status is only setup at the time of hit, we call it Schrodinger Cache, matching to the famous Schrodinger Cat experience in quantum theory.

Config 4.2: Rerouting

If Case is Reroute, Genelet will internally re-write the URL into a new URL in the standard format:

http://WEBSITE/HANDLER/role/tag/component?action=string&query…

So you need to at least map out, or by assignment, the triplet {role, tag, component} in order to rewrite meaningfully. If role is a login role, a proper authentication is automatically enforced.

Here is an example of pattern:

{
"Reg": "^\/(\w+)/(\d+)-([\w\_]+)\.(\w+)\/$"
"Mats": ["role", "book_id", "subject", "tag"]
"Case": "Reroute"
"Que": "component=book&action=edit"
}

So a GET request to

http://WEBSITE/admin/1234-New_York_Weather.html

will be re-written internally to

http://WEBSITE/HANDLER/admin/html/book?action=edit&book_id=1234&subject=New_York_Weather