mirror of
https://github.com/bdnugget/kcgi.git
synced 2026-11-07 05:47:27 +00:00
Split khttp_templatex functions out of khttp_template.3.
Provide working examples for both.
This commit is contained in:
1 parent
15a2db7654
commit
cfe14c8cce
4 files changed
+357
-191
No files matched your search
@@ -104,6 +104,7 @@ MAN3S = man/kcgi.3 \
|
||||
man/khttp_putc.3 \
|
||||
man/khttp_puts.3 \
|
||||
man/khttp_template.3 \
|
||||
man/khttp_templatex.3 \
|
||||
man/khttp_urlabs.3 \
|
||||
man/khttp_urldecode.3 \
|
||||
man/khttp_urlencode.3 \
|
||||
|
||||
@@ -311,6 +311,7 @@ string) for the full HTTP message body.
|
||||
.Xr khttp_putc 3 ,
|
||||
.Xr khttp_puts 3 ,
|
||||
.Xr khttp_template 3 ,
|
||||
.Xr khttp_templatex 3 ,
|
||||
.Xr khttp_write 3 ,
|
||||
.Xr khttpbasic_validate 3 ,
|
||||
.Xr khttpdigest_validate 3 ,
|
||||
|
||||
+108
-191
@@ -1,6 +1,6 @@
|
||||
.\" $Id$
|
||||
.\"
|
||||
.\" Copyright (c) 2014, 2017--2018 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
.\" Copyright (c) 2014, 2017--2018, 2020 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
.\" Copyright (c) 2018 Ingo Schwarze <schwarze@openbsd.org>
|
||||
.\"
|
||||
.\" Permission to use, copy, modify, and distribute this software for any
|
||||
@@ -20,11 +20,8 @@
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm khttp_template ,
|
||||
.Nm khttp_templatex ,
|
||||
.Nm khttp_template_buf ,
|
||||
.Nm khttp_templatex_buf ,
|
||||
.Nm khttp_template_fd ,
|
||||
.Nm khttp_templatex_fd
|
||||
.Nm khttp_template_fd
|
||||
.Nd emit filled-in templates for kcgi
|
||||
.Sh LIBRARY
|
||||
.Lb libkcgi
|
||||
@@ -40,13 +37,6 @@
|
||||
.Fa "const char *filename"
|
||||
.Fc
|
||||
.Ft enum kcgi_err
|
||||
.Fo khttp_templatex
|
||||
.Fa "const struct ktemplate *t"
|
||||
.Fa "const char *filename"
|
||||
.Fa "const struct ktemplatex *tx"
|
||||
.Fa "void *arg"
|
||||
.Fc
|
||||
.Ft enum kcgi_err
|
||||
.Fo khttp_template_buf
|
||||
.Fa "struct kreq *req"
|
||||
.Fa "const struct ktemplate *t"
|
||||
@@ -54,45 +44,31 @@
|
||||
.Fa "size_t sz"
|
||||
.Fc
|
||||
.Ft enum kcgi_err
|
||||
.Fo khttp_templatex_buf
|
||||
.Fa "const struct ktemplate *t"
|
||||
.Fa "const char *buf"
|
||||
.Fa "size_t sz"
|
||||
.Fa "const struct ktemplatex *tx"
|
||||
.Fa "void *arg"
|
||||
.Fc
|
||||
.Ft enum kcgi_err
|
||||
.Fo khttp_template_fd
|
||||
.Fa "struct kreq *req"
|
||||
.Fa "const struct ktemplate *t"
|
||||
.Fa "int fd"
|
||||
.Fa "const char *filename"
|
||||
.Fc
|
||||
.Ft enum kcgi_err
|
||||
.Fo khttp_templatex_fd
|
||||
.Fa "const struct ktemplate *t"
|
||||
.Fa "int fd"
|
||||
.Fa "const char *filename"
|
||||
.Fa "const struct ktemplatex *tx"
|
||||
.Fa "void *arg"
|
||||
.Fc
|
||||
.Sh DESCRIPTION
|
||||
These template functions write a block of HTTP output,
|
||||
replacing certain substrings with variable content.
|
||||
They operate in a
|
||||
.Xr kcgi 3
|
||||
context
|
||||
Modify input by replacing keys in a template.
|
||||
May only be called after
|
||||
.Xr khttp_body 3 .
|
||||
Output is written with
|
||||
.Xr khttp_write 3
|
||||
using the
|
||||
.Fa req
|
||||
allocated with
|
||||
previously allocated with
|
||||
.Xr khttp_parse 3
|
||||
or
|
||||
.Xr khttp_fcgi_parse 3
|
||||
and may only be called after
|
||||
.Xr khttp_body 3 .
|
||||
.Xr khttp_fcgi_parse 3 .
|
||||
The
|
||||
.Xr khttp_templatex 3
|
||||
family allows for alternative writers.
|
||||
.Pp
|
||||
All template functions accept a
|
||||
.Fa "const struct ktemplate *t"
|
||||
argument consisting of the following fields:
|
||||
All functions accept a template
|
||||
.Fa t
|
||||
consisting of the following fields:
|
||||
.Bl -tag -width Ds
|
||||
.It Fa "const char *const *key"
|
||||
An array of keys to be replaced in the template.
|
||||
@@ -111,148 +87,71 @@ is found in
|
||||
.Fa t->key .
|
||||
The optional
|
||||
.Fa arg
|
||||
is passed to the current writing function.
|
||||
This callback function normally uses
|
||||
.Xr khttp_write 3
|
||||
or
|
||||
.Fa tx->writer
|
||||
to write data.
|
||||
is passed the function.
|
||||
The function must return zero on failure, non-zero on success.
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Fn khttp_template ,
|
||||
.Fn khttp_template_fd ,
|
||||
and
|
||||
.Fn khttp_template_buf
|
||||
functions use
|
||||
.Xr khttp_write 3
|
||||
as the current writing function.
|
||||
.Pp
|
||||
The
|
||||
.Fn khttp_templatex ,
|
||||
.Fn khttp_templatex_buf ,
|
||||
and
|
||||
.Fn khttp_templatex_fd
|
||||
functions extend this behaviour with an additional
|
||||
.Fa "const struct ktemplatex *tx"
|
||||
argument having the following fields:
|
||||
.Bl -tag -width Ds
|
||||
.It Fa "enum kcgi_err (*writer)(const char *b, size_t sz, void *arg)"
|
||||
Sets the current writing function that writes
|
||||
.Fa sz
|
||||
bytes pointed to by
|
||||
.Fa b .
|
||||
The
|
||||
.Fa arg
|
||||
argument is as passed to the function; it may be
|
||||
.Dv NULL .
|
||||
Any return value but
|
||||
.Dv KCGI_OK
|
||||
is considered an error.
|
||||
.It Fa "int (*fbk)(const char *k, size_t sz, void *arg)"
|
||||
If an encountered key
|
||||
.Fa k
|
||||
of length
|
||||
.Fa sz
|
||||
is not found in
|
||||
.Fa t->key ,
|
||||
this function is invoked.
|
||||
The field
|
||||
.Fa t->arg
|
||||
is passed as the
|
||||
.Fa arg .
|
||||
This function normally uses the writing function in
|
||||
.Fa tx->writer
|
||||
to write data.
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Fa tx->writer
|
||||
callback may not be
|
||||
.Dv NULL .
|
||||
.Pp
|
||||
The functions
|
||||
.Fn khttp_template
|
||||
and
|
||||
.Fn khttp_templatex
|
||||
open
|
||||
.Fa filename
|
||||
in read-only mode and call the descriptor functions.
|
||||
.Pp
|
||||
The descriptor functions
|
||||
.Fn khttp_template_fd
|
||||
and
|
||||
.Fn khttp_templatex_fd
|
||||
read the template from the open file descriptor
|
||||
.Fa fd
|
||||
using
|
||||
.Xr mmap 2
|
||||
and call the buffer functions.
|
||||
They only use the
|
||||
.Fa filename
|
||||
for error reporting.
|
||||
If it is
|
||||
.Dv NULL ,
|
||||
.Qq <unknown descriptor>
|
||||
is used.
|
||||
.Pp
|
||||
The buffer functions
|
||||
.Fn khttp_template_buf
|
||||
and
|
||||
.Fn khttp_templatex_buf
|
||||
read the template from the buffer
|
||||
.Fa buf
|
||||
of length
|
||||
.Fa sz .
|
||||
If
|
||||
.Fa sz
|
||||
is 0, the template is considered empty and
|
||||
.Fa buf
|
||||
is ignored.
|
||||
.Ss Template language
|
||||
Each substring of the template buffer beginning and ending with a pair
|
||||
of
|
||||
.Dq at
|
||||
signs,
|
||||
.Cm @@ Ns Ar key Ns Cm @@ ,
|
||||
is called a
|
||||
.Dq key sequence .
|
||||
If the
|
||||
.Dq at
|
||||
pair is escaped with a single backslash,
|
||||
.Cm \e@@ ,
|
||||
the backslash is removed and it's emitted as
|
||||
.Cm @@ .
|
||||
A key sequence may not contain an escaped pair: this is parsed as a backslash
|
||||
followed by the trailing pair.
|
||||
.Pp
|
||||
If the
|
||||
.Ar key
|
||||
is found in
|
||||
.Fa t->key ,
|
||||
the key sequence is removed from the buffer and the callback
|
||||
.Fa t->cb
|
||||
is invoked.
|
||||
Otherwise, if the fallthrough callback
|
||||
.Fa tx->fbk
|
||||
is not
|
||||
.Dv NULL ,
|
||||
the key sequence is removed from the buffer and the callback
|
||||
.Fa tx-fbk
|
||||
is invoked.
|
||||
If the key sequence is not found in
|
||||
.Fa t->key
|
||||
and the fallthrough callback is
|
||||
.Dv NULL ,
|
||||
the key sequence is passed unchanged to the current writing function.
|
||||
.Pp
|
||||
If
|
||||
.Fa t
|
||||
is
|
||||
.Dv NULL ,
|
||||
the whole template is passed through without any processing.
|
||||
the input is passed through to
|
||||
.Xr khttp_write 3
|
||||
without any processing.
|
||||
.Pp
|
||||
Otherwise, the input is passed to
|
||||
.Xr khttp_write 3
|
||||
until a key sequence in encountered matching a key in
|
||||
.Fa t->key .
|
||||
The callback
|
||||
.Fa t->cb
|
||||
is then invoked instead of printing the key sequence.
|
||||
If there are multiple matching keys in
|
||||
.Fa t->key ,
|
||||
only one is used (which is not yet fixed).
|
||||
If the key sequence is not found in
|
||||
.Fa t->key ,
|
||||
it is passed unchanged to
|
||||
.Xr khttp_write 3 .
|
||||
.Pp
|
||||
The different input types are
|
||||
.Fn khttp_template ,
|
||||
which reads input from the file
|
||||
.Fa filename ;
|
||||
.Fn khttp_template_buf ,
|
||||
which reads from a binary buffer
|
||||
.Fa buf
|
||||
of length
|
||||
.Fa sz ;
|
||||
and
|
||||
.Fn khttp_template_fd ,
|
||||
which reads from a file descriptor
|
||||
.Fa fd
|
||||
with optional file-name
|
||||
.Fa fname
|
||||
used only for logging purposes.
|
||||
.Sh SYNTAX
|
||||
Each substring of the input beginning and ending with a pair
|
||||
of
|
||||
.Dq at
|
||||
signs,
|
||||
.Cm @@ Ns Ar key Ns Cm @@ ,
|
||||
is called a
|
||||
.Qq key sequence .
|
||||
Zero-length keys
|
||||
.Cm @@@@
|
||||
are allowed and match empty template keys.
|
||||
If the
|
||||
.Cm @@
|
||||
pair is escaped with a single backslash,
|
||||
.Cm \e@@ ,
|
||||
the backslash is removed and it's emitted as
|
||||
.Cm @@ .
|
||||
.Pp
|
||||
A key sequence may not contain an escaped pair: this is parsed as a
|
||||
backslash followed by the trailing pair.
|
||||
.Sh RETURN VALUES
|
||||
These functions return an
|
||||
These return an
|
||||
.Ft enum kcgi_err
|
||||
indicating the error state:
|
||||
.Bl -tag -width KCGI_SYSTEM
|
||||
@@ -264,34 +163,52 @@ Memory allocation failed.
|
||||
A system call failed.
|
||||
For example, writing to the output stream failed, or
|
||||
.Fn khttp_template
|
||||
or
|
||||
.Fn khttp_templatex
|
||||
failed to
|
||||
.Xr open 2
|
||||
.Fa filename .
|
||||
.It Dv KCGI_FORM
|
||||
.Fa t->cb
|
||||
or
|
||||
.Fa tx->fbk
|
||||
returned 0.
|
||||
.El
|
||||
.Sh EXAMPLES
|
||||
The following simple example takes a buffer
|
||||
.Fa buf
|
||||
and applies the replacement template of two values, writing it to the
|
||||
current context
|
||||
.Fa req .
|
||||
.Bd -literal -offset indent
|
||||
static int writer(size_t idx, void *arg)
|
||||
{
|
||||
struct kreq *r = arg;
|
||||
if (idx == 0)
|
||||
khttp_puts(r, "foo-value");
|
||||
else if (idx == 1)
|
||||
khttp_puts(r, "bar-value");
|
||||
return 1;
|
||||
}
|
||||
|
||||
enum kcgi_err format(struct kreq *r)
|
||||
{
|
||||
const char *const keys[] = { "foo", "bar" };
|
||||
struct ktemplate t = {
|
||||
.key = keys,
|
||||
.keysz = 2,
|
||||
.arg = r,
|
||||
.cb = writer
|
||||
};
|
||||
const char *buf = "foo=@@foo@@, bar=@@bar@@";
|
||||
return khttp_template_buf(r, &t, buf, strlen(buf));
|
||||
}
|
||||
.Ed
|
||||
.Pp
|
||||
An empty template produces no output, and
|
||||
.Dv KCGI_OK
|
||||
is returned.
|
||||
The function will produce
|
||||
.Qq foo=foo-value, bar=bar-value .
|
||||
.Sh SEE ALSO
|
||||
.Xr kcgi 3 ,
|
||||
.Xr khttp_body 3 ,
|
||||
.Xr khttp_parse 3 ,
|
||||
.Xr khttp_templatex 3 ,
|
||||
.Xr khttp_write 3
|
||||
.Sh AUTHORS
|
||||
These functions were written by
|
||||
Written by
|
||||
.An Kristaps Dzonsons Aq Mt kristaps@bsd.lv .
|
||||
.Sh CAVEATS
|
||||
The
|
||||
.Fn khttp_template
|
||||
and
|
||||
.Fn khttp_templatex
|
||||
functions need access to the file system.
|
||||
Read the files before entering a sandbox and use the buffer or file
|
||||
descriptor versions instead.
|
||||
@@ -0,0 +1,247 @@
|
||||
.\" $Id$
|
||||
.\"
|
||||
.\" Copyright (c) 2014, 2017--2018, 2020 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
.\" Copyright (c) 2018 Ingo Schwarze <schwarze@openbsd.org>
|
||||
.\"
|
||||
.\" Permission to use, copy, modify, and distribute this software for any
|
||||
.\" purpose with or without fee is hereby granted, provided that the above
|
||||
.\" copyright notice and this permission notice appear in all copies.
|
||||
.\"
|
||||
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.Dd $Mdocdate$
|
||||
.Dt KHTTP_TEMPLATEX 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm khttp_templatex ,
|
||||
.Nm khttp_templatex_buf ,
|
||||
.Nm khttp_templatex_fd
|
||||
.Nd emit filled-in templates for kcgi
|
||||
.Sh LIBRARY
|
||||
.Lb libkcgi
|
||||
.Sh SYNOPSIS
|
||||
.In sys/types.h
|
||||
.In stdarg.h
|
||||
.In stdint.h
|
||||
.In kcgi.h
|
||||
.Ft enum kcgi_err
|
||||
.Fo khttp_templatex
|
||||
.Fa "const struct ktemplate *t"
|
||||
.Fa "const char *filename"
|
||||
.Fa "const struct ktemplatex *x"
|
||||
.Fa "void *arg"
|
||||
.Fc
|
||||
.Ft enum kcgi_err
|
||||
.Fo khttp_templatex_buf
|
||||
.Fa "const struct ktemplate *t"
|
||||
.Fa "const char *buf"
|
||||
.Fa "size_t sz"
|
||||
.Fa "const struct ktemplatex *x"
|
||||
.Fa "void *arg"
|
||||
.Fc
|
||||
.Ft enum kcgi_err
|
||||
.Fo khttp_templatex_fd
|
||||
.Fa "const struct ktemplate *t"
|
||||
.Fa "int fd"
|
||||
.Fa "const char *filename"
|
||||
.Fa "const struct ktemplatex *x"
|
||||
.Fa "void *arg"
|
||||
.Fc
|
||||
.Sh DESCRIPTION
|
||||
Modify input by replacing keys in a template.
|
||||
This generalises the
|
||||
.Xr khttp_template 3
|
||||
family of functions with generic writing functions.
|
||||
All functions accept a template
|
||||
.Fa t
|
||||
consisting of the following fields:
|
||||
.Bl -tag -width Ds
|
||||
.It Fa "const char *const *key"
|
||||
An array of keys to be replaced in the template.
|
||||
.It Fa "size_t keysz"
|
||||
The number of keys in
|
||||
.Fa t->key .
|
||||
.It Fa "void *arg"
|
||||
An optional argument passed to
|
||||
.Fa t->cb .
|
||||
.It Fa "int (*cb)(size_t index, void *arg)"
|
||||
The callback function invoked when a key at position
|
||||
.Fa index ,
|
||||
which is always less than
|
||||
.Fa t->keysz ,
|
||||
is found in
|
||||
.Fa t->key .
|
||||
The optional
|
||||
.Fa arg
|
||||
is passed the function.
|
||||
The function must return zero on failure, non-zero on success.
|
||||
.El
|
||||
.Pp
|
||||
They further accept an extension
|
||||
.Fa x
|
||||
consisting of the following:
|
||||
.Bl -tag -width Ds
|
||||
.It Fa writer
|
||||
A writing function for writing input that does not match key sequences.
|
||||
If it is invoked and the return value is not
|
||||
.Dv KCGI_OK ,
|
||||
templating stops and the return value is returned to the caller.
|
||||
.It Fa fbk
|
||||
A fall-back function invoked if a key sequences was not found in the
|
||||
.Fa c->key
|
||||
array.
|
||||
This accepts the key sequence, length of the sequence, and
|
||||
.Fa arg .
|
||||
If
|
||||
.Dv NULL ,
|
||||
key sequences not found are passed to
|
||||
.Fa writer .
|
||||
.El
|
||||
.Pp
|
||||
If
|
||||
.Fa t
|
||||
is
|
||||
.Dv NULL ,
|
||||
the input is passed through to
|
||||
.Fa x->writer
|
||||
without any processing.
|
||||
.Pp
|
||||
Otherwise, the input is passed to
|
||||
.Fa x->writer
|
||||
until a key sequence in encountered matching a key in
|
||||
.Fa t->key .
|
||||
The callback
|
||||
.Fa t->cb
|
||||
is then invoked instead of printing the key sequence.
|
||||
If there are multiple matching keys in
|
||||
.Fa t->key ,
|
||||
only one is used (which is not yet fixed).
|
||||
If the key sequence is not found in
|
||||
.Fa t->key ,
|
||||
it is passed to
|
||||
.Fa x->fbk ,
|
||||
if not
|
||||
.Dv NULL ,
|
||||
or passed directly to
|
||||
.Fa x->writer
|
||||
otherwise.
|
||||
.Pp
|
||||
The different input types are
|
||||
.Fn khttpx_template ,
|
||||
which reads input from the file
|
||||
.Fa filename ;
|
||||
.Fn khttpx_template_buf ,
|
||||
which reads from a binary buffer
|
||||
.Fa buf
|
||||
of length
|
||||
.Fa sz ;
|
||||
and
|
||||
.Fn khttpx_template_fd ,
|
||||
which reads from a file descriptor
|
||||
.Fa fd
|
||||
with optional file-name
|
||||
.Fa fname
|
||||
used only for logging purposes.
|
||||
.Sh SYNTAX
|
||||
Each substring of the input beginning and ending with a pair
|
||||
of
|
||||
.Dq at
|
||||
signs,
|
||||
.Cm @@ Ns Ar key Ns Cm @@ ,
|
||||
is called a
|
||||
.Qq key sequence .
|
||||
Zero-length keys
|
||||
.Cm @@@@
|
||||
are allowed and match empty template keys.
|
||||
If the
|
||||
.Cm @@
|
||||
pair is escaped with a single backslash,
|
||||
.Cm \e@@ ,
|
||||
the backslash is removed and it's emitted as
|
||||
.Cm @@ .
|
||||
.Pp
|
||||
A key sequence may not contain an escaped pair: this is parsed as a
|
||||
backslash followed by the trailing pair.
|
||||
.Sh RETURN VALUES
|
||||
These return an
|
||||
.Ft enum kcgi_err
|
||||
indicating the error state:
|
||||
.Bl -tag -width KCGI_SYSTEM
|
||||
.It Dv KCGI_OK
|
||||
No error occurred.
|
||||
.It Dv KCGI_ENOMEM
|
||||
Memory allocation failed.
|
||||
.It Dv KCGI_SYSTEM
|
||||
A system call failed.
|
||||
For example, writing to the output stream failed, or
|
||||
.Fn khttp_template
|
||||
failed to
|
||||
.Xr open 2
|
||||
.Fa filename .
|
||||
.It Dv KCGI_FORM
|
||||
.Fa t->cb
|
||||
returned 0.
|
||||
.El
|
||||
.Pp
|
||||
If the
|
||||
.Fa x->writer
|
||||
function returns anything but
|
||||
.Dv KCGI_OK ,
|
||||
the return code is passed as the return value.
|
||||
.Sh EXAMPLES
|
||||
The following simple example takes a buffer
|
||||
.Fa buf
|
||||
and applies the replacement template of two values, writing it to the
|
||||
current context
|
||||
.Fa req .
|
||||
It stores the result in the given buffer
|
||||
.Fa out .
|
||||
.Bd -literal -offset indent
|
||||
static int writer(size_t idx, void *arg)
|
||||
{
|
||||
struct kcgi_buf *p = arg;
|
||||
if (idx == 0)
|
||||
kcgi_buf_puts(p, "foo-value");
|
||||
else if (idx == 1)
|
||||
kcgi_buf_puts(p, "bar-value");
|
||||
return 1;
|
||||
}
|
||||
|
||||
enum kcgi_err format(struct kcgi_buf *out)
|
||||
{
|
||||
const char *const keys[] = { "foo", "bar" };
|
||||
struct ktemplate t = {
|
||||
.key = keys,
|
||||
.keysz = 2,
|
||||
.arg = out,
|
||||
.cb = writer
|
||||
};
|
||||
struct ktemplatex x = {
|
||||
.writer = kcgi_buf_write,
|
||||
.fbk = NULL
|
||||
};
|
||||
const char *in = "foo=@@foo@@, bar=@@bar@@";
|
||||
|
||||
memset(&out, 0, sizeof(struct kcgi_buf));
|
||||
return khttp_templatex_buf
|
||||
(&t, in, strlen(in), &x, out);
|
||||
}
|
||||
.Ed
|
||||
.Pp
|
||||
The function will produce
|
||||
.Qq foo=foo-value, bar=bar-value .
|
||||
.Sh SEE ALSO
|
||||
.Xr kcgi 3 ,
|
||||
.Xr khttp_body 3 ,
|
||||
.Xr khttp_parse 3 ,
|
||||
.Xr khttp_template 3 ,
|
||||
.Xr khttp_write 3
|
||||
.Sh AUTHORS
|
||||
Written by
|
||||
.An Kristaps Dzonsons Aq Mt kristaps@bsd.lv .
|
||||
Reference in new issue
Block a user