/
yaws_api.5
515 lines (389 loc) · 12.7 KB
/
yaws_api.5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
.TH YAWS_API "1" "" "" "User API"
.SH NAME
yaws_api \- api available to yaws web server programmers
.SH SYNOPSIS
.B yaws_api:Function(...)
.SH DESCRIPTION
.\" Add any additional description here
.PP
This is the api available to yaws web server programmers. The erlang
module yaws_api contains a wide variety of functions that can
be used inside yaws pages.
.PP
Each chunk of yaws code is executed while the yaws page is
being delivered from the server. We give a very simple example here
to show the basic idea. Imagine the following html code:
\fI
.nf
<html>
<body>
<h1> Header 1</h1>
<erl>
out(Arg) ->
{html, "<p> Insert this text into the document"}.
</erl>
</body>
</html>
.fi
\fR
.PP
The \fBout(Arg)\fR function is supplied one argument, an #arg{} structure.
We have the following relevant record definitions:
\fI
.nf
-record(arg, {
clisock, %% the socket leading to the peer client
headers, %% headers
req, %% request
clidata, %% The client data (as a binary in POST requests)
server_path, %% The normalized server path
querydata, %% Was the URL on the form of ...?query (GET reqs)
appmoddata, %% the remainder of the path leading up to the querey
docroot, %% where's the data
fullpath, %% full path to yaws file
cont, %% Continuation for chunked multipart uploads
state, %% State for use by users of the out/1 callback
pid, %% pid of the yaws worker process
opaque, %% useful to pass static data
appmod_prepath, %% path in front of: <appmod><appmoddata>
pathinfo %% Set to 'd/e' when calling c.yaws for the request
%% http://some.host/a/b/c.yaws/d/e
}).
.fi
\fR
The headers argument is also a record:
\fI
.nf
-record(headers, {
connection,
accept,
host,
if_modified_since,
if_match,
if_none_match,
if_range,
if_unmodified_since,
range,
referer,
user_agent,
accept_ranges,
cookie = [],
keep_alive,
content_length,
authorization,
other = [] %% misc other headers
}).
.fi
\fR
.PP The \fBout/1\fR function can use the Arg to generate any content
it likes. We have the following functions to aid that generation.
.SH API
.TP
\fBssi(DocRoot, ListOfFiles)\fR
Server side include. Just include the files as is in the document. The files
will \fBnot\fR be parsed and searched for <erl> tags.
.TP
\fBpre_ssi_files(DocRoot, ListOfFiles) ->
Server side include of pre indented code. The data in Files
will be included but contained in a <pre> tag. The data will be
htmlized.
.TP
\fBpre_ssi_string(String)\fR
Include htmlized content from String.
.TP
\fBf(Fmt, Args)\fR
The equivalent of io_lib:format/2. This function is automatically
-included in all erlang code which is a part of a yaws page.
.TP
\fBhtmlize(Binary)\fR
Htmlize a binary object.
.TP
\fBhtmlize_l(DeepList)\fR
Htmlize any deep list of chars and binaries.
.TP
\fBsetcookie(Name, Value, [Path, [ Expire, [Domain , [Secure]]]])\fR
Sets a cookie to the browser.
.TP
\fBfind_cookie_val(Cookie, Header)\fR
This function can be used to search for a cookie that was previously
set by \fBsetcookie/2-6\fR. For example if we set a cookie
as \fByaws_api:setcookie("sid",SomeRandomSid) \fR, then on subsequent requests
from the browser we can call:
\fBfind_cookie("sid",(Arg#arg.headers)#headers.cookie)\fR
The function returns [] if no cookie was found, otherwise the actual cookie
is returned as a string.
.TP
\fBredirect(Url\fR
This function generates a redirect to the browser.
It will clear any previously set headers. So to generate
a redirect \fBand\fR set a cookie, we need to set the cookie after
the redirect as in:
\fI
.nf
out(Arg) ->
... do some stuff
Ret = [{redirect, "http://www.somewhere.com"},
setcookie("sid", Random)
].
.fi
\fR
.TP
\fBget_line(String)\fR
This function is convenient when getting \\r\\n terminated lines
from a stream of data. It returns:
\fB{line, Line, Tail}\fR or \fB{lastline, Line, Tail}\fR
The function handles multilines as defined in e.g. SMTP or HTTP
.TP
\fBmime_type(FileName)\fR
Returns the mime type as defined by the extension of FileName
.TP
\fBstream_chunk_deliver(YawsPid, Data)\fR
When a yaws function needs to deliver chunks of data which it gets
from a process. The other process can call this function to deliver
these chunks. It requires the \fBout/1\fR function to return the
value \fB{streamcontent, MimeType, FirstChunk}\fR to work.
.TP
\fBstream_chunk_end(YawsPid)\fR
When the process discussed above is done delivering data, it must call
this function to let the yaws content delivering process finish up
the HTTP transaction.
.TP
\fBparse_query(Arg)\fR
This function will parse the query part of the URL.
It will return a {Key, Value} list of the items supplied in the query
part of the URL.
.TP
\fBqueryvar(Arg, VarName)\fR
This function is automatically included from yaws_api in all
.yaws pages. It is used to search for a variable in the
querypart of the url. Returns {ok, Val} or undefined.
.TP
\fBparse_post(Arg)\fR
This function will parse the POST data as supplied from the browser.
It will return a {Key, Value} list of the items set by the browser.
.TP
\fBpostvar(Arg, VarName)\fR
This function is automatically included from yaws_api in all
.yaws pages. It is used to search for a variable in the
POSTed data from the client. Returns {ok, Val} or undefined.
.TP
\fBparse_multipart_post(Arg)\fR
If the browser has set the Content-Type header to the value
"multipart/form-data", which is the case when the browser
wants to upload a file to the server the following happens:
If the function returns \fB{result, Res}\fR no more data
will come from the browser.
If the function returns \fB{cont, Cont, Res}\fR the browser
will supply more data. (The file was to big to come in one read)
This indicates that there is more data to come and the out/1 function
should return {get_more, Cont, User_state} where User_state might
usefully be a File Descriptor.
The Res value is a list of either:
\fB{header, Header}\fR | \fB{part_body, Binary}\fR | \fB{body, Binary}\fR
Example usage could be:
\fI
.nf
<erl>
out(A) ->
case yaws_api:parse_multipart_post(A) of
{cont, Cont, Res} ->
St = handle_res(A, Res),
{get_more, Cont, St};
{result, Res} ->
handle_res(A, Res),
{html, f("<pre>Done </pre>",[])}
end.
handle_res(A, [{head, Name}|T]) ->
io:format("head:~p~n",[Name]),
handle_res(A, T);
handle_res(A, [{part_body, Data}|T]) ->
io:format("part_body:~p~n",[Data]),
handle_res(A, T);
handle_res(A, [{body, Data}|T]) ->
io:format("body:~p~n",[Data]),
handle_res(A, T);
handle_res(A, []) ->
io:format("End_res~n").
</erl>
.fi
\fR
.TP
\fBnew_cookie_session(Opaque)\fR
Create a new cookie based session, the yaws system will set the
cookie. The new randomgenerated cookie is returned from this
function. The Opaque argument will typically contain user data
such as username and password
.TP
\fBcookieval_to_opaque(CookieVal)\fR
.TP
\fBprint_cookie_sessions() \fR
.TP
\fBreplace_cookie_session(Cookie, NewOpaque)\fR
.TP
\fBdelete_cookie_session(Cookie)\fR
.TP
\fBsetconf(Gconf, Groups)\fR
This function is intended for embedded mode in yaws. It makes it possible
to load a yaws configuration from another data source than /etc/yaws.conf, such
as a database.
If yaws is started with the environment \fI{embedded, true}\fR, yaws will
start with an empty default configuration, and wait for some other
program to execute a \fIsetconf/2\fR
The Gconf is a \fI#gconf{}\fR record and the Group variable is
a list of lists of \fI#sconf{}\fR records. Each sublist must
contain \fI#sconf{}\fR records with the same IP/Port listen address.
.TP
\fBurl_decode(Str)\fR
Decode url-encoded string. A URL ncoded string is a string where
all alfa numeric characters and the the character _ are preserved
and all other characters are encode as "%XY" where X and Y are the
hex values of the least respective most significat 4 bits in the 8 bit
character.
.TP
\fBurl_encode(Str)\fR
Url-encodes a string. All URLs in HTML documents must be URL encoded.
.TP
\fBreformat_header(H)\fR
Returns a list of reformated header values from a #header{}
record. The return list is suitable for retransmit.
.TP
\fBparse_url(Str)\fR
Parse URL in a string, returns a #url record
.TP
\fBformat_url(UrlRecord)\fR
Takes a #url record a formats the Url as a string
.TP
\fBcall_cgi(Arg, Scriptfilename)\fR
Calls an executable CGI script,
given by its full path. Used to make `.yaws' wrappers for CGI
programs. This function usually returns \fIstreamcontent\fR.
.TP
\fBcall_cgi(Arg, Exefilename, Scriptfilename)\fR
Like before, but
calls \fIExefilename\fR to handle the script. The file name of the
script is handed to the executable via a CGI meta variable.
.SH RETURN VALUES from out/1
.PP
The out/1 function can return different values to control the behavior
of the server.
.TP
\fB{html, DeepList}\fB
This assumes that DeepList is formatted HTML code.
The code will be inserted in the page.
.TP
\fB{ehtml, Term}\fR
This will transform the erlang term Term into a
stream of HTML content. The basic syntax of Term
is
\fI
.nf
EHTML = [EHTML] | {Tag, Attrs, Body} | {Tag, Attrs} | {Tag} |
binary() | character()
Tag = atom()
Attrs = [{Key, Value}] or {EventTag, {jscall, FunName, [Args]}}
Key = atom()
Value = string()
Body = EHTML
.fi
\fR
For example, \fI{p, [], "Howdy"}\fR expand into
"<p>Howdy</p> and
\fI
.nf
{form, [{action, "a.yaws"}],
{input, [{type,text}]}}
.fi
\fR
expands into
\fI
.nf
<form action="a.yaws"
<input type="text">
</form>
.fi
\fR
It may be more convenient to generate erlang tuples
than plain html code.
.TP
\fB{content, MimeType, Content}\fR
This function will make the web server generate
different content than HTML. This return value is only allowed
in a yaws file which has only one <erl> </erl> part and no
html parts at all.
.TP
\fB{streamcontent, MimeType, FirstChunk}\fR
This return value plays the same role as the \fIcontent\fR return
value above.
However it makes it possible to stream data to the client
if the yaws code doesn't have access to all the data in one go. (Typically
if a file is very large or if data arrives from back end servers on the network.
.TP
\fB{header, H}\fR
Accumulates a HTTP header. Used by for example the \fBsetcookie/2-6\fR
function.
.TP
\fB{allheaders, HeaderList}\fB
Will clear all previously accumulated headers and replace them.
.TP
\fB{status, Code}\fR
Will set another HTTP status code than 200.
.TP
\fBbreak\fR
Will stop processing of any consecutive chunks of erl or html code
in the yaws file.
.TP
\fBok\fR
Do nothing.
.TP
\fB{redirect, Url}\fR
Erase all previous headers and accumulate a single
Location header. Set the status code.
.TP
\fB{redirect_local, Path}\fR
Does a redirect to the same Scheme://Host:Port/Path as we
currently are executing in.
.TP
\fB{get_more, Cont, State}\fR
When we are receiving large POSTs we can return this value
and be invoked again when more Data arrives.
.TP
\fB{page, Page}\fR
Make Yaws return a different page than the one being
requested.
.TP
\fB{page, {Options, Page}}\fR
Like the above, but supplying an additional deep list of options. For
now, the only type of option is \fI{header, H}\fR with the effect of
accumulating the HTTP header \fIH\fR for page \fIPage\fR.
.TP
\fB{ssi, File, Delimiter, Bindings}\fR
Server side include File and macro expansion in File.
Each occurence of a string, say "xyz", inside File which
is inside Delimters is replaced with the corresponsing
value in Bindings.
Example:
Delimiter = %%
File contains the string .... %%xyz%% .....
Bindings contain the tuple {"xyz", "Dingbat"}
The occurence of %%xyz%% in File will be replaced with "Dingbat"
in the Server side included output.
The {ssi, File, Delimiter, Bindings} statement can also
occur inside a deep ehtml structure.
.TP
\fB{bindings, [{Key1, Value2}, {Key2, Value2} .....]}\fR
Establish variable bindings that can be used in the page.
All bindings can then be used in the rest of yaws code
(in HTML source and within erl tags).
In HTML source %%Key%% is expanded to Value and within erl
tags yaws_api:get_binding(Key) can be used to extract Value.
.TP
\fB[ListOfValues]\fR
It is possible to return a deep list of the above defined
return values. Any occurrence of \fIstream_content\fR, \fIget_more\fR
or \fIpage\fR in this list is legal only if it is the last position of
the list.
.SH AUTHOR
Written by Claes Wikstrom
.SH "SEE ALSO"
.BR yaws.conf (5)
.BR erl (1)