[sources] Add support for --sbom-* and /__/kawipiko/sbom.*; add support for /__/kawipiko/manual.*; move special pages under /__/kawipiko/*.

This commit is contained in:
Ciprian Dorin Craciun 2022-09-02 16:01:50 +03:00
parent d9de6b85af
commit d3fea01477
21 changed files with 1811 additions and 28 deletions

View file

@ -71,6 +71,8 @@ kawipiko -- blazingly fast static HTTP server \- kawipiko-archiver
\-\-sources\-md5 (dump an \(ga\(gamd5sum\(ga\(ga of the sources) \-\-sources\-md5 (dump an \(ga\(gamd5sum\(ga\(ga of the sources)
\-\-sources\-cpio (dump a \(ga\(gacpio.gz\(ga\(ga of the sources) \-\-sources\-cpio (dump a \(ga\(gacpio.gz\(ga\(ga of the sources)
\-\-sbom \-\-sbom\-text \-\-sbom\-json
.ft P .ft P
.fi .fi
.UNINDENT .UNINDENT

View file

@ -0,0 +1,514 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<title>kawipiko -- blazingly fast static HTTP server</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 7952 2016-07-26 18:15:59Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
.subscript {
vertical-align: sub;
font-size: smaller }
.superscript {
vertical-align: super;
font-size: smaller }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
overflow: hidden;
}
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title, .code .error {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin: 0 0 0.5em 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr.docutils {
width: 75% }
img.align-left, .figure.align-left, object.align-left, table.align-left {
clear: left ;
float: left ;
margin-right: 1em }
img.align-right, .figure.align-right, object.align-right, table.align-right {
clear: right ;
float: right ;
margin-left: 1em }
img.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
table.align-center {
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left }
.align-center {
clear: both ;
text-align: center }
.align-right {
text-align: right }
/* reset inner alignment in figures */
div.align-right {
text-align: inherit }
/* div.align-center * { */
/* text-align: left } */
.align-top {
vertical-align: top }
.align-middle {
vertical-align: middle }
.align-bottom {
vertical-align: bottom }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font: inherit }
pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
pre.code .ln { color: grey; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre {
white-space: pre }
span.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.footnote {
border-left: solid 1px black;
margin-left: 1px }
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
border: 0px;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.docutils.booktabs * {
border: 0px;
}
table.docutils.booktabs th {
border-bottom: thin solid;
text-align: left;
}
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
ul.auto-toc {
list-style-type: none }
</style>
</head>
<body>
<div class="document" id="kawipiko-blazingly-fast-static-http-server">
<h1 class="title">kawipiko -- blazingly fast static HTTP server</h1>
<h2 class="subtitle" id="kawipiko-archiver"><tt class="docutils literal"><span class="pre">kawipiko-archiver</span></tt></h2>
<pre class="literal-block">
&gt;&gt; kawipiko-archiver --help
&gt;&gt; kawipiko-archiver --man
</pre>
<pre class="literal-block">
--sources &lt;path&gt;
--archive &lt;path&gt;
--compress &lt;gzip | zopfli | brotli | identity&gt;
--compress-level &lt;number&gt;
--compress-cache &lt;path&gt;
--exclude-index
--exclude-strip
--exclude-cache
--include-etag
--exclude-slash-redirects
--include-folder-listing
--exclude-paths-index
--progress --debug
--version
--help (show this short help)
--man (show the full manual)
--sources-md5 (dump an ``md5sum`` of the sources)
--sources-cpio (dump a ``cpio.gz`` of the sources)
--sbom --sbom-text --sbom-json
</pre>
<hr class="docutils" />
<div class="section" id="flags">
<h1>Flags</h1>
<p><tt class="docutils literal"><span class="pre">--sources</span></tt></p>
<blockquote>
The path to the source folder that is the root of the static website content.</blockquote>
<p><tt class="docutils literal"><span class="pre">--archive</span></tt></p>
<blockquote>
The path to the target CDB file that contains the archived static content.</blockquote>
<p><tt class="docutils literal"><span class="pre">--compress</span></tt>, and <tt class="docutils literal"><span class="pre">--compress-level</span></tt></p>
<blockquote>
<p>Each individual file (and consequently of the corresponding HTTP response body) is compressed with either <tt class="docutils literal">gzip</tt>, <tt class="docutils literal">zopfli</tt> or <tt class="docutils literal">brotli</tt>; by default (or alternatively with <tt class="docutils literal">identity</tt>) no compression is used.</p>
<p>Even if compression is explicitly requested, if the compression ratio is bellow a certain threshold (depending on the uncompressed size), the file is stored without any compression.
(It's senseless to force the client to spend time and decompress the response body if that time is not recovered during network transmission.)</p>
<p>The compression level can be chosen, the value depending on the algorithm:</p>
<ul class="simple">
<li><tt class="docutils literal">gzip</tt> -- <tt class="docutils literal"><span class="pre">-1</span></tt> for algorithm default, <tt class="docutils literal"><span class="pre">-2</span></tt> for Huffman only, <tt class="docutils literal">0</tt> to <tt class="docutils literal">9</tt> for fast to slow;</li>
<li><tt class="docutils literal">zopfli</tt> -- <tt class="docutils literal"><span class="pre">-1</span></tt> for algorithm default, <tt class="docutils literal">0</tt> to <tt class="docutils literal">30</tt> iterations for fast to slow;</li>
<li><tt class="docutils literal">brotli</tt> -- <tt class="docutils literal"><span class="pre">-1</span></tt> for algorithm default, <tt class="docutils literal">0</tt> to <tt class="docutils literal">9</tt> for fast to slow, <tt class="docutils literal"><span class="pre">-2</span></tt> for extreme;</li>
<li>(by &quot;algorithm default&quot;, it is meant &quot;what that algorithm considers the recommended default compression level&quot;;)</li>
<li><tt class="docutils literal">kawipiko</tt> by default uses the maximum compression level for each algorithm; (i.e. <tt class="docutils literal">9</tt> for <tt class="docutils literal">gzip</tt>, <tt class="docutils literal">30</tt> for <tt class="docutils literal">zopfli</tt>, and <tt class="docutils literal"><span class="pre">-2</span></tt> for <tt class="docutils literal">brotli</tt>;)</li>
</ul>
</blockquote>
<p><tt class="docutils literal"><span class="pre">--sources-cache</span> &lt;path&gt;</tt>, and <tt class="docutils literal"><span class="pre">--compress-cache</span> &lt;path&gt;</tt></p>
<blockquote>
<p>At the given path a single file is created (that is an BBolt database), that will be used to cache the following information:</p>
<ul class="simple">
<li>in case of <tt class="docutils literal"><span class="pre">--sources-cache</span></tt>, the fingerprint of each file contents is stored, so that if the file was not changed, re-reading it shouldn't be attempted unless it is absolutely necessary; also if the file is small enough, its contents is stored in this database (deduplicated by its fingerprint);</li>
<li>in case of <tt class="docutils literal"><span class="pre">--compress-cache</span></tt> the compression outcome of each file contents is stored (deduplicated by its fingerprint), so that compression is done only once over multiple runs;</li>
</ul>
<p>Each of these caches can be safely reused between multiple related archives, especially when they have many files in common.
Each of these caches can be independently used (or shared).</p>
<p>Using these caches allows one to very quickly rebuild an archive when only a couple of files have been changed, without even touching the file-system for the unchanged ones.</p>
</blockquote>
<p><tt class="docutils literal"><span class="pre">--exclude-index</span></tt></p>
<blockquote>
Disables using <tt class="docutils literal">_index.*</tt> and <tt class="docutils literal">index.*</tt> files (where <tt class="docutils literal">.*</tt> is one of <tt class="docutils literal">.html</tt>, <tt class="docutils literal">.htm</tt>, <tt class="docutils literal">.xhtml</tt>, <tt class="docutils literal">.xht</tt>, <tt class="docutils literal">.txt</tt>, <tt class="docutils literal">.json</tt>, and <tt class="docutils literal">.xml</tt>) to respond to a request whose URL path ends in <tt class="docutils literal">/</tt> (corresponding to the folder wherein <tt class="docutils literal">_index.*</tt> or <tt class="docutils literal">index.*</tt> file is located).
(This can be used to implement &quot;slash&quot; blog style URL's like <tt class="docutils literal">/blog/whatever/</tt> which maps to <tt class="docutils literal">/blog/whatever/index.html</tt>.)</blockquote>
<p><tt class="docutils literal"><span class="pre">--exclude-strip</span></tt></p>
<blockquote>
Disables using a file with the suffix <tt class="docutils literal">.html</tt>, <tt class="docutils literal">.htm</tt>, <tt class="docutils literal">.xhtml</tt>, <tt class="docutils literal">.xht</tt>, and <tt class="docutils literal">.txt</tt> to respond to a request whose URL does not exactly match an existing file.
(This can be used to implement &quot;suffix-less&quot; blog style URL's like <tt class="docutils literal">/blog/whatever</tt> which maps to <tt class="docutils literal">/blog/whatever.html</tt>.)</blockquote>
<p><tt class="docutils literal"><span class="pre">--exclude-cache</span></tt></p>
<blockquote>
Disables adding an <tt class="docutils literal"><span class="pre">Cache-Control:</span> public, immutable, <span class="pre">max-age=3600</span></tt> header that forces the browser (and other intermediary proxies) to cache the response for an hour (the <tt class="docutils literal">public</tt> and <tt class="docutils literal"><span class="pre">max-age=3600</span></tt> arguments), and furthermore not request it even on reloads (the <tt class="docutils literal">immutable</tt> argument).</blockquote>
<p><tt class="docutils literal"><span class="pre">--include-etag</span></tt></p>
<blockquote>
<p>Enables adding an <tt class="docutils literal">ETag</tt> response header that contains the SHA256 of the response body.</p>
<p>By not including the <tt class="docutils literal">ETag</tt> header (i.e. the default), and because identical headers are stored only one, if one has many files of the same type (that in turn without <tt class="docutils literal">ETag</tt> generates the same headers), this can lead to significant reduction in stored headers blocks, including reducing RAM usage.
(At this moment it does not support HTTP conditional requests, i.e. the <tt class="docutils literal"><span class="pre">If-None-Match</span></tt>, <tt class="docutils literal"><span class="pre">If-Modified-Since</span></tt> and their counterparts; however this <tt class="docutils literal">ETag</tt> header might be used in conjuction with <tt class="docutils literal">HEAD</tt> requests to see if the resource has changed.)</p>
</blockquote>
<p><tt class="docutils literal"><span class="pre">--exclude-slash-redirects</span></tt></p>
<blockquote>
Disables adding redirects to/from paths with/without <cite>/</cite>
(For example, by default, if <cite>/file</cite> exists, then there is also a <cite>/file/</cite> redirect towards <cite>/file</cite>; and vice-versa from <cite>/folder</cite> towards <cite>/folder/</cite>.)</blockquote>
<p><tt class="docutils literal"><span class="pre">--include-folder-listing</span></tt></p>
<blockquote>
Enables the creation of an internal list of folders.</blockquote>
<p><tt class="docutils literal"><span class="pre">--exclude-paths-index</span></tt></p>
<blockquote>
Disables the creation of an internal list of references that can be used in conjunction with the <tt class="docutils literal"><span class="pre">--index-all</span></tt> flag of the <tt class="docutils literal"><span class="pre">kawipiko-server</span></tt>.</blockquote>
<p><tt class="docutils literal"><span class="pre">--progress</span></tt></p>
<blockquote>
Enables periodic reporting of various metrics.</blockquote>
<p><tt class="docutils literal"><span class="pre">--debug</span></tt></p>
<blockquote>
Enables verbose logging.
It will log various information about the archived files (including compression statistics).</blockquote>
</div>
<div class="section" id="ignored-files">
<h1>Ignored files</h1>
<ul class="simple">
<li>any file with the following prefixes: <tt class="docutils literal">.</tt>, <tt class="docutils literal">#</tt>;</li>
<li>any file with the following suffixes: <tt class="docutils literal">~</tt>, <tt class="docutils literal">#</tt>, <tt class="docutils literal">.log</tt>, <tt class="docutils literal">.tmp</tt>, <tt class="docutils literal">.temp</tt>, <tt class="docutils literal">.lock</tt>;</li>
<li>any file that contains the following: <tt class="docutils literal">#</tt>;</li>
<li>any file that exactly matches the following: <tt class="docutils literal">Thumbs.db</tt>, <tt class="docutils literal">.DS_Store</tt>;</li>
<li>(at the moment these rules are not configurable through flags;)</li>
</ul>
</div>
<div class="section" id="wildcard-files">
<h1>Wildcard files</h1>
<p>By placing a file whose name matches <tt class="docutils literal">_wildcard.*</tt> (i.e. with the prefix <tt class="docutils literal">_wildcard.</tt> and any other suffix), it will be used to respond to any request whose URL fails to find a &quot;better&quot; match.</p>
<p>These wildcard files respect the folder hierarchy, in that wildcard files in (direct or transitive) subfolders override the wildcard file in their parents (direct or transitive).</p>
<p>In addition to <tt class="docutils literal">_wildcard.*</tt>, there is also support for <tt class="docutils literal">_200.html</tt> (or just <tt class="docutils literal">200.html</tt>), plus <tt class="docutils literal">_404.html</tt> (or just <tt class="docutils literal">404.html</tt>).</p>
</div>
<div class="section" id="redirect-files">
<h1>Redirect files</h1>
<p>By placing a file whose name is <tt class="docutils literal">_redirects</tt> (or <tt class="docutils literal">_redirects.txt</tt>), it instructs the archiver to create redirect responses.</p>
<p>The syntax is quite simple:</p>
<pre class="literal-block">
# This is a comment.
# NOTE: Absolute paths are allowed only at the top of the sources folder.
/some-path https://example.com/ 301
# NOTE: Relative paths are always, and are reinterpreted as relative to the containing folder.
./some-path https://example.com/ 302
# NOTE: Redirects only for a specific domain. (The protocol is irelevant.)
# (Allowed only at the top of the sources folder.)
://example.com/some-path https://example.com/ 303
http://example.com/some-path https://example.com/ 307
https://example.com/some-path https://example.com/ 308
</pre>
</div>
<div class="section" id="symlinks-hardlinks-loops-and-duplicated-files">
<h1>Symlinks, hardlinks, loops, and duplicated files</h1>
<p>You freely use symlinks (including pointing outside of the content root) and they will be crawled during archival respecting the &quot;logical&quot; hierarchy they introduce.
(Any loop that you introduce into the hierarchy will be ignored and a warning will be issued.)</p>
<p>You can safely symlink or hardlink the same file (or folder) in multiple places (within the content hierarchy), and its data will be stored only once.
(The same applies to duplicated files that have exactly the same data.)</p>
</div>
</div>
</body>
</html>

View file

@ -44,6 +44,8 @@ kawipiko -- blazingly fast static HTTP server
--sources-md5 (dump an ``md5sum`` of the sources) --sources-md5 (dump an ``md5sum`` of the sources)
--sources-cpio (dump a ``cpio.gz`` of the sources) --sources-cpio (dump a ``cpio.gz`` of the sources)
--sbom --sbom-text --sbom-json

View file

@ -34,6 +34,8 @@ NAME
--sources-md5 (dump an ``md5sum`` of the sources) --sources-md5 (dump an ``md5sum`` of the sources)
--sources-cpio (dump a ``cpio.gz`` of the sources) --sources-cpio (dump a ``cpio.gz`` of the sources)
--sbom --sbom-text --sbom-json
---- ----

View file

@ -98,6 +98,8 @@ kawipiko -- blazingly fast static HTTP server \- kawipiko-server
\-\-sources\-md5 (dump an \(gamd5sum\(ga of the sources) \-\-sources\-md5 (dump an \(gamd5sum\(ga of the sources)
\-\-sources\-cpio (dump a \(gacpio.gz\(ga of the sources) \-\-sources\-cpio (dump a \(gacpio.gz\(ga of the sources)
\-\-sbom \-\-sbom\-text \-\-sbom\-json
.ft P .ft P
.fi .fi
.UNINDENT .UNINDENT
@ -228,13 +230,22 @@ Disables the virtual\-hosts feature by ignoring the \fIHost\fP header.
Disables serving a few special pages internal to the server like: Disables serving a few special pages internal to the server like:
.INDENT 0.0 .INDENT 0.0
.INDENT 3.5 .INDENT 3.5
/__/about .sp
/__/version .nf
.ft C
/__/heartbeat /__/heartbeat
/__/sources.md5 /__/kawipiko/about
/__/sources.cpio /__/kawipiko/version
/__/banners/errors/403 /__/kawipiko/manual.txt
/__/banners/errors/... /__/kawipiko/manual.html
/__/kawipiko/sbom.txt
/__/kawipiko/sbom.json
/__/kawipiko/sources.md5
/__/kawipiko/sources.cpio
/__/kawipiko/banners/errors/403
/__/kawipiko/banners/errors/...
.ft P
.fi
.UNINDENT .UNINDENT
.UNINDENT .UNINDENT
.UNINDENT .UNINDENT

View file

@ -0,0 +1,555 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<title>kawipiko -- blazingly fast static HTTP server</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 7952 2016-07-26 18:15:59Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
.subscript {
vertical-align: sub;
font-size: smaller }
.superscript {
vertical-align: super;
font-size: smaller }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
overflow: hidden;
}
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title, .code .error {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin: 0 0 0.5em 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr.docutils {
width: 75% }
img.align-left, .figure.align-left, object.align-left, table.align-left {
clear: left ;
float: left ;
margin-right: 1em }
img.align-right, .figure.align-right, object.align-right, table.align-right {
clear: right ;
float: right ;
margin-left: 1em }
img.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
table.align-center {
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left }
.align-center {
clear: both ;
text-align: center }
.align-right {
text-align: right }
/* reset inner alignment in figures */
div.align-right {
text-align: inherit }
/* div.align-center * { */
/* text-align: left } */
.align-top {
vertical-align: top }
.align-middle {
vertical-align: middle }
.align-bottom {
vertical-align: bottom }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font: inherit }
pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
pre.code .ln { color: grey; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre {
white-space: pre }
span.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.footnote {
border-left: solid 1px black;
margin-left: 1px }
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
border: 0px;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.docutils.booktabs * {
border: 0px;
}
table.docutils.booktabs th {
border-bottom: thin solid;
text-align: left;
}
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
ul.auto-toc {
list-style-type: none }
</style>
</head>
<body>
<div class="document" id="kawipiko-blazingly-fast-static-http-server">
<h1 class="title">kawipiko -- blazingly fast static HTTP server</h1>
<h2 class="subtitle" id="kawipiko-server"><tt class="docutils literal"><span class="pre">kawipiko-server</span></tt></h2>
<pre class="literal-block">
&gt;&gt; kawipiko-server --help
&gt;&gt; kawipiko-server --man
</pre>
<pre class="literal-block">
--archive &lt;path&gt;
--archive-inmem (memory-loaded archive file)
--archive-mmap (memory-mapped archive file)
--archive-preload (preload archive in OS cache)
--bind &lt;ip&gt;:&lt;port&gt; (HTTP, only HTTP/1.1, FastHTTP)
--bind-2 &lt;ip&gt;:&lt;port&gt; (HTTP, only HTTP/1.1, Go net/http)
--bind-tls &lt;ip&gt;:&lt;port&gt; (HTTPS, only HTTP/1.1, FastHTTP)
--bind-tls-2 &lt;ip&gt;:&lt;port&gt; (HTTPS, with HTTP/2, Go net/http)
--bind-quic &lt;ip&gt;:&lt;port&gt; (HTTPS, with HTTP/3)
--http1-disable
--http2-disable
--http3-alt-svc &lt;ip&gt;:&lt;port&gt;
--tls-bundle &lt;path&gt; (TLS certificate bundle)
--tls-public &lt;path&gt; (TLS certificate public)
--tls-private &lt;path&gt; (TLS certificate private)
--tls-self-rsa (use self-signed RSA)
--tls-self-ed25519 (use self-signed Ed25519)
--processes &lt;count&gt; (of slave processes)
--threads &lt;count&gt; (of threads per process)
--index-all
--index-paths
--index-data-meta
--index-data-content
--hosts-disable (ignore `Host` header)
--special-pages-disable
--security-headers-disable
--security-headers-tls
--limit-memory &lt;MiB&gt;
--timeout-disable
--report --quiet --debug
--dummy
--dummy-empty
--dummy-delay &lt;duration&gt;
--profile-cpu &lt;path&gt;
--profile-mem &lt;path&gt;
--version
--help (show this short help)
--man (show the full manual)
--sources-md5 (dump an `md5sum` of the sources)
--sources-cpio (dump a `cpio.gz` of the sources)
--sbom --sbom-text --sbom-json
</pre>
<hr class="docutils" />
<div class="section" id="flags">
<h1>Flags</h1>
<p><tt class="docutils literal"><span class="pre">--bind</span> &lt;ip:port&gt;</tt>, <tt class="docutils literal"><span class="pre">--bind-tls</span> &lt;ip:port&gt;</tt>, <tt class="docutils literal"><span class="pre">--bind-2</span> &lt;ip:port&gt;</tt>, <tt class="docutils literal"><span class="pre">--bind-tls-2</span> &lt;ip:port&gt;</tt>, and <tt class="docutils literal"><span class="pre">--bind-quic</span> &lt;ip:port&gt;</tt></p>
<blockquote>
<p>The IP and port to listen for requests with:</p>
<ul class="simple">
<li>(insecure) HTTP/1.1 for <tt class="docutils literal"><span class="pre">--bind</span></tt>, leveraging <tt class="docutils literal">fasthttp</tt> library;</li>
<li>(secure) HTTP/1.1 over TLS for <tt class="docutils literal"><span class="pre">--bind-tls</span></tt>, leveraging <tt class="docutils literal">fasthttp</tt> library;</li>
<li>(insecure) HTTP/1.1 for <tt class="docutils literal"><span class="pre">--bind-2</span></tt>, leveraging Go's <tt class="docutils literal">net/http</tt> library; (not as performant as the <tt class="docutils literal">fasthttp</tt> powered endpoint;)</li>
<li>(secure) H2 or HTTP/1.1 over TLS for <tt class="docutils literal"><span class="pre">--bind-tls-2</span></tt>, leveraging Go's <tt class="docutils literal">net/http</tt>; (not as performant as the <tt class="docutils literal">fasthttp</tt> powered endpoint;)</li>
<li>(secure) H3 over QUIC for <tt class="docutils literal"><span class="pre">--bind-quic</span></tt>, leveraging <tt class="docutils literal"><span class="pre">github.com/lucas-clemente/quic-go</span></tt> library; (given that H3 is still a new protocol, this must be used with caution; also one should use the <tt class="docutils literal"><span class="pre">--http3-alt-svc</span> &lt;ip:port&gt;</tt>;)</li>
<li>if one uses just <tt class="docutils literal"><span class="pre">--bind-tls</span></tt> (without <tt class="docutils literal"><span class="pre">--bind-tls-2</span></tt>, and without <tt class="docutils literal"><span class="pre">--http2-disabled</span></tt>), then the TLS endpoint is split between <tt class="docutils literal">fasthttp</tt> for HTTP/1.1 and Go's <tt class="docutils literal">net/http</tt> for H2;</li>
</ul>
</blockquote>
<p><tt class="docutils literal"><span class="pre">--tls-bundle</span> &lt;path&gt;</tt>, <tt class="docutils literal"><span class="pre">--tls-public</span> &lt;path&gt;</tt>, and <tt class="docutils literal"><span class="pre">--tls-private</span> &lt;path&gt;</tt> (optional)</p>
<blockquote>
<p>If TLS is enabled, these options allows one to specify the certificate to use, either as a single file (a bundle) or separate files (the actual public certificate and the private key).</p>
<p>If one doesn't specify any of these options, an embedded self-signed certificate will be used. In such case, one can choose between RSA (the <tt class="docutils literal"><span class="pre">--tls-self-rsa</span></tt> flag) or Ed25519 (the <tt class="docutils literal"><span class="pre">--tls-self-ed25519</span></tt> flag);</p>
</blockquote>
<p><tt class="docutils literal"><span class="pre">--http1-disable</span></tt>, <tt class="docutils literal"><span class="pre">--http2-disable</span></tt></p>
<blockquote>
Disables that particular protocol.
(It can be used only with <tt class="docutils literal"><span class="pre">--bind-tls-2</span></tt>, given that <tt class="docutils literal">fasthttp</tt> only supports HTTP/1.)</blockquote>
<p><tt class="docutils literal"><span class="pre">--processes</span> &lt;count&gt;</tt> and <tt class="docutils literal"><span class="pre">--threads</span> &lt;count&gt;</tt></p>
<blockquote>
<p>The number of processes and threads per each process to start. (Given Go's concurrency model, the threads count is somewhat a soft limit, hinting to the runtime the desired parallelism level.)</p>
<p>It is highly recommended to use one process and as many threads as there are cores.</p>
<p>Depending on the use-case, one can use multiple processes each with a single thread; this would reduce goroutine contention if it causes problems.
(However note that if using <tt class="docutils literal"><span class="pre">--archive-inmem</span></tt>, then each process will allocate its own copy of the database in RAM; in such cases it is highly recommended to use <tt class="docutils literal"><span class="pre">--archive-mmap</span></tt>.)</p>
</blockquote>
<p><tt class="docutils literal"><span class="pre">--archive</span> &lt;path&gt;</tt></p>
<blockquote>
The path of the CDB file that contains the archived static content.
(It can be created with the <tt class="docutils literal"><span class="pre">kawipiko-archiver</span></tt> tool.)</blockquote>
<p><tt class="docutils literal"><span class="pre">--archive-inmem</span></tt></p>
<blockquote>
Reads the CDB file in RAM, and thus all requests are served from RAM without touching the file-system.
(The memory impact is equal to the size of the CDB archive. This can be used if enough RAM is available to avoid swapping.)</blockquote>
<p><tt class="docutils literal"><span class="pre">--archive-mmap</span></tt></p>
<blockquote>
(<strong>recommended</strong>) The CDB file is <a class="reference external" href="#mmap">memory mapped</a>, thus reading its data uses the kernel's file-system cache, as opposed to issuing <tt class="docutils literal">read</tt> syscalls.</blockquote>
<p><tt class="docutils literal"><span class="pre">--archive-preload</span></tt></p>
<blockquote>
Before starting to serve requests, read the CDB file so that its data is buffered in the kernel's file-system cache. (This option can be used with or without <tt class="docutils literal"><span class="pre">--archive-mmap</span></tt>.)</blockquote>
<p><tt class="docutils literal"><span class="pre">--index-all</span></tt>, <tt class="docutils literal"><span class="pre">--index-paths</span></tt>, <tt class="docutils literal"><span class="pre">--index-data-meta</span></tt>, and <tt class="docutils literal"><span class="pre">--index-data-content</span></tt></p>
<blockquote>
<p>In order to serve a request <tt class="docutils literal">kawipiko</tt> does the following:</p>
<ul class="simple">
<li>given the request's path, it is used to locate the corresponding resource's metadata (i.e. response headers) and data (i.e. response body) references;
by using <tt class="docutils literal"><span class="pre">--index-paths</span></tt> a RAM-based lookup table is created to eliminate a CDB read operation for this purpose; (the memory impact is proportional to the size of all resource paths combined; given that the number of resources is acceptable, say up to a couple hundred thousand, one could safely use this option;)</li>
<li>based on the resource's metadata reference, the actual metadata (i.e. the response headers) is located;
by using <tt class="docutils literal"><span class="pre">--index-data-meta</span></tt> a RAM-based lookup table is created to eliminate a CDB read operation for this purpose; (the memory impact is proportional to the size of all resource metadata blocks combined; given that the metadata blocks are deduplicated, one could safely use this option; if one also uses <tt class="docutils literal"><span class="pre">--archive-mmap</span></tt> or <tt class="docutils literal"><span class="pre">--archive-inmem</span></tt>, then the memory impact is only proportional to the number of resource metadata blocks;)</li>
<li>based on the resource's data reference, the actual data (i.e. the response body) is located;
by using <tt class="docutils literal"><span class="pre">--index-data-content</span></tt> a RAM-based lookup table is created to eliminate a CDB operation operation for this purpose; (the memory impact is proportional to the size of all resource data blocks combined; one can use this option to obtain the best performance; if one also uses <tt class="docutils literal"><span class="pre">--archive-mmap</span></tt> or <tt class="docutils literal"><span class="pre">--archive-inmem</span></tt>, then the memory impact is only proportional to the number of resource data blocks;)</li>
<li><tt class="docutils literal"><span class="pre">--index-all</span></tt> enables all the options above;</li>
<li>(depending on the use-case) it is recommended to use <tt class="docutils literal"><span class="pre">--index-paths</span></tt>; if <tt class="docutils literal"><span class="pre">--exclude-etag</span></tt> was used during archival, one can also use <tt class="docutils literal"><span class="pre">--index-data-meta</span></tt>;</li>
<li>it is recommended to use either <tt class="docutils literal"><span class="pre">--archive-mmap</span></tt> or <tt class="docutils literal"><span class="pre">--archive-inmem</span></tt>, else (especially if data is indexed) the resulting effect is that of loading everything in RAM;</li>
</ul>
</blockquote>
<p><tt class="docutils literal"><span class="pre">--hosts-disable</span></tt></p>
<blockquote>
Disables the virtual-hosts feature by ignoring the <cite>Host</cite> header.</blockquote>
<p><tt class="docutils literal"><span class="pre">--special-pages-disable</span></tt></p>
<blockquote>
<p>Disables serving a few special pages internal to the server like:</p>
<pre class="literal-block">
/__/heartbeat
/__/kawipiko/about
/__/kawipiko/version
/__/kawipiko/manual.txt
/__/kawipiko/manual.html
/__/kawipiko/sbom.txt
/__/kawipiko/sbom.json
/__/kawipiko/sources.md5
/__/kawipiko/sources.cpio
/__/kawipiko/banners/errors/403
/__/kawipiko/banners/errors/...
</pre>
</blockquote>
<p><tt class="docutils literal"><span class="pre">--security-headers-disable</span></tt></p>
<blockquote>
<p>Disables adding a few security related headers:</p>
<pre class="literal-block">
Referrer-Policy: strict-origin-when-cross-origin
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
X-Frame-Options: sameorigin
</pre>
</blockquote>
<p><tt class="docutils literal"><span class="pre">--security-headers-tls</span></tt></p>
<blockquote>
<p>Enables adding the following TLS related headers to the response:</p>
<pre class="literal-block">
Strict-Transport-Security: max-age=31536000
Content-Security-Policy: upgrade-insecure-requests
</pre>
<p>These instruct the browser to always use HTTPS for the served domain.
(Useful even without HTTPS, when used behind a TLS terminator, load-balancer or proxy that do support HTTPS.)</p>
</blockquote>
<p><tt class="docutils literal"><span class="pre">--report</span></tt></p>
<blockquote>
Enables periodic reporting of various metrics.
Also enables reporting a selection of metrics if certain thresholds are matched (which most likely is a sign of high-load).</blockquote>
<p><tt class="docutils literal"><span class="pre">--quiet</span></tt></p>
<blockquote>
Disables most logging messages.</blockquote>
<p><tt class="docutils literal"><span class="pre">--debug</span></tt></p>
<blockquote>
Enables all logging messages.</blockquote>
<p><tt class="docutils literal"><span class="pre">--dummy</span></tt>, <tt class="docutils literal"><span class="pre">--dummy-empty</span></tt></p>
<blockquote>
<p>It starts the server in a &quot;dummy&quot; mode, ignoring all archive related arguments and always responding with <tt class="docutils literal">hello <span class="pre">world!\n</span></tt> (unless <tt class="docutils literal"><span class="pre">--dummy-empty</span></tt> was used) and without additional headers except the HTTP status line and <tt class="docutils literal"><span class="pre">Content-Length</span></tt>.</p>
<p>This argument can be used to benchmark the raw performance of the underlying <tt class="docutils literal">fasthttp</tt>, Go's <tt class="docutils literal">net/http</tt>, or QUIC performance; this is the upper limit of the achievable performance given the underlying technologies.
(From my own benchmarks <tt class="docutils literal">kawipiko</tt>'s adds only about ~15% overhead when actually serving the <tt class="docutils literal"><span class="pre">hello-world.cdb</span></tt> archive.)</p>
</blockquote>
<p><tt class="docutils literal"><span class="pre">--dummy-delay</span> &lt;duration&gt;</tt></p>
<blockquote>
<p>Enables delaying each response with a certain amount (for example <tt class="docutils literal">1s</tt>, <tt class="docutils literal">1ms</tt>, etc.)</p>
<p>It can be used to simulate the real-world network latencies, perhaps to see how a site with many resources loads in various conditions.
(For example, see <a class="reference external" href="https://notes.volution.ro/v1/2019/08/notes/e8700e9a/">an experiment</a> I made with an image made out of 1425 tiles.)</p>
</blockquote>
<p><tt class="docutils literal"><span class="pre">--profile-cpu</span> &lt;path&gt;</tt>, and <tt class="docutils literal"><span class="pre">--profile-mem</span> &lt;path&gt;</tt></p>
<blockquote>
Enables CPU and memory profiling using Go's profiling infrastructure.</blockquote>
</div>
</div>
</body>
</html>

View file

@ -70,6 +70,8 @@ kawipiko -- blazingly fast static HTTP server
--sources-md5 (dump an `md5sum` of the sources) --sources-md5 (dump an `md5sum` of the sources)
--sources-cpio (dump a `cpio.gz` of the sources) --sources-cpio (dump a `cpio.gz` of the sources)
--sbom --sbom-text --sbom-json
@ -157,15 +159,19 @@ Flags
``--special-pages-disable`` ``--special-pages-disable``
Disables serving a few special pages internal to the server like: Disables serving a few special pages internal to the server like: ::
/__/about
/__/version
/__/heartbeat /__/heartbeat
/__/sources.md5 /__/kawipiko/about
/__/sources.cpio /__/kawipiko/version
/__/banners/errors/403 /__/kawipiko/manual.txt
/__/banners/errors/... /__/kawipiko/manual.html
/__/kawipiko/sbom.txt
/__/kawipiko/sbom.json
/__/kawipiko/sources.md5
/__/kawipiko/sources.cpio
/__/kawipiko/banners/errors/403
/__/kawipiko/banners/errors/...
``--security-headers-disable`` ``--security-headers-disable``

View file

@ -61,6 +61,8 @@ NAME
--sources-md5 (dump an `md5sum` of the sources) --sources-md5 (dump an `md5sum` of the sources)
--sources-cpio (dump a `cpio.gz` of the sources) --sources-cpio (dump a `cpio.gz` of the sources)
--sbom --sbom-text --sbom-json
---- ----
@ -187,8 +189,18 @@ FLAGS
--special-pages-disable --special-pages-disable
Disables serving a few special pages internal to the server like: Disables serving a few special pages internal to the server like:
/__/about /__/version /__/heartbeat /__/sources.md5
/__/sources.cpio /__/banners/errors/403 /__/banners/errors/... /__/heartbeat
/__/kawipiko/about
/__/kawipiko/version
/__/kawipiko/manual.txt
/__/kawipiko/manual.html
/__/kawipiko/sbom.txt
/__/kawipiko/sbom.json
/__/kawipiko/sources.md5
/__/kawipiko/sources.cpio
/__/kawipiko/banners/errors/403
/__/kawipiko/banners/errors/...
--security-headers-disable --security-headers-disable
Disables adding a few security related headers: Disables adding a few security related headers:

View file

@ -38,7 +38,17 @@
printf -- '[ii] rendering `%s`...\n' "${_manual}" >&2 printf -- '[ii] rendering `%s`...\n' "${_manual}" >&2
rst2man --strict \ rst2html --strict --no-generator --embed-stylesheet \
< "./documentation/manuals/${_manual}.rst" \
>| "./documentation/manuals/${_manual}.html.tmp" \
#
mv -T -- \
"./documentation/manuals/${_manual}.html.tmp" \
"./documentation/manuals/${_manual}.html" \
#
rst2man --strict --no-generator \
< "./documentation/manuals/${_manual}.rst" \ < "./documentation/manuals/${_manual}.rst" \
| sed -r \ | sed -r \
-e 's#^\.TH .*#.TH "KAWIPIKO\-'"${_manual^^}"'" "1" "'"${_date}"'" "volution.ro" "kawipiko"#' \ -e 's#^\.TH .*#.TH "KAWIPIKO\-'"${_manual^^}"'" "1" "'"${_date}"'" "volution.ro" "kawipiko"#' \

View file

@ -57,9 +57,17 @@
cp -T -- ./documentation/manuals/server.txt ./sources/cmd/server/manual.txt cp -T -- ./documentation/manuals/server.txt ./sources/cmd/server/manual.txt
fi fi
if ! cmp -s -- ./documentation/manuals/server.html ./sources/cmd/server/manual.html ; then
cp -T -- ./documentation/manuals/server.html ./sources/cmd/server/manual.html
fi
if ! cmp -s -- ./documentation/manuals/archiver.txt ./sources/cmd/archiver/manual.txt ; then if ! cmp -s -- ./documentation/manuals/archiver.txt ./sources/cmd/archiver/manual.txt ; then
cp -T -- ./documentation/manuals/archiver.txt ./sources/cmd/archiver/manual.txt cp -T -- ./documentation/manuals/archiver.txt ./sources/cmd/archiver/manual.txt
fi fi
if ! cmp -s -- ./documentation/manuals/server.html ./sources/cmd/server/manual.html ; then
cp -T -- ./documentation/manuals/server.html ./sources/cmd/server/manual.html
fi
!! !!

View file

@ -1269,6 +1269,14 @@ func Main () () {
version.Main ("kawipiko-archiver", "sources.cpio") version.Main ("kawipiko-archiver", "sources.cpio")
return return
case "--sbom-text", "--sbom-txt", "--sbom" :
version.Main ("kawipiko-archiver", "sbom.txt")
return
case "--sbom-json" :
version.Main ("kawipiko-archiver", "sbom.json")
return
case "--help", "-h" : case "--help", "-h" :
if _, _error := os.Stdout.WriteString (usageText); _error == nil { if _, _error := os.Stdout.WriteString (usageText); _error == nil {
return return

View file

View file

@ -34,6 +34,8 @@ NAME
--sources-md5 (dump an ``md5sum`` of the sources) --sources-md5 (dump an ``md5sum`` of the sources)
--sources-cpio (dump a ``cpio.gz`` of the sources) --sources-cpio (dump a ``cpio.gz`` of the sources)
--sbom --sbom-text --sbom-json
---- ----

View file

@ -22,8 +22,10 @@
--progress --debug --progress --debug
--version
--help (show this short help) --help (show this short help)
--man (show the full manual) --man (show the full manual)
--sources-md5 --sources-cpio --sbom --sbom-json
** supported archive version: @{SCHEMA} ** supported archive version: @{SCHEMA}

View file

@ -0,0 +1,555 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<title>kawipiko -- blazingly fast static HTTP server</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 7952 2016-07-26 18:15:59Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
.subscript {
vertical-align: sub;
font-size: smaller }
.superscript {
vertical-align: super;
font-size: smaller }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
overflow: hidden;
}
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title, .code .error {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin: 0 0 0.5em 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr.docutils {
width: 75% }
img.align-left, .figure.align-left, object.align-left, table.align-left {
clear: left ;
float: left ;
margin-right: 1em }
img.align-right, .figure.align-right, object.align-right, table.align-right {
clear: right ;
float: right ;
margin-left: 1em }
img.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
table.align-center {
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left }
.align-center {
clear: both ;
text-align: center }
.align-right {
text-align: right }
/* reset inner alignment in figures */
div.align-right {
text-align: inherit }
/* div.align-center * { */
/* text-align: left } */
.align-top {
vertical-align: top }
.align-middle {
vertical-align: middle }
.align-bottom {
vertical-align: bottom }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font: inherit }
pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
pre.code .ln { color: grey; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre {
white-space: pre }
span.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.footnote {
border-left: solid 1px black;
margin-left: 1px }
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
border: 0px;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.docutils.booktabs * {
border: 0px;
}
table.docutils.booktabs th {
border-bottom: thin solid;
text-align: left;
}
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
ul.auto-toc {
list-style-type: none }
</style>
</head>
<body>
<div class="document" id="kawipiko-blazingly-fast-static-http-server">
<h1 class="title">kawipiko -- blazingly fast static HTTP server</h1>
<h2 class="subtitle" id="kawipiko-server"><tt class="docutils literal"><span class="pre">kawipiko-server</span></tt></h2>
<pre class="literal-block">
&gt;&gt; kawipiko-server --help
&gt;&gt; kawipiko-server --man
</pre>
<pre class="literal-block">
--archive &lt;path&gt;
--archive-inmem (memory-loaded archive file)
--archive-mmap (memory-mapped archive file)
--archive-preload (preload archive in OS cache)
--bind &lt;ip&gt;:&lt;port&gt; (HTTP, only HTTP/1.1, FastHTTP)
--bind-2 &lt;ip&gt;:&lt;port&gt; (HTTP, only HTTP/1.1, Go net/http)
--bind-tls &lt;ip&gt;:&lt;port&gt; (HTTPS, only HTTP/1.1, FastHTTP)
--bind-tls-2 &lt;ip&gt;:&lt;port&gt; (HTTPS, with HTTP/2, Go net/http)
--bind-quic &lt;ip&gt;:&lt;port&gt; (HTTPS, with HTTP/3)
--http1-disable
--http2-disable
--http3-alt-svc &lt;ip&gt;:&lt;port&gt;
--tls-bundle &lt;path&gt; (TLS certificate bundle)
--tls-public &lt;path&gt; (TLS certificate public)
--tls-private &lt;path&gt; (TLS certificate private)
--tls-self-rsa (use self-signed RSA)
--tls-self-ed25519 (use self-signed Ed25519)
--processes &lt;count&gt; (of slave processes)
--threads &lt;count&gt; (of threads per process)
--index-all
--index-paths
--index-data-meta
--index-data-content
--hosts-disable (ignore `Host` header)
--special-pages-disable
--security-headers-disable
--security-headers-tls
--limit-memory &lt;MiB&gt;
--timeout-disable
--report --quiet --debug
--dummy
--dummy-empty
--dummy-delay &lt;duration&gt;
--profile-cpu &lt;path&gt;
--profile-mem &lt;path&gt;
--version
--help (show this short help)
--man (show the full manual)
--sources-md5 (dump an `md5sum` of the sources)
--sources-cpio (dump a `cpio.gz` of the sources)
--sbom --sbom-text --sbom-json
</pre>
<hr class="docutils" />
<div class="section" id="flags">
<h1>Flags</h1>
<p><tt class="docutils literal"><span class="pre">--bind</span> &lt;ip:port&gt;</tt>, <tt class="docutils literal"><span class="pre">--bind-tls</span> &lt;ip:port&gt;</tt>, <tt class="docutils literal"><span class="pre">--bind-2</span> &lt;ip:port&gt;</tt>, <tt class="docutils literal"><span class="pre">--bind-tls-2</span> &lt;ip:port&gt;</tt>, and <tt class="docutils literal"><span class="pre">--bind-quic</span> &lt;ip:port&gt;</tt></p>
<blockquote>
<p>The IP and port to listen for requests with:</p>
<ul class="simple">
<li>(insecure) HTTP/1.1 for <tt class="docutils literal"><span class="pre">--bind</span></tt>, leveraging <tt class="docutils literal">fasthttp</tt> library;</li>
<li>(secure) HTTP/1.1 over TLS for <tt class="docutils literal"><span class="pre">--bind-tls</span></tt>, leveraging <tt class="docutils literal">fasthttp</tt> library;</li>
<li>(insecure) HTTP/1.1 for <tt class="docutils literal"><span class="pre">--bind-2</span></tt>, leveraging Go's <tt class="docutils literal">net/http</tt> library; (not as performant as the <tt class="docutils literal">fasthttp</tt> powered endpoint;)</li>
<li>(secure) H2 or HTTP/1.1 over TLS for <tt class="docutils literal"><span class="pre">--bind-tls-2</span></tt>, leveraging Go's <tt class="docutils literal">net/http</tt>; (not as performant as the <tt class="docutils literal">fasthttp</tt> powered endpoint;)</li>
<li>(secure) H3 over QUIC for <tt class="docutils literal"><span class="pre">--bind-quic</span></tt>, leveraging <tt class="docutils literal"><span class="pre">github.com/lucas-clemente/quic-go</span></tt> library; (given that H3 is still a new protocol, this must be used with caution; also one should use the <tt class="docutils literal"><span class="pre">--http3-alt-svc</span> &lt;ip:port&gt;</tt>;)</li>
<li>if one uses just <tt class="docutils literal"><span class="pre">--bind-tls</span></tt> (without <tt class="docutils literal"><span class="pre">--bind-tls-2</span></tt>, and without <tt class="docutils literal"><span class="pre">--http2-disabled</span></tt>), then the TLS endpoint is split between <tt class="docutils literal">fasthttp</tt> for HTTP/1.1 and Go's <tt class="docutils literal">net/http</tt> for H2;</li>
</ul>
</blockquote>
<p><tt class="docutils literal"><span class="pre">--tls-bundle</span> &lt;path&gt;</tt>, <tt class="docutils literal"><span class="pre">--tls-public</span> &lt;path&gt;</tt>, and <tt class="docutils literal"><span class="pre">--tls-private</span> &lt;path&gt;</tt> (optional)</p>
<blockquote>
<p>If TLS is enabled, these options allows one to specify the certificate to use, either as a single file (a bundle) or separate files (the actual public certificate and the private key).</p>
<p>If one doesn't specify any of these options, an embedded self-signed certificate will be used. In such case, one can choose between RSA (the <tt class="docutils literal"><span class="pre">--tls-self-rsa</span></tt> flag) or Ed25519 (the <tt class="docutils literal"><span class="pre">--tls-self-ed25519</span></tt> flag);</p>
</blockquote>
<p><tt class="docutils literal"><span class="pre">--http1-disable</span></tt>, <tt class="docutils literal"><span class="pre">--http2-disable</span></tt></p>
<blockquote>
Disables that particular protocol.
(It can be used only with <tt class="docutils literal"><span class="pre">--bind-tls-2</span></tt>, given that <tt class="docutils literal">fasthttp</tt> only supports HTTP/1.)</blockquote>
<p><tt class="docutils literal"><span class="pre">--processes</span> &lt;count&gt;</tt> and <tt class="docutils literal"><span class="pre">--threads</span> &lt;count&gt;</tt></p>
<blockquote>
<p>The number of processes and threads per each process to start. (Given Go's concurrency model, the threads count is somewhat a soft limit, hinting to the runtime the desired parallelism level.)</p>
<p>It is highly recommended to use one process and as many threads as there are cores.</p>
<p>Depending on the use-case, one can use multiple processes each with a single thread; this would reduce goroutine contention if it causes problems.
(However note that if using <tt class="docutils literal"><span class="pre">--archive-inmem</span></tt>, then each process will allocate its own copy of the database in RAM; in such cases it is highly recommended to use <tt class="docutils literal"><span class="pre">--archive-mmap</span></tt>.)</p>
</blockquote>
<p><tt class="docutils literal"><span class="pre">--archive</span> &lt;path&gt;</tt></p>
<blockquote>
The path of the CDB file that contains the archived static content.
(It can be created with the <tt class="docutils literal"><span class="pre">kawipiko-archiver</span></tt> tool.)</blockquote>
<p><tt class="docutils literal"><span class="pre">--archive-inmem</span></tt></p>
<blockquote>
Reads the CDB file in RAM, and thus all requests are served from RAM without touching the file-system.
(The memory impact is equal to the size of the CDB archive. This can be used if enough RAM is available to avoid swapping.)</blockquote>
<p><tt class="docutils literal"><span class="pre">--archive-mmap</span></tt></p>
<blockquote>
(<strong>recommended</strong>) The CDB file is <a class="reference external" href="#mmap">memory mapped</a>, thus reading its data uses the kernel's file-system cache, as opposed to issuing <tt class="docutils literal">read</tt> syscalls.</blockquote>
<p><tt class="docutils literal"><span class="pre">--archive-preload</span></tt></p>
<blockquote>
Before starting to serve requests, read the CDB file so that its data is buffered in the kernel's file-system cache. (This option can be used with or without <tt class="docutils literal"><span class="pre">--archive-mmap</span></tt>.)</blockquote>
<p><tt class="docutils literal"><span class="pre">--index-all</span></tt>, <tt class="docutils literal"><span class="pre">--index-paths</span></tt>, <tt class="docutils literal"><span class="pre">--index-data-meta</span></tt>, and <tt class="docutils literal"><span class="pre">--index-data-content</span></tt></p>
<blockquote>
<p>In order to serve a request <tt class="docutils literal">kawipiko</tt> does the following:</p>
<ul class="simple">
<li>given the request's path, it is used to locate the corresponding resource's metadata (i.e. response headers) and data (i.e. response body) references;
by using <tt class="docutils literal"><span class="pre">--index-paths</span></tt> a RAM-based lookup table is created to eliminate a CDB read operation for this purpose; (the memory impact is proportional to the size of all resource paths combined; given that the number of resources is acceptable, say up to a couple hundred thousand, one could safely use this option;)</li>
<li>based on the resource's metadata reference, the actual metadata (i.e. the response headers) is located;
by using <tt class="docutils literal"><span class="pre">--index-data-meta</span></tt> a RAM-based lookup table is created to eliminate a CDB read operation for this purpose; (the memory impact is proportional to the size of all resource metadata blocks combined; given that the metadata blocks are deduplicated, one could safely use this option; if one also uses <tt class="docutils literal"><span class="pre">--archive-mmap</span></tt> or <tt class="docutils literal"><span class="pre">--archive-inmem</span></tt>, then the memory impact is only proportional to the number of resource metadata blocks;)</li>
<li>based on the resource's data reference, the actual data (i.e. the response body) is located;
by using <tt class="docutils literal"><span class="pre">--index-data-content</span></tt> a RAM-based lookup table is created to eliminate a CDB operation operation for this purpose; (the memory impact is proportional to the size of all resource data blocks combined; one can use this option to obtain the best performance; if one also uses <tt class="docutils literal"><span class="pre">--archive-mmap</span></tt> or <tt class="docutils literal"><span class="pre">--archive-inmem</span></tt>, then the memory impact is only proportional to the number of resource data blocks;)</li>
<li><tt class="docutils literal"><span class="pre">--index-all</span></tt> enables all the options above;</li>
<li>(depending on the use-case) it is recommended to use <tt class="docutils literal"><span class="pre">--index-paths</span></tt>; if <tt class="docutils literal"><span class="pre">--exclude-etag</span></tt> was used during archival, one can also use <tt class="docutils literal"><span class="pre">--index-data-meta</span></tt>;</li>
<li>it is recommended to use either <tt class="docutils literal"><span class="pre">--archive-mmap</span></tt> or <tt class="docutils literal"><span class="pre">--archive-inmem</span></tt>, else (especially if data is indexed) the resulting effect is that of loading everything in RAM;</li>
</ul>
</blockquote>
<p><tt class="docutils literal"><span class="pre">--hosts-disable</span></tt></p>
<blockquote>
Disables the virtual-hosts feature by ignoring the <cite>Host</cite> header.</blockquote>
<p><tt class="docutils literal"><span class="pre">--special-pages-disable</span></tt></p>
<blockquote>
<p>Disables serving a few special pages internal to the server like:</p>
<pre class="literal-block">
/__/heartbeat
/__/kawipiko/about
/__/kawipiko/version
/__/kawipiko/manual.txt
/__/kawipiko/manual.html
/__/kawipiko/sbom.txt
/__/kawipiko/sbom.json
/__/kawipiko/sources.md5
/__/kawipiko/sources.cpio
/__/kawipiko/banners/errors/403
/__/kawipiko/banners/errors/...
</pre>
</blockquote>
<p><tt class="docutils literal"><span class="pre">--security-headers-disable</span></tt></p>
<blockquote>
<p>Disables adding a few security related headers:</p>
<pre class="literal-block">
Referrer-Policy: strict-origin-when-cross-origin
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
X-Frame-Options: sameorigin
</pre>
</blockquote>
<p><tt class="docutils literal"><span class="pre">--security-headers-tls</span></tt></p>
<blockquote>
<p>Enables adding the following TLS related headers to the response:</p>
<pre class="literal-block">
Strict-Transport-Security: max-age=31536000
Content-Security-Policy: upgrade-insecure-requests
</pre>
<p>These instruct the browser to always use HTTPS for the served domain.
(Useful even without HTTPS, when used behind a TLS terminator, load-balancer or proxy that do support HTTPS.)</p>
</blockquote>
<p><tt class="docutils literal"><span class="pre">--report</span></tt></p>
<blockquote>
Enables periodic reporting of various metrics.
Also enables reporting a selection of metrics if certain thresholds are matched (which most likely is a sign of high-load).</blockquote>
<p><tt class="docutils literal"><span class="pre">--quiet</span></tt></p>
<blockquote>
Disables most logging messages.</blockquote>
<p><tt class="docutils literal"><span class="pre">--debug</span></tt></p>
<blockquote>
Enables all logging messages.</blockquote>
<p><tt class="docutils literal"><span class="pre">--dummy</span></tt>, <tt class="docutils literal"><span class="pre">--dummy-empty</span></tt></p>
<blockquote>
<p>It starts the server in a &quot;dummy&quot; mode, ignoring all archive related arguments and always responding with <tt class="docutils literal">hello <span class="pre">world!\n</span></tt> (unless <tt class="docutils literal"><span class="pre">--dummy-empty</span></tt> was used) and without additional headers except the HTTP status line and <tt class="docutils literal"><span class="pre">Content-Length</span></tt>.</p>
<p>This argument can be used to benchmark the raw performance of the underlying <tt class="docutils literal">fasthttp</tt>, Go's <tt class="docutils literal">net/http</tt>, or QUIC performance; this is the upper limit of the achievable performance given the underlying technologies.
(From my own benchmarks <tt class="docutils literal">kawipiko</tt>'s adds only about ~15% overhead when actually serving the <tt class="docutils literal"><span class="pre">hello-world.cdb</span></tt> archive.)</p>
</blockquote>
<p><tt class="docutils literal"><span class="pre">--dummy-delay</span> &lt;duration&gt;</tt></p>
<blockquote>
<p>Enables delaying each response with a certain amount (for example <tt class="docutils literal">1s</tt>, <tt class="docutils literal">1ms</tt>, etc.)</p>
<p>It can be used to simulate the real-world network latencies, perhaps to see how a site with many resources loads in various conditions.
(For example, see <a class="reference external" href="https://notes.volution.ro/v1/2019/08/notes/e8700e9a/">an experiment</a> I made with an image made out of 1425 tiles.)</p>
</blockquote>
<p><tt class="docutils literal"><span class="pre">--profile-cpu</span> &lt;path&gt;</tt>, and <tt class="docutils literal"><span class="pre">--profile-mem</span> &lt;path&gt;</tt></p>
<blockquote>
Enables CPU and memory profiling using Go's profiling infrastructure.</blockquote>
</div>
</div>
</body>
</html>

View file

@ -61,6 +61,8 @@ NAME
--sources-md5 (dump an `md5sum` of the sources) --sources-md5 (dump an `md5sum` of the sources)
--sources-cpio (dump a `cpio.gz` of the sources) --sources-cpio (dump a `cpio.gz` of the sources)
--sbom --sbom-text --sbom-json
---- ----
@ -187,8 +189,18 @@ FLAGS
--special-pages-disable --special-pages-disable
Disables serving a few special pages internal to the server like: Disables serving a few special pages internal to the server like:
/__/about /__/version /__/heartbeat /__/sources.md5
/__/sources.cpio /__/banners/errors/403 /__/banners/errors/... /__/heartbeat
/__/kawipiko/about
/__/kawipiko/version
/__/kawipiko/manual.txt
/__/kawipiko/manual.html
/__/kawipiko/sbom.txt
/__/kawipiko/sbom.json
/__/kawipiko/sources.md5
/__/kawipiko/sources.cpio
/__/kawipiko/banners/errors/403
/__/kawipiko/banners/errors/...
--security-headers-disable --security-headers-disable
Disables adding a few security related headers: Disables adding a few security related headers:

View file

@ -138,20 +138,32 @@ func (_server *server) ServeUnwrapped (_context *fasthttp.RequestCtx) () {
if bytes.Equal (_path, StringToBytes ("/__/heartbeat")) || bytes.HasPrefix (_path, StringToBytes ("/__/heartbeat/")) { if bytes.Equal (_path, StringToBytes ("/__/heartbeat")) || bytes.HasPrefix (_path, StringToBytes ("/__/heartbeat/")) {
_server.ServeStatic (_context, http.StatusOK, HeartbeatDataOk, HeartbeatContentType, HeartbeatContentEncoding, false) _server.ServeStatic (_context, http.StatusOK, HeartbeatDataOk, HeartbeatContentType, HeartbeatContentEncoding, false)
return return
} else if bytes.Equal (_path, StringToBytes ("/__/about")) || bytes.Equal (_path, StringToBytes ("/__/about/")) { } else if bytes.Equal (_path, StringToBytes ("/__/kawipiko/about")) || bytes.Equal (_path, StringToBytes ("/__/kawipiko/about/")) {
_server.ServeStatic (_context, http.StatusOK, AboutBannerData, AboutBannerContentType, AboutBannerContentEncoding, true) _server.ServeStatic (_context, http.StatusOK, AboutBannerData, AboutBannerContentType, AboutBannerContentEncoding, true)
return return
} else if bytes.Equal (_path, StringToBytes ("/__/version")) || bytes.Equal (_path, StringToBytes ("/__/version/")) { } else if bytes.Equal (_path, StringToBytes ("/__/kawipiko/version")) || bytes.Equal (_path, StringToBytes ("/__/kawipiko/version/")) {
_server.ServeSpecial (_context, "version", true) _server.ServeSpecial (_context, "version", true)
return return
} else if bytes.Equal (_path, StringToBytes ("/__/sources.md5")) { } else if bytes.Equal (_path, StringToBytes ("/__/kawipiko/manual.txt")) {
_server.ServeSpecial (_context, "manual.txt", true)
return
} else if bytes.Equal (_path, StringToBytes ("/__/kawipiko/manual.html")) {
_server.ServeSpecial (_context, "manual.html", true)
return
} else if bytes.Equal (_path, StringToBytes ("/__/kawipiko/sources.md5")) {
_server.ServeSpecial (_context, "sources.md5", true) _server.ServeSpecial (_context, "sources.md5", true)
return return
} else if bytes.Equal (_path, StringToBytes ("/__/sources.cpio")) { } else if bytes.Equal (_path, StringToBytes ("/__/kawipiko/sources.cpio")) {
_server.ServeSpecial (_context, "sources.cpio", true) _server.ServeSpecial (_context, "sources.cpio", true)
return return
} else if bytes.HasPrefix (_path, StringToBytes ("/__/banners/errors/")) { } else if bytes.Equal (_path, StringToBytes ("/__/kawipiko/sbom.txt")) {
_code := _path[len ("/__/banners/errors/") :] _server.ServeSpecial (_context, "sbom.txt", true)
return
} else if bytes.Equal (_path, StringToBytes ("/__/kawipiko/sbom.json")) {
_server.ServeSpecial (_context, "sbom.json", true)
return
} else if bytes.HasPrefix (_path, StringToBytes ("/__/kawipiko/banners/errors/")) {
_code := _path[len ("/__/kawipiko/banners/errors/") :]
if _code, _error := strconv.Atoi (BytesToString (*NoEscapeBytes (&_code))); _error == nil { if _code, _error := strconv.Atoi (BytesToString (*NoEscapeBytes (&_code))); _error == nil {
_banner, _bannerFound := ErrorBannersData[uint (_code)] _banner, _bannerFound := ErrorBannersData[uint (_code)]
if (_code > 0) && _bannerFound { if (_code > 0) && _bannerFound {
@ -522,6 +534,16 @@ func (_server *server) ServeSpecial (_context *fasthttp.RequestCtx, _special str
_contentType = MimeTypeText _contentType = MimeTypeText
_contentEncoding = "identity" _contentEncoding = "identity"
case "manual.txt" :
_data = StringToBytes (manualText)
_contentType = MimeTypeText
_contentEncoding = "identity"
case "manual.html" :
_data = StringToBytes (manualHtml)
_contentType = MimeTypeHtml
_contentEncoding = "identity"
case "sources.md5" : case "sources.md5" :
_data = StringToBytes (embedded.BuildSourcesMd5) _data = StringToBytes (embedded.BuildSourcesMd5)
_contentType = MimeTypeText _contentType = MimeTypeText
@ -532,6 +554,16 @@ func (_server *server) ServeSpecial (_context *fasthttp.RequestCtx, _special str
_contentType = MimeTypeText _contentType = MimeTypeText
_contentEncoding = "application/x-cpio" _contentEncoding = "application/x-cpio"
case "sbom.txt" :
_data = StringToBytes (embedded.SbomTxt)
_contentType = MimeTypeText
_contentEncoding = "identity"
case "sbom.json" :
_data = StringToBytes (embedded.SbomJson)
_contentType = MimeTypeJson
_contentEncoding = "identity"
default : default :
panic ("[8546f2bd]") panic ("[8546f2bd]")
} }
@ -711,6 +743,14 @@ func Main () () {
version.Main ("kawipiko-server", "sources.cpio") version.Main ("kawipiko-server", "sources.cpio")
return return
case "--sbom-text", "--sbom-txt", "--sbom" :
version.Main ("kawipiko-server", "sbom.txt")
return
case "--sbom-json" :
version.Main ("kawipiko-server", "sbom.json")
return
case "--help", "-h" : case "--help", "-h" :
if _, _error := os.Stdout.WriteString (usageText); _error == nil { if _, _error := os.Stdout.WriteString (usageText); _error == nil {
return return
@ -2593,6 +2633,9 @@ var usageText string
//go:embed manual.txt //go:embed manual.txt
var manualText string var manualText string
//go:embed manual.html
var manualHtml string
func init () { func init () {
usageText = strings.ReplaceAll (usageText, "@{SCHEMA}", CurrentSchemaVersion) usageText = strings.ReplaceAll (usageText, "@{SCHEMA}", CurrentSchemaVersion)
} }

View file

@ -41,8 +41,10 @@
--report --quiet --debug --report --quiet --debug
--version
--help (show this short help) --help (show this short help)
--man (show the full manual) --man (show the full manual)
--sources-md5 --sources-cpio --sbom --sbom-json
** supported archive version: @{SCHEMA} ** supported archive version: @{SCHEMA}

View file

@ -70,6 +70,16 @@ func Main (_executableName string, _special string) () {
AbortError (_error, "[292d8865] unexpected error!") AbortError (_error, "[292d8865] unexpected error!")
} }
case "sbom.txt" :
if _, _error := os.Stdout.Write (StringToBytes (SbomTxt)); _error != nil {
AbortError (_error, "[e8f9540a] unexpected error!")
}
case "sbom.json" :
if _, _error := os.Stdout.Write (StringToBytes (SbomJson)); _error != nil {
AbortError (_error, "[9f9eb7ff] unexpected error!")
}
default : default :
panic ("[65a6f35f]") panic ("[65a6f35f]")
} }

View file

@ -34,6 +34,14 @@ func main () () {
version.Main ("kawipiko-wrapper", "sources.cpio") version.Main ("kawipiko-wrapper", "sources.cpio")
return return
case "--sbom-text", "--sbom-txt", "--sbom" :
version.Main ("kawipiko-wrapper", "sbom.txt")
return
case "--sbom-json" :
version.Main ("kawipiko-wrapper", "sbom.json")
return
case "server" : case "server" :
server.Main () server.Main ()
return return

View file

@ -0,0 +1,19 @@
package embedded
import _ "embed"
//go:embed documentation/sbom.txt
var SbomTxt string
//go:embed documentation/sbom.html
var SbomHtml string
//go:embed documentation/sbom.json
var SbomJson string