1. Trang chủ
  2. » Công Nghệ Thông Tin

Tài liệu Embedding Perl in HTML with Mason Chapter 3: Special Components: Dhandlers and Autohandlers pdf

19 399 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Special components: Dhandlers and Autohandlers
Thể loại Chapter
Định dạng
Số trang 19
Dung lượng 59,18 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Dhandlers The term " dhandler" stands for "default handler." The concept is simple: if Mason is asked to process a certain component but that component does not exist in the component t

Trang 1

Chapter 3: Special Components: Dhandlers and Autohandlers

In previous chapters you've seen an overview of the basic structure and syntax of Mason components, and you've seen how components can

cooperate by invoking one another and passing arguments

In this chapter you'll learn about dhandlers and autohandlers, two powerful

mechanisms that help lend reusable structure to your site and help you

design creative solutions to unique problems Mason's dhandlers provide a flexible way to create "virtual" URLs that don't correspond directly to

components on disk, and autohandlers let you easily control many structural aspects of your site with a powerful object-oriented metaphor

Dhandlers

The term " dhandler" stands for "default handler." The concept is simple: if Mason is asked to process a certain component but that component does not exist in the component tree, Mason will look for a component called

dhandler and serve that instead of the requested component Mason looks for dhandlers in the apparent requested directory and all parent directories For instance, if your web server receives a request for

/archives/2001/March/21 and passes that request to Mason, but no such Mason component exists, Mason will sequentially look for

/archives/2001/March/dhandler, /archives/2001/dhandler, /archives/dhandler, and /dhandler If any of these components exist, the search will terminate and Mason will serve the first dhandler it finds, making the remainder of the requested component path available to the dhandler via

$m->dhandler_arg For instance, if the first dhandler found is

/archives/dhandler, then inside this component (and any components it

Trang 2

calls), $m->dhandler_arg will return 2001/March/21 The dhandler can use this information to decide how to process the request

Dhandlers can be useful in many situations Suppose you have a large

number of documents that you want to serve to your users through your web site These documents might be PDF files stored on a central document

server, JPEG files stored in a database, text messages from an electronic mailing list archive (as in the example from the previous paragraph), or even PNG files that you create dynamically in response to user input You may want to use Mason's features to create or process these documents, but it wouldn't be feasible to create a separate Mason component for each

document on your server

In many situations, the dhandler feature is simply a way to make URLs more attractive to the end user of the site Most people probably prefer URLs like

http://www.yoursite.com/docs/corporate/decisions.pdf over URLs like

http://www.yoursite.com/doc.cgi?domain=corporate&format=pdf&content

=dec isions It also lets you design an intuitive browsing interface, so that

people who chop off the tail end of the URL and request

http://www.yoursite.com/docs/corporate/ can see a listing of available

corporate documents if your dhandler chooses to show one

The alert reader may have noticed that using dhandlers is remarkably similar

to capturing the PATH_INFO environment variable in a CGI application In fact, this is not exactly true: Apache's PATH_INFO mechanism is actually available to you if you're running Mason under mod_perl, but it gets

triggered under different conditions than does Mason's dhandler mechanism

Trang 3

If Apache receives a request with a certain path, say,

/path/to/missing/component, then its actions depend on what the final

existing part of that path is If the /path/to/missing/ directory exists but

doesn't contain a component file, then Mason will be invoked, a dhandler will be searched for, and the remainder of the URL will be placed in

$m->dhandler_arg On the other hand, if /path/to/missing exists as a regular Mason component instead of as a directory, this component will be invoked

by Mason and the remainder of the path will be placed (by Apache) into

$r->path_info Note that the majority of this handling is done by

Apache; Mason steps into the picture after Apache has already decided whether the given URL points to a file, what that file is, and what the

leftover bits are

What are the implications of this? The behavioral differences previously described may help you determine what strategy to use in different

situations For example, if you've got a bunch of content sitting in a database but you want to route requests through a single Mason component, you may want to construct "file-terminating" URLs and use $r->path_info to get

at the remaining bits However, if you've got a directory tree under Mason's control and you want to provide intelligent behavior for requests that don't exist (perhaps involving customized 404 document generation, massaging of content output, and so on) you may want to construct

"directory-terminating" URLs and use $m->dhandler_arg to get at the rest

Finer Control over Dhandlers

Occasionally you will want more control over how Mason delegates

execution to dhandlers Several customization mechanisms are available

Trang 4

First, any component (including a dhandler) may decline to handle a request,

so that Mason continues its search for dhandlers up the component tree For instance, given components located at /docs/component.mas, /docs/dhandler, and /dhandler, /docs/component.mas may decline the request by calling

$m->decline, which passes control to /docs/dhandler If /docs/dhandler calls

$m->decline, it will pass control to /dhandler Each component may do some processing before declining, so that it may base its decision to decline

on specific user input, the state of the database, or the phase of the moon If any output has been generated, $m->decline will clear the output buffer before starting to process the next component

Second, you may change the filename used for dhandlers, so that instead of

searching for files called dhandler, Mason will search for files called

default.mas or any other name you might wish To do this, set the

dhandler_name Interpreter parameter (see Chapter 6 for details on

setting parameters) This may be useful if you use a text editor that

recognizes Mason component syntax (we mention some such editors in

Appendix C) by file extension, if you want to configure your web server to handle (or deny) requests based on file extension, or if you simply don't like

the name dhandler

Dhandlers and Apache Configuration

You may very well have something in your Apache configuration file that looks something like this:

DocumentRoot /home/httpd/html

<LocationMatch "\.html$">

Trang 5

SetHandler perl-script

PerlHandler HTML::Mason::ApacheHandler

</LocationMatch>

This directive has a rather strange interaction with Mason's dhandler

mechanism If you have a dhandler at /home/httpd/html/dhandler on the filesystem, which corresponds to the URL /dhandler and a request arrives for the URL /nonexistent.html, Mason will be asked to handle the request Since the file doesn't exist, Mason will call your dhandler, just as you would

expect

However, if you request the URL /subdir/nonexistent.html, Apache will never call Mason at all and will instead simply return a NOT FOUND (404) error Why, you ask? A good question indeed It turns out that in the process

of answering the request, Apache notices that there is no

/home/httpd/html/subdir directory on the filesystem before it even gets to the content generation phase, therefore it doesn't invoke Mason In fact, if you

were to create an empty /home/httpd/html/subdir directory, Mason would be

called

One possible solution is simply to create empty directories for each path you would like to be handled by a dhandler, but this is not a very practical

solution in most cases Fortunately, you can add another configuration

directive like this:

<Location /subdir>

SetHandler perl-script

PerlHandler HTML::Mason::ApacheHandler

</Location>

Trang 6

This tells Apache that it should pass control to Mason for all URL paths

beginning with /subdir, regardless of what directories exist on disk Of

course, using this Location directive means that all URLs under this

location, including images, will be served by Mason, so use it with care

Autohandlers

Mason's autohandler feature is one of its most powerful tools for managing complex web sites

Managing duplication is a problem in any application, and web applications are no exception For instance, if all pages on a given site should use the same (or similar) header and footer content, you immediately face a choice: should you simply duplicate all the common content in each individual page,

or should you abstract it out into a central location that each page can

reference? Anyone who's worked on web sites knows that the first approach

is foolhardy: as soon as you need to make even a minor change to the

common content, you have to do some kind of find-and-replace across your entire site, a tedious and error-prone process

For this reason, all decent web serving environments provide a way to

include external chunks of data into the web pages they serve A simple example of this is the Server Side Include mechanism in Apache and other web servers A more sophisticated example is Mason's own ability to call one component from inside another

Although an include mechanism like this is absolutely necessary for a

manageable web site, it doesn't solve all the duplication problems you might encounter

Trang 7

First, the onus of calling the correct shared elements still rests within each individual page There is no simple way for a site manager to wave a wand over her web site and say, "Take all the pages in this directory and apply this header and this footer." Instead, she must edit each individual page to add a reference to the proper header and footer, which sounds remarkably like the hassle we were trying to avoid in the first place Anyone who has had to change the header and footer for one portion of a site without changing other portions of the site knows that include mechanisms aren't the cat pajamas they're cracked up to be

Second, include mechanisms address only content duplication, not any other

kind of shared functionality They don't let you share access control, content filtering, page initialization, or session management, to name just a few mechanisms that are typically shared across a site or a portion of a site

To address these problems, Mason borrows a page from object-oriented programming One of the central goals of object-oriented programming is to allow efficient and flexible sharing of functionality, so that a

Rhododendron object can inherit from a Plant object, avoiding the need

to reimplement the photosynthesize() method Similarly, each

component in Mason may have a

parent component, so that several components may have the same parent, thereby sharing their common functionality

To specify a component's parent, use the inherit flag:

<%flags>

inherit => 'mommy.mas'

</%flags>

Trang 8

If a component doesn't specify a parent explicitly, Mason may assign a

default parent This is (finally) how autohandlers come into the picture:

• The default parent for any "regular" component (one that isn't an autohandler but might be a dhandler) is a component named

"autohandler" in the same directory If no autohandler exists in the same directory, Mason will look for an autohandler one directory up, then one more directory up, and so on, until reaching the top of the component root If this search doesn't find an autohandler, then no parent is assigned at all

• The default parent for an autohandler is an autohandler in a higher directory In other words, an autohandler inherits just like any other component, except that it won't inherit from itself

Note that these are only the defaults; any component, including an

autohandler, may explicitly specify a parent by setting the inherit flag

Be careful when assigning a parent to an autohandler, though: you may end

up with a circular inheritance chain if the autohandler's parent inherits

(perhaps by default) from the autohandler

Just like dhandlers, you can change the component name used for the

autohandler mechanism from autohandler to something else, by setting the

Mason interpreter's autohandler_name parameter

We'll use the standard object-oriented terminology when talking about the inheritance hierarchy: a component that has a parent is said to be a "child" that "inherits from" its parent (and its parent's parent, and so on) At runtime, the hierarchy of parent and child components is often referred to in Mason as the "wrapping chain," for reasons you are about to witness

Trang 9

Example 3-1 and Example 3-2 show how to use autohandlers for our simple content-sharing scheme, adding common headers and footers to all the pages

in a directory

Example 3-1 /autohandler

<html>

<head><title>Example.com</title></head>

<body>

% $m->call_next;

<br><a href="/">Home</a>

</body>

</html>

Example 3-2 /welcome.html

<p>Welcome to a very wonderful site We hope you enjoy your stay.</p>

This demonstrates the first property of inheritance, which we call " content wrapping" any component that inherits from the autohandler in Example 3-1, like /welcome.html in Example 3-2, will automatically be wrapped in the simple header and footer shown Note that /welcome.html doesn't need

to explicitly insert a header and footer; that happens automatically via the autohandler mechanism

Let's trace through the details of the component processing A request comes

to the web server for http://example.com/welcome.html, which Mason

translates into a request for the /welcome.html component The component

is found in the component path, so the dhandler mechanism is not invoked

Trang 10

/welcome.html doesn't explicitly specify a parent, so Mason looks for a component named /autohandler, and it finds one It then tries to determine a parent for /autohandler because there are no directories above /autohandler and /autohandler doesn't explicitly specify a parent, /autohandler remains parentless, and the construction of the inheritance hierarchy is complete

Mason then begins processing /autohandler,the top component in the parent hierarchy The first part of the component doesn't contain any special Mason sections, so it simply gets output as text Mason then sees the call to

$m->call_next, which means that it should go one step down the inheritance hierarchy and start processing its child component, in this case

/welcome.html The /welcome.html component generates some output,

which gets inserted into the middle of /autohandler and then finishes

Control passes back to /autohandler, which generates a little more output and then finishes, ending the server response

Using Autohandlers for Initialization

As we mentioned earlier, the autohandler mechanism can be applied to more than just header and footer generation For the sake of dividing this material into reasonably sized chunks for learning, we're leaving the more advanced object-oriented stuff like methods and attributes for Chapter 5 However, several extremely common autohandler techniques are presented here

First, most interesting sites are going to interact with a database Generally you'll want to open the database connection at the beginning of the response and simply make the database handle available globally for the life of the request.1 The autohandler provides a convenient way to do this (see Example 3-3 and Example 3-4)

Ngày đăng: 14/12/2013, 12:15

TỪ KHÓA LIÊN QUAN

🧩 Sản phẩm bạn có thể quan tâm