1Perlbal::Manual::PluginUss(e3r)Contributed Perl DocumentPaetrilobnal::Manual::Plugins(3)
2
3
4
6 Perlbal::Manual::Plugins - Creating and using plugins
7
8 VERSION
9 Perlbal 1.78.
10
11 DESCRIPTION
12 How to create and use Perlbal plugins.
13
14 How to use a plugin
15 Perlbal supports plugins through modules under "Perlbal::Plugin::*"
16 that implement a set of functions described further down this document.
17
18 Some of these plugins are shipped with Perlbal itself, while others can
19 be found on CPAN (you can also create your own plugin and have it
20 available only locally).
21
22 In order to use a plugin you first have to load it; on your Perlbal's
23 configuration file add something like:
24
25 Load MyPlugin
26
27 This loads plugin "Perlbal::Plugin::MyPlugin".
28
29 Each plugin will have its own way of being configured (some don't
30 require any configuration at all), so you'll have to refer to their
31 documentation (or code).
32
33 Typically (but not always), a plugin will allow you to set additional
34 parameters to a service; for instance:
35
36 LOAD MaxContentLength
37 CREATE SERVICE example
38 SET max_content_length = 100000
39 SET plugins = MaxContentLength
40
41 "max_content_length" is a parameter of
42 Perlbal::Plugin::MaxContentLength.
43
44 If you're worried that two plugins may have the same parameter, of if
45 you simply want to define those variables all in the same spot and thus
46 will be doing it outside of the plugin's context, you can use the more
47 verbose syntax:
48
49 SET my_service.my_plugin.my_variable = my_value
50
51 Notice that some plugins need to be stated service by service; hence,
52 this line:
53
54 SET plugins = MaxContentLength
55
56 The "plugins" parameter (a list of strings separated by commas or
57 spaces) defines which plugins are acceptable for a service.
58
59 Troubleshooting
60
61 If you try to load a plugin and receive the following error message:
62
63 ERROR: Can't locate Perlbal/Plugin/MyPlugin.pm in @INC
64
65 That means that either the plugin isn't installed or perlbal couldn't
66 find it. (perhaps it is installed in a different version of perl other
67 than the one used to run perlbal?)
68
69 How to create a plugin
70 A Perlbal plugin consists in a package under the "Perlbal::Plugin"
71 namespace that implements a number of functions: "register",
72 "unregister", "load" and "unload".
73
74 These steps and functions (plus some helper functions you can define or
75 use) are described below.
76
77 PLEASE KEEP IN MIND: Perlbal is a single-process, asynchronous web
78 server. You must not do things in plugins which will cause it to block,
79 or no other requests can be served at the same time.
80
81 Creating a package
82
83 While there are many ways of creating a package, we'd recommend that
84 you use something to do it for you. A good option is Module::Starter.
85
86 (note: if you really want to, you can just create a file with your
87 package and use it; by using something like Module::Starter you're
88 making sure that several pitfalls are avoided, lots of basic rules are
89 followed and that your package can easily be made available as a
90 distribution that you can deploy on any machine - or, if you feel so
91 inclined, upload to CPAN - in a simple way)
92
93 Let's assume you want to create a plugin that checks requests for a
94 "X-Magic" header and, if present, add an header "X-Color" to the
95 response when serving a file. Let's assume your plugin will be called
96 "Perlbal::Plugin::ColorOfMagic".
97
98 Having installed Module::Starter, here's a command you can run that
99 will create your package for you:
100
101 $ module-starter --module=Perlbal::Plugin::ColorOfMagic --author="My name" --email=my@email.address
102
103 That should create a file tree that you can get better acquainted with
104 by reading Module::Starter's fine documentation. For this example, the
105 file you really need should now reside in
106 "lib/Perlbal/Plugin/ColorOfMagic.pm".
107
108 This file probably starts with something like the following:
109
110 package Perlbal::Plugin::ColorOfMagic;
111
112 use warnings;
113 use strict;
114
115 You'll have to add a few functions to this file. These are described
116 below.
117
118 (note: upon creating this package, some boilerplate documentation will
119 also be present on the file; you should revise it and even remove bits
120 that don't feel right for your plugin)
121
122 register
123
124 "register" is called when the plugin is being added to a service. This
125 is where you register your plugin's hooks, if required (see
126 Perlbal::Manual::Hooks for the list of existing hooks and further
127 documentation on how they work).
128
129 For the sake of our example ("Perlbal::Plugin::ColorOfMagic", see
130 above), what we want to do is register a hook that modifies the
131 response headers; that means we want a "modify_response_headers" hook.
132
133 Here's what you'd do:
134
135 sub register {
136 my ($class, $service) = @_;
137
138 my $my_hook_code = sub {
139
140 my Perlbal::ClientHTTPBase $cp = shift;
141
142 if ( $cp->{req_headers}->header('X-Magic') ) {
143 $cp->{res_headers}->header( 'X-Color', 'Octarine' );
144 }
145
146 return 0;
147 };
148
149 $service->register_hook('ColorOfMagic','modify_response_headers', $my_hook_code);
150 }
151
152 Inside "register", we're calling "register_hook" to register our
153 "ColorOfMagic" "modify_response_headers" hook. Its code, that will run
154 "when we've set all the headers, and are about to serve a file" (see
155 Perlbal::Manual::Hooks), receives a Perlbal::ClientHTTPBase object (you
156 can see what kind of object your hook will receive on
157 Perlbal::Manual::Hooks). We're checking to see if "X-Magic" is defined
158 on the request and, if so, we're setting header "X-Color" on the
159 response to "Octarine".
160
161 Notice that the hook ends with "return 0". This is because returning a
162 true value means that you want to cancel the connection to the backend
163 and send the response to the client yourself.
164
165 unregister
166
167 "unregister" is called when the plugin is removed from a service. It's
168 a standard good practice to unregister your plugin's hooks here, like
169 so:
170
171 sub unregister {
172 my ($class, $service) = @_;
173 $service->unregister_hooks('ColorOfMagic');
174 return 1;
175 }
176
177 You can also use "unregister_hook" to unregister one single hook:
178
179 $service->unregister_hook('ColorOfMagic', 'modify_response_headers');
180
181 load
182
183 "load" is called when your plugin is loaded (or reloaded).
184
185 This is where you should perform your plugin's initialization, which
186 can go from setting up some variables to registering a management
187 command (to register commands see the documentation for
188 "manage_command" further down this document).
189
190 my $color;
191
192 sub load {
193 my $class = shift;
194
195 $color = 'Octarine';
196
197 return 1;
198 }
199
200 "load" must always be defined, but if you really don't need it you can
201 have it simply returning a true value:
202
203 sub load { return 1; }
204
205 unload
206
207 "unload" is called when your plugin is unloaded. This is where you
208 should perform any clean up tasks.
209
210 "unload" must always be defined, but if you really don't need it you
211 can have it simply returning a true value:
212
213 sub unload { return 1; }
214
215 Don't forget to call "unregister_global_hook" if you have registered
216 any (see the documentation for "manage_command" further down this
217 document and you'll see what we're talking about).
218
219 register vs. load
220
221 "load" is called when the plugin is loaded, while "register" is called
222 whenever the plugin is set for a service.
223
224 This means that you should use "load" for anything that is global, such
225 as registering a global hook, and you should use "register" for things
226 that are specific to a service, such as registering service hooks.
227
228 dumpconfig
229
230 "dumpconfig" is not required.
231
232 When managing Perlbal (see Perlbal::Manual::Management) you can send a
233 "dumpconfig" command that will result in a configuration dump.
234
235 Apart from the global configuration, each plugin that implements a
236 "dumpconfig" function will also have that function called.
237
238 "dumpconfig" should return an array of messages to be displayed.
239
240 sub dumpconfig {
241 my ($class, $service) = @_;
242
243 my @messages;
244
245 push @messages, "COLOROFMAGIC is $color";
246
247 return @messages;
248 }
249
250 Again, "dumpconfig" is not required, so implement it only if it makes
251 sense for your plugin.
252
253 Helper functions
254
255 add_tunable
256
257 Adding a tunable will allow you to set its value within each plugin:
258
259 LOAD MyPlugin
260 CREATE SERVICE my_service
261 SET my_new_parameter = 42
262 SET plugins = MyPlugin
263 ENABLE my_service
264
265 "add_tunable" can be used by plugins that want to add tunables so that
266 the config file can have more options for service settings.
267
268 sub load {
269
270 Perlbal::Service::add_tunable(
271 my_new_parameter => {
272 check_role => '*',
273 check_type => 'int',
274 des => "description of my new parameter",
275 default => 0,
276 },
277 );
278 return 1;
279
280 }
281
282 "check_role" defines for which roles the value can be set
283 ("reverse_proxy", "web_server", etc). A value of "*" mean that the
284 value can be set for any role.
285
286 The acceptable values for "check_type" are "enum", "regexp", "bool",
287 "int", "size", "file", "file_or_none" and "directory_or_none". An
288 Unknown check_type error message will be displayed whenever you try to
289 set a value that has an unknown "check_type".
290
291 "check_type" can also contain a code reference that will be used to
292 validate the type.
293
294 check_type => sub {
295 my $self = shift;
296 my $val = shift;
297 my $emesg = shift;
298
299 ...
300 },
301
302 This code reference should return a true or false value. If returning
303 false, the contents of $emesg (which is passed as a reference to the
304 function) will be used as the error message.
305
306 Here's a better explanation of the acceptable values for "check_type":
307
308 bool
309 Boolean value. Must be defined and will be checked as a Perl value.
310
311 directory_or_none
312 The value needs to be defined and the content must be an existing
313 directory (validated against perl's -d switch).
314
315 enum
316 An array reference containing the acceptable values:
317
318 check_type => [enum => ["yellow", "blue", "green"]],
319
320 file
321 A filename, validated against perl's -f switch.
322
323 file_or_none
324 A filename, validated against perl's -f switch, or the default
325 value.
326
327 int An integer value, validated against "/^\d+$/".
328
329 regexp
330 Regular expression.
331
332 The correct form of setting a regexp tunable is by setting it as an
333 array reference containing the type ("regexp"), the regular
334 expression and a message that can explain it:
335
336 check_type => ["regexp", qr/^\d+\.\d+\.\d+\.\d+:\d+$/, "Expecting IP:port of form a.b.c.d:port."],
337
338 size
339 A size, validated against "/^(\d+)[bkm]$/".
340
341 manage_command
342
343 Perlbal catches unknown configuration commands and tries to match them
344 against hooks in the form of "manage_command.*".
345
346 Let's say that you want to set a management command "time" that will
347 allow you to see what time it is on the server.
348
349 sub load {
350
351 Perlbal::register_global_hook('manage_command.time', sub {
352 my $time = localtime time;
353
354 return [ "It is now:", $time ];
355 });
356
357 return 1;
358
359 }
360
361 If you want to display a text message you should return an array
362 reference; each of the values will be printed with a trailing newline
363 character:
364
365 time
366 It is now:
367 Wed Dec 1 19:08:58 2010
368
369 If you need to parse additional parameters on your hook, you can use
370 "parse" and "args" on the Perlbal::ManageCommand object that your
371 function will receive:
372
373 my $mc = shift;
374
375 $mc->parse(qr/^time\s+(today|tomorrow)$/, "usage: TIME [today|tomorrow]");
376
377 my ($cmd, $choice) = $mc->args;
378
379 This would allow you to call your command with an argument that would
380 have to be one of "today" or "tomorrow".
381
382 register_setter
383
384 "register_setter" allows you to define parameters that can be set for
385 your plugin, using a syntax such as:
386
387 SET my_service.my_plugin.my_variable = my_value
388
389 For instance:
390
391 SET discworld.colorofmagic.color = 'Orange'
392
393 Here's how you'd configure a new setter, by using "register_setter"
394 inside "load":
395
396 my $color;
397
398 sub load {
399 $color = 'Octarine';
400
401 $svc->register_setter('ColorOfMagic', 'color', sub {
402 my ($out, $what, $val) = @_;
403 return 0 unless $what && $val;
404
405 $color = $val;
406
407 $out->("OK") if $out;
408
409 return 1;
410 });
411
412 return 1;
413 }
414
415 selector
416
417 For plugins that will work with a "selector" service, sometimes you'll
418 want to override the "selector" itself.
419
420 You can do this in "register":
421
422 sub register {
423 my ($class, $svc) = @_;
424
425 $svc->selector(\&my_selector_function);
426
427 Don't forget to unregister your function on the way out:
428
429 sub unregister {
430 my ($class, $svc) = @_;
431 $svc->selector(undef);
432 return 1;
433 }
434
435 Your "selector" function receives a Perlbal::ClientHTTPBase object.
436
437 my Perlbal::ClientHTTPBase $cb = shift;
438
439 Inside your "selector" function you can set which service to forward
440 the request to like this:
441
442 my $service = Perlbal->service($service_name);
443 $service->adopt_base_client($cb);
444 return 1;
445
446 See Perlbal::Plugin::Vhosts or Perlbal::Plugin::Vpaths for examples on
447 how to do this.
448
449 Known plugins
450 The following is a list of known plugins:
451
452 • Perlbal::Plugin::AccessControl (Perlbal core)
453
454 Basic access control based on IPs and Netmasks.
455
456 • Perlbal::Plugin::Addheader
457
458 Add Headers to Perlbal webserver responses.
459
460 • Perlbal::Plugin::AutoRemoveLeadingDir (Perlbal core)
461
462 Auto-removal of leading directory path components in the URL.
463
464 • Perlbal::Plugin::BackendHeaders
465
466 See which backend served the request.
467
468 • Perlbal::Plugin::Cgilike (Perlbal core)
469
470 Handle Perlbal requests with a Perl subroutine.
471
472 • Perlbal::Plugin::EchoService (Perlbal core)
473
474 Simple plugin demonstrating how to create an add-on service for
475 Perlbal using the plugin infrastructure.
476
477 • Perlbal::Plugin::ExpandSSL
478
479 Add a custom header according to the SSL of a service.
480
481 • Perlbal::Plugin::FlvStreaming (Perlbal core)
482
483 Enable FLV streaming with reverse proxy.
484
485 • Perlbal::Plugin::ForwardedFor
486
487 Rename the X-Forwarded-For header in Perlbal.
488
489 • Perlbal::Plugin::Highpri (Perlbal core)
490
491 Makes some requests high priority.
492
493 • Perlbal::Plugin::Include (Perlbal core)
494
495 Allows multiple, nesting configuration files.
496
497 • Perlbal::Plugin::LazyCDN (Perlbal core)
498
499 Support for Content Delivery Networks.
500
501 • Perlbal::Plugin::MaxContentLength (Perlbal core)
502
503 Reject large requests.
504
505 • Perlbal::Plugin::NotModified (Perlbal core)
506
507 Automatic 304 Not Modified responses when clients send a
508 "If-Modified-Since" header.
509
510 • Perlbal::Plugin::PSGI
511
512 PSGI web server on Perlbal.
513
514 • Perlbal::Plugin::Palimg (Perlbal core)
515
516 Plugin that allows Perlbal to serve palette altered images.
517
518 • Perlbal::Plugin::Queues (Perlbal core)
519
520 Simple queue length header inclusion plugin.
521
522 • Perlbal::Plugin::Redirect (Perlbal core)
523
524 Plugin to do redirecting in Perlbal land.
525
526 • Perlbal::Plugin::Stats (Perlbal core)
527
528 Basic Perlbal statistics gatherer.
529
530 • Perlbal::Plugin::StickySessions
531
532 Session affinity for Perlbal.
533
534 • Perlbal::Plugin::Throttle (Perlbal core)
535
536 Throttle connections from hosts that connect too frequently.
537
538 • Perlbal::Plugin::TrustHeader
539
540 Remove untrusted headers.
541
542 • Perlbal::Plugin::UrlGroup
543
544 Let URL match it in regular expression.
545
546 • Perlbal::Plugin::Vhosts (Perlbal core)
547
548 Name-based virtual hosts.
549
550 • Perlbal::Plugin::Vpaths (Perlbal core)
551
552 Select by path (selector role only).
553
554 • Perlbal::Plugin::XFFExtras (Perlbal core)
555
556 Perlbal plugin that can optionally add an X-Forwarded-Port and/or
557 X-Forwarded-Proto header to reverse proxied requests.
558
559 SEE ALSO
560 Perlbal::Manual::Hooks, Perlbal::Manual::Internals.
561
562 There are sample configuration files under conf/; some of these are
563 examples on how to use and configure existing plugins: echoservice.conf
564 for Perlbal::Plugin::EchoService, virtual-hosts.conf for
565 Perlbal::Plugin::VHosts, etc.
566
567
568
569perl v5.36.0 2022-07-20 Perlbal::Manual::Plugins(3)