sites
The sites
service is used to host content for an account and serve it over HTTP to the account's subdomain.
Service docs
SystemService::Sites
struct SystemService::Sites {
const psibase::AccountNumber service;
serveSys(...); // Serves a request by looking up the content uploaded to the specified subdomain
storeSys(...); // Stores content accessible at the caller's subdomain
remove(...); // Removes content from the caller's subdomain
isValidPath(...); // Checks whether a request for content on a site at the given path is valid (such a request will not produce a 404).
enableSpa(...); // Enables/disables single-page application mode. When enabled, all content requests return the root document.
setCsp(...); // Sets the Content Security Policy for the specified path (or "*" for a global CSP). If a specific CSP is set, it takes precedence over the global CSP. If no specific or global CSP is set, a default CSP is used.
enableCache(...); // Enables/disables HTTP caching of responses (Enabled by default) Cache strategy: - `If-None-Match` header is checked against the hash of the content - The hash is stored in the `ETag` header - If the hash matches, a 304 Not Modified response is returned - If the hash does not match, the new content is returned with an updated `ETag` header
};
Provide web hosting.
This service provides web hosting to all accounts. It is the default server that handles
hosting of the data
items specified in psibase packages.
See psibase CLI docs for details on how to upload files and directories.
After files are uploaded, the site is available at http://$ACCOUNT.$DOMAIN
SystemService::Sites::serveSys
std::optional<psibase::HttpReply> SystemService::Sites::serveSys(
psibase::HttpRequest request
);
Serves a request by looking up the content uploaded to the specified subdomain.
SystemService::Sites::storeSys
void SystemService::Sites::storeSys(
std::string path,
std::string contentType,
std::optional<std::string> contentEncoding,
std::vector<char> content
);
Stores content accessible at the caller's subdomain.
SystemService::Sites::remove
void SystemService::Sites::remove(
std::string path
);
Removes content from the caller's subdomain.
SystemService::Sites::isValidPath
bool SystemService::Sites::isValidPath(
psibase::AccountNumber site,
std::string path
);
Checks whether a request for content on a site at the given path is valid (such a request will not produce a 404)..
Note: For single-page applications, static assets (e.g. 'style.css') can be checked normally. However, all other assets
are routed client-side, so a route like /page1
is considered a valid route as long as the SPA serves a root document.
SystemService::Sites::enableSpa
void SystemService::Sites::enableSpa(
bool enable
);
Enables/disables single-page application mode. When enabled, all content requests return the root document..
SystemService::Sites::setCsp
void SystemService::Sites::setCsp(
std::string path,
std::string csp
);
Sets the Content Security Policy for the specified path (or "*" for a global CSP). If a specific CSP is set, it takes precedence over the global CSP. If no specific or global CSP is set, a default CSP is used..
SystemService::Sites::enableCache
void SystemService::Sites::enableCache(
bool enable
);
Enables/disables HTTP caching of responses (Enabled by default) Cache strategy:
If-None-Match
header is checked against the hash of the content- The hash is stored in the
ETag
header - If the hash matches, a 304 Not Modified response is returned
- If the hash does not match, the new content is returned with an updated
ETag
header.
Additional design notes
CSP header baseline
The Content-Security-Policy
header aids security efforts, as modern browsers restrict the capabilities of the document on the client-side according to the policy expressed in this header. The sites server uses a permissive baseline CSP header that should permit most common requirements.
Default policy | Values |
---|---|
default-src | self |
font-src | self, https: |
script-src | self, unsafe-eval, unsafe-inline, blob: https: |
img-src | * |
style-src | self, unsafe-inline |
frame-src | * |
connect-src | *, blob: |
Dynamic CSP
If the baseline CSP is insufficient, the sites
service allows users to customize the header for their entire site or for a specific path using the setCsp
action.
The priority of the CSP header applied to content is given to a header set for a specific path, then the header set for an entire site, and finally will default to the default policy if no custom headers were provided.
HTTP caching
On upload, the sites
server calculates and stores a hash of the content at each path. The server now returns the hash in an etag
header, as well as setting the cache-control
header to no-cache
.
This cache policy tells the browser to add, on any subsequent requests for the same content, an If-None-Match
header with the previously sent ETag value. The server then has a chance to respond with 304 Unmodified
, allowing the browser to use its cached value for the asset, rather than initiating a fresh transfer.
This helps reduce the load on the server and speeds up subsequent page loads.
Compression
Uploading assets to a psibase network using the the psibase CLI will automatically apply Brotli compression to content of a supported mime type.
Automatically compressed types:
- text/plain
- text/html
- text/css
- application/javascript
- application/json
- application/xml
- application/rss+xml
- application/atom+xml
- image/svg+xml
- font/ttf
- font/otf
- application/wasm
Compression level can be specified in every CLI where it makes sense:
psibase boot -z <LEVEL>
psibase upload -z <LEVEL>
psibase install -z <LEVEL>
cargo psibase install -z <LEVEL>
The compression level ranges from 1-11, where 1 is the fastest and 11 is the best compression. The default value is 4.
Fallback decompression
If the client uses the Accept-Encoding
HTTP request header to indicate that it does not support the encoding type of the requested content, and the server knows how to decompress the content, then the server will automatically decompress the content before serving it to the client.
The only encoding type that currently supports fallback decompression is Brotli.