]> sipb.mit.edu Git - ikiwiki.git/blob - doc/plugins/write/external.mdwn
mention proxy.py
[ikiwiki.git] / doc / plugins / write / external.mdwn
1 External plugins are standalone, executable programs, that can be written
2 in any language. When ikiwiki starts up, it runs the program, and
3 communicates with it using XML RPC. If you want to [[write]] an external
4 plugin, read on..
5
6 ikiwiki contains one sample external plugin, named `externaldemo`. This is
7 written in perl, but is intended to be an example of how to write an
8 external plugin in your favorite programming language. Wow us at how much
9 easier you can do the same thing in your favorite language. ;-)
10
11 There's now a second external plugin, the [[rst]] plugin, written in
12 python. It uses a `proxy.py`, a helper library for ikiwiki python plugins.
13
14 [[toc ]]
15
16 ## How external plugins use XML RPC
17
18 While XML RPC is typically used over http, ikiwiki doesn't do that.
19 Instead, the external plugin reads XML RPC data from stdin, and writes it
20 to stdout. To ease parsing, each separate XML RPC request or response must
21 start at the beginning of a line, and end with a newline. When outputting
22 XML RPC to stdout, be _sure_ to flush stdout. Failure to do so will result
23 in deadlock!
24
25 An external plugin should operate in a loop. First, read a command from
26 stdin, using XML RPC. Dispatch the command, and return its result to
27 stdout, also using XML RPC. After reading a command, and before returning
28 the result, the plugin can output XML RPC requests of its own, calling
29 functions in ikiwiki. Note: *Never* make an XML RPC request at any other
30 time. Ikiwiki won't be listening for it, and you will deadlock.
31
32 When ikiwiki starts up an external plugin, the first RPC it will make
33 is to call the plugin's `import()` function. That function typically makes
34 an RPC to ikiwiki's `hook()` function, registering a callback.
35
36 An external plugin can use XML RPC to call any of the exported functions
37 documented in the [[plugin_interface_documentation|write]]. It can also
38 actually call any non-exported IkiWiki function, but doing so is a good way
39 to break your plugin when ikiwiki changes. There is currently no versioned
40 interface like there is for perl plugins, but external plugins were first
41 supported in ikiwiki version 2.6.
42
43 ## Accessing data structures
44
45 Ikiwiki has a few global data structures such as `%config`, which holds
46 its configuration. External plugins can use the `getvar` and `setvar` RPCs
47 to access any such global hash. To get the "url" configuration value,
48 call `getvar("config", "url")`. To set it, call 
49 `setvar("config", "url", "http://example.com/)`.
50
51 The `%pagestate` is a special hash with a more complex format. To access
52 it, external plugins can use the `getstate` and `setstate` RPCs. To access
53 stored state, call `getstate("page", "id", "key")`, and to store state,
54 call `setstate("page", "id", "key", "value")`.
55
56 ## Notes on function parameters
57
58 The [[plugin_interface_documentation|write]] talks about functions that take
59 "named parameters". When such a function is called over XML RPC, such named
60 parameters look like a list of keys and values:
61
62         page, foo, destpage, bar, magnify, 1
63
64 If a name is repeated in the list, the later value overrides the earlier
65 one:
66
67         name, Bob, age, 20, name, Sally, gender, female
68
69 In perl, boiling this down to an associative array of named parameters is
70 very easy:
71
72         sub foo {
73                 my %params=@list;
74
75 Other languages might not find it so easy. If not, it might be a good idea
76 to convert these named parameters into something more natural for the
77 language as part of their XML RPC interface.
78
79 ## Function injection
80
81 Some parts of ikiwiki are extensible by adding functions. For example, the
82 RCS interface relies on plugins providing several IkiWiki::rcs_* functions.
83 It's actually possible to do this from an external plugin too. 
84
85 To make your external plugin provide an `IkiWiki::rcs_update` function, for
86 example, make an RPC call to `inject`. Pass it named parameters "name" and
87 "call", where "name" is the name of the function to inject into perl (here
88 "Ikiwiki::rcs_update" and "call" is the RPC call ikiwiki will make whenever
89 that function is run.
90
91 If the RPC call is memoizable, you can also pass a "memoize" parameter, set
92 to 1.
93
94 ## Limitations of XML RPC
95
96 Since XML RPC can't pass around references to objects, it can't be used
97 with functions that take or return such references. That means you can't
98 100% use XML RPC for `cgi` or `formbuilder` hooks (which are passed CGI and
99 FormBuilder perl objects), or use it to call `template()` (which returns a
100 perl HTML::Template object).
101
102 Also. the `getopt` hook doesn't work, as ARGV is not available to the external
103 plugin.
104
105 ## Performance issues
106
107 Since each external plugin is a separate process, when ikiwiki is
108 configured to use lots of external plugins, it will start up slower, and
109 use more resources. One or two should not be a problem though.
110
111 There is some overhead in using XML RPC for function calls. Most plugins
112 should find it to be pretty minimal though. In one benchmark, ikiwiki was
113 able to perform 10000 simple XML RPC calls in 11 seconds -- 900 per second.
114
115 Using external plugins for hooks such as `sanitize` and `format`, which
116 pass around entire pages, and are run for each page rendered, will cause
117 more XML RPC overhead than usual, due to the larger number of calls, and the
118 large quantity of data conversion going on. In contrast, `preprocess` hooks
119 are called generally rarely, and pass around minimal data.
120
121 External plugins should avoid making RPC calls unnecessarily (ie, in a loop).
122 Memoizing the results of appropriate RPC calls is one good way to minimise the
123 number of calls.
124
125 Injecting a replacement for a commonly called ikiwiki function
126 could result in a lot more RPC calls than expected and slow
127 eveything down. `pagetitle`, for instance, is called about 100 times
128 per page build. Whenever possible, you should tell ikiwiki to memoize
129 injected functions.
130
131 In general, use common sense, and your external plugin will probably
132 perform ok.