A file based web template engine for fast APIs and websites. This repo favors very low memory and cpu that is tailored for docker containers and kubernetes pods. Stratis can run parallel/sidecar with your application.
- Command line server startup.
- Templating.
- Built-in REST API.
- Built-in WebSocket API.
- Built-in Sessions (etcd/cookie).
- Built-in OAuth2 and user permissions (Including websocket)
- Live update (triggered by file changes).
- Client side (browser) javascript api.
- Binary distributions.
Implemented in,
- NodeJS, with EJS backend and the express.js webserver.
See more info about planned language implementations below.
On the server, if we have,
- /www/index.html - Html EJS template.
- /www/index.code.js - The API methods and templating objects for index.html.
- /www/relative.html - Html EJS template.
Run command (using the cli) :
stratis /www
Or in code example
The page html definition index.html
,
<head>
<%- render_stratis_script_tag() %>
<script lang="javascript">
stratis.print_x_plus_2({x: 40}).then(val => console.log(val))
stratis.y().then(val => console.log(val))
</script>
</head>
<body>
<%- print_x_plus_2(40) %> <%- y %> <%- await include('./relative.html') %>
</body>
The page code api methods index.code.js
,
async function print_x_plus_2({ x }, context) {
return x + 2
}
module.exports = {
print_x_plus_2,
y: 33,
}
*.code.js
are always private.
To call the index.html api with REST,
GET http://[my_domain]/index.html/my_api_function?arg1=...&arg2=...
POST http://[my_domain]/index.html/my_api_function
payload: { "arg": "value" }
If you add on the server-side html template (page),
<head>
<%- render_stratis_script_tag('stratis') %>
<script lang="javascript">
stratis.print_x_plus_2({x: 40}).then(val => console.log(val))
stratis.y().then(val => console.log(val))
</script>
</head>
<body>
<%- print_x_plus_2(40) %> <%- y %> <%- await include('./relative.html') %>
</body>
A javascript object named stratis
will be created in the client browser, that includes all the exposed page api function as defined in [filepath].code.js
. See below website structure.
Note: you can change the name of the api object to whatever you like. Otherwise,
- In main pages the default is
stratis
- On included templates the default is the
[filename]
of the template.
Stratis uses file paths and extensions to specify application behavior (see Access control rules below). e.g.,
/public/index.html
or/index.public.html
would be public files since they match the public path specifier./private/index.html
or/index.private.html
would be private files since they match the private path specifier/secure/index.html
or/index.secure.html
would be secure files since they match the secure path specifier (Will trigger security_provider if defined)./public/index.code.js
would be an api code file for html since it ends in.code.js
/public/my_api
would be an api description, it would only be available if a matching.code.js
file is found/public/my_api.code.js
would be an api code file formy_api
since it ends in.code.js
public files can be downloaded.
*.code.js
files are always private.
Files that match the regex,
([^\w]|^)(private|public|secure)([^\w]|$)
would be public, private or secure respectively, following,
- If
private
appears the file/path is private. - Else if
secure
appears the file/path is secure. - Else if
public
appears the file/path is public.
All files are by default public unless the folder [serve_path]/public
exists, then all files are by default private unless under the folder public
.
Page files are rendered as templates if downloaded, and can have attached page code, remote methods and a rest api. Files with path [filepath].[ext]
are considered page files if,
- Match the extension:
.htm
,.html
,.css
,.json
,.yaml
- There exists a file named
[filepath without ext].code.js
.
Page files are rendered as templates using the ejs
template engine.
Code files define the methods/ejs objects/configuration of the page. A file will be a code file if its path ends with, .code.js
. Where,
- Code files are always private.
- Code files match a page file with the same filename, e.g, the code file,
index.code.js
will matchindex.html
andindex.htm
.
A example of a basic code file,
async function print_server_date_with_prefix({ sent_from_client }, context) {
// return value must json complient.
return `${sent_from_client}, server date: ${new Date()}`
}
let api_static_info = {
loaded_at: new Date(),
}
module.exports = {
api_static_info,
print_server_date_with_prefix,
}
And context
is of type StratisPageCallContext. Some of its properties,
{
req: {}, // the http (express) request object.
res: {}, // the http (express) response object.
session: {}, // the http session.
websocket: {}, // the stratis api websocket (if called through a websocket)
...
}
The above code file will expose,
- A method called
print_server_date_with_prefix
that would be available in the browser or under[page_url]/print_server_date_with_prefix
- An object (will be printed as json or string) that would be available in the browser or under
[page_url]/api_static_info
Code file methods are exposed as REST api, where both the payload and query string is parsed as the method arguments. To call a page api,
http(s)://mydomain.com/[filepath.ext]/[api_exposed_method_or_function]?arg1=..&arg2=...
Where the method first argument is the merge result of the dictionaries,
query-string
- the dictionary of arguments.request payload
- If content type is not defined or content type includes the word 'json', parse as json args. Otherwise assume input stream in request. Websocket request are always json.
NOTE! See file upload example here.
Code files methods are exposed as WebSocket api. You can connect a websocket to the page api via,
ws(s)://mydomain.com/[filepath.ext]
Where the WebSocket payload is,
{
"rid": "[the request id]",
"name": "[the function or object name]",
"args": {
"send_from_client": "value"
}
}
You cannot send files through the websocket api. Use the REST API instead (see above).
The following methods will be available on all pages, through the api or while rendering the template.
render_stratis_script()
- renders the stratis script for browsers (Native)render_stratis_api_yaml_description()
- renders the stratis api description as yamlrender_stratis_api_json_description()
- renders the stratis api description as json
Template objects (Overridable),
session
- The session =req.session
if exists otherwise an empty dictionary.req
- the http request.res
- the http response.context
-StratisPageCallContext
, holds information about the stratis render.
Feel free to ping me in issues or directly on LinkedIn to contribute.
Implementing the stratis low-impact webserver and allowing multiple language code files (e.g. code.py
or code.go
) would very helpful for dockerized (or pod running) micros-services and processing jobs; it may provide an easy way to generate an interface for monitoring and interacting with running containers or allow web interfaces to be created for visual monitoring, with little to no impact on the required resources.
Looking for help on this subject.
Copyright ©
Zav Shotan
and other contributors.
It is free software, released under the MIT licence, and may be redistributed under the terms specified in LICENSE
.