最新HTTP/2标准已经发布,是基于谷歌QUIC的技术升级而成。虽然标准已经发布,但是目前还鲜有应用支持,那么有没有方法进行技术尝鲜呢?答案是肯定的。本文虫虫给大家介绍一个Golang Web服务器应用Algernon,作为一个单文件的Golang应用内置了HTTP/2,Lua,Markdown,Pongo2,HyperApp,Amber, Sass (SCSS),GCSS,JSX,BoltDB的功能,支持 Redis , PostgreSQL ,MariaDB / MySQL数据库。支持限速,插件,用户和权限等各种功能。所有这些都包含在一个自包含 可执行文件 中,麻雀虽小五脏俱全。
技术架构
使用Golang开发,后端数据库可以使用Bolt(内置), MySQL ,PostgreSQL或Redis(推荐)。对各种功能支持总共使用了下面的类库:
permissions2用于处理用户和权限;gopher- lua 用于解释和运行Lua;http2用于服务HTTP/2,QUIC用于服务QUIC;blackfriday用于Markdown渲染;amber用于Amber模板;Pongo2用于Pongo2模板;Sass(S CSS )和GCSS用于CSS预处理;logrus用于日志记录;goja-babel用于从JSX转换为JavaScript;tollbooth用于速率限制;pie用于插件支持;graceful用于优雅关闭。
设计思想
该项目源于用Markdown,Pongo2,Amber,HTML或JSX(+ React)等编写应用,并用CSS样式支持和设计。数据使用Lua脚本与Redis,BoltDB,PostgreSQL或MariaDB/MySQL 链接 操作。
Amber和GCSS是时下静态网站的最佳组合方式,与HTML和CSS相比,它允许更清晰的架构,减少内容重复,也很容易使用Lua提供数据,支持MVC架构对模型(M),控制器(C)和视图(V)的更好的分割。
Pongo2,Sass和Lua也是很好的一个选择,而且Pongo2比Amber更灵活。
Bolt是一个纯粹的key/value存储,使用Golang编写。Bolt无需预先安装设置数据库,内置在Algernon中使用。也支持广泛使用的数据库,比如MariaDB/MySQL和PostgreSQL。
Algernon以下文件进行特殊渲染和解析以下文件(后缀),按优先顺序排列:
index.lua是Lua代码,动态lua脚本处理。
index.html HTML默认页面。
index.md 渲染为HTML下的Markdown代码。
index.txt 纯文本文件。
index.pongo2,index.po2或index.tmpl渲染为HTML的Pongo2代码。
index.amber渲染为HTML的Amber代码。
index.hyper.js或index.hyper.jsx渲染为HTML的JSX + HyperApp代码
data.lua是Lua代码,其中函数和变量可用于同一目录中的Pongo2、Amber和Markdown页面。
如果将单个Lua脚本作为命令行参数提供,用于独立服务器。它可用于设置处理程序或为特定URL前缀提供文件和目录。
style.gcss是GCSS代码,支持对同目录下的Pongo2,Amber和Markdown页面的样式。
总之,Algernon支持对以下文件扩展名的处理:
Markdown:.md(渲染为HTML)
Pongo2:.po2,.pongo2或.tpl(渲染为任何文本,通常为HTML)
琥珀色:.amber(渲染为HTML)
Sass:.scss(渲染为CSS)
GCSS:.gcss(渲染为CSS)
JSX:.jsx(渲染为JavaScript / ECMAScript)
Lua:.lua(提供自己的输出和内容类型的脚本)
HyperApp:.hyper.js或.hyper.jsx(渲染为HTML)
根据扩展名为其他文件指定mimetype。
没有索引文件的目录显示为目录列表。
尽可能使用UTF-8。
可以通过命令行或lua脚本配置服务器,但是配置是非必须的,默认无需配置既可以使用。
技术特点
支持HTTP,HTTP/2,默认启动HTTPS(HTTP/2需要浏览器支持)。
支持Lua动态程序,可以使用Lua脚本处理程序。
Algernon可执行文件为本机静态编译编,速度相当快。
适用于Linux,OS X和64位Windows。
Lua解释器被编译为可执行文件。
支持热部署自动刷新功能,实时编辑/实时预览。
自包含的Algernon应用程序可以压缩到存档(以.zip或.alg结尾),支持子启动时加载。
内置支持Markdown,Pongo2,Amber,Sass(SCSS),GCSS和JSX。
默认情况下,使用Redis作为数据库后端,如果没有可用的Redis服务器,Algernon将使用内置的Bolt数据库。
可以对Markdown渲染的HTML页面指定以MultiMarkdown语法的标题:
title: Title内容。
后台无需要文件转换器(如SASS)即可进行文件转化。
如果设置了autorefresh,源文件时自动刷新页面。
交互式REPL。
如果Markdown文件名作为第一个参数,则它将在端口3000上提供预览,无需任何数据库。方便在本地查看README.md文件。
完全多线程。将使用所有可用的CPU。
支持通过tollbooth进行速率限制。
Lua REPL提供了帮助命令,可快速浏览可用的Lua功能。
可以加载用任何语言编写的插件。插件必须提供Lua.Code和Lua.Help函数,并通过stderr + stdin来交互 JSON -RPC。
内置线程安全文件 缓存 ,具有多种可用缓存模式(例如,仅用于缓存图像)。
可以读取并保存到JSON文档。支持简单的JSON路径表达式(如简单版本的XPath,但对于JSON)。
支持缓存压缩,可以将缓存中存储的文件直接从缓存发送到客户端,无需解压缩。
对大于4096B的文件发送到客户端的文件默认使用gzip压缩。
使用PostgreSQL作为后端数据库时候,默认使用HSTORE键/值类型(PostgreSQL 9.1或更高版本)。
没有外部依赖,纯Golang程序。
需要Go 1.12或更高版本。另外用于QUIC支持的包不支持使用gccgo(GCC)构建。
安装
OS X
苹果OS X系统可以使用包管理器直接安装:
brew install algernon
如果没有安装Homebrew包管理器,请先安装。
Arch Linux
可以使用AUR源安装:
pacman -S algernon
二进制包
其他系统请下载对应二进制包即可使用。
源码安装
从源码编译安装,适用于任何系统。用get命令从官方主分支下载最新源码
get -u github/xyproto/algernon
使用该方法安装,需要先设置GOPATH, 并将$GOPATH/bin添加到执行PATH中
export GOPATH =~/go
export PATH = $PATH:$GOPATH/bin
也可以先git clone到本地然后编译安装
Golang 1.12版本
早期Golang版本
docker容器
Algernon基本使用
运行Algernon:
以开发者模式运行
algernon -e
该命令启用调试模式,以内置的Bolt数据库,以HTTP形式启动,并对除了以下类型的其他文件启用缓存,这些类型包括Pongo2,Amber,Lua,Sass,GCSS,Markdown和JSX。
新建一个简单的hello lua文件index.lua:
浏览器访问,结果如下:
自定义Algernon应用程序
创建应用目录:
mkdir mypage && cd mypage
创建名为index.lua的文件,其中包含以下内容和上面一样。
启动:
algernon –httponly –autorefresh .
启动增加参数autorefresh,使得文件编辑后可以热加载实时生效。可以试着编辑下index.lua并刷新浏览器以查看新结果。
注意—autorefresh对Markdown,Pongo2和Amber页面也生效,比如我新建一个chongchong.md页面:
然后浏览器访问:
HTTP/2 和HTTPS支持应用
利用openssl创建创建自签名证书,仅用于测试:
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 3000 -nodes
结果中,按照提示中按Return键,在Common Name时候输入任意名称,我们输入的是CC,就会在本目录生成cert.pem和key.pem两个证书文件
启动
algernon .
然后通过浏览器以https访问:
由于使用子签名证书,没有添加根域证书,需要在浏览器添加信息才能访问。
注意https头信息,确实是HTTP/2。
Lua支持
基本的Lua功能
//返回服务器的版本 字符串 。
version() -> string
//睡眠给定的秒数(可以是浮点数)。
sleep( number )
//将给定的字符串记录为信息。采用可变数量的字符串。
log(…)
//将给定的字符串记录为警告。采用可变数量的字符串。
warn(…)
//将给定的字符串记录为错误。采用可变数量的字符串。
err(…)
//返回1970年的纳秒数(Unix时间)
unixnano() -> number
//将Markdown转换为HTML
markdown(string) -> string
//返回运行REPL或脚本的目录。如果给出了文件名(可选),则返回脚本运行的路径,使用路径分隔符和给定的文件名连接。
scriptdir([string]) -> string
//返回运行服务器的目录。如果给出了文件名(可选),则返回服务器运行的路径,使用路径分隔符和给定的文件名连接。
serverdir([string]) -> string
Lua插件
//在给定可执行文件路径的情况下加载插件。成功时返回true。如果在Lua提示符上调用,将返回插件帮助文本。
Plugin(string)
//给定一个插件路径,返回插件中Lua.Code函数返回的Lua代码。可能会返回一个空字符串。
PluginCode(string) -> string
//获取插件路径,函数名称和参数。如果函数调用失败,则返回空字符串;如果成功,则返回结果为JSON字符串。
CallPlugin(string, string, …) -> string
Lua代码库函数
这些函数可以与插件函数结合使用,用于存储加载serverconf.lua时插件返回的Lua代码,然后在处理请求时检索Lua代码。
//创建或使用代码库对象。 (可选)将数据结构名称作为第一个参数。
CodeLib([string]) -> userdata
//给定命名空间和Lua代码,将给定代码添加到命名空间。成功时返回true。
codelib:add(string, string) -> bool
//给定命名空间和Lua代码,将给定代码设置为命名空间中的唯一代码。成功时返回true。
codelib:set(string, string) -> bool
//给定命名空间,返回Lua代码或空字符串。
codelib:get(string) -> string
//将给定命名空间中的(eval)代码导入当前的Lua状态。成功时返回true。
codelib:import(string) -> bool
//完全清除代码库。成功时返回true。
codelib:clear() -> bool
Lua文件上传函数
//创建文件上传对象。采用表单ID(来自POST请求)作为第一个参数。将可选的最大上载大小(以MiB为单位)作为第二个参数。
//失败时返回nil和错误字符串,成功时返回userdata和空字符串。
UploadedFile(string[, number]) -> userdata, string
//返回客户端指定的上传文件名
uploadedfile:filename() -> string
//返回已接收数据的大小
uploadedfile:size() -> number
Lua处理请求函数
//设置页面的Content-Type。
content(string)
//返回请求的HTTP方法(GET,POST等)。
method() -> string
//将文本输出到浏览器/客户端。采用可变数量的字符串。
print(…)
//返回请求的URL路径。
urlpath() -> string
//返回请求中的HTTP标头,给定键或空字符串。
header(string) -> string
//在给定键和值的情况下设置HTTP标头。
setheader(string, string)
更多函数支持请参考官方文档,此处略。
Markdown支持
Algernon实现对Markdown的快速浏览,实现在线webMarkdown查看器。-m标志用来启动:
algernon -m README.md在浏览器中查看README.md。
除了常规的Markdown语法之外,Algernon还支持在Markdown文件的顶部设置页眉标题和语法高亮样式,如下所示:
该代码将使用highlight.js突出显示代码,并提供多种样式。
replace_with_theme后面的字符串将用于替换当前主题字符串与给定字符串。这使得可以为一个主题使用一个图像(如logo_default_theme.png)。主题可以是light,dark,redbox,bw,github,wing,material,neon,default,werc或CSS文件的路径。或者同一目录下的style.gcss文件自定义的样式。
范例和截图
官方提供了大量的范例可以供使用,可以在官方仓下载samplepack.zip安装包,解压到web目录更目录然后通过浏览器就可以访问。
bootstrap小应用
hyperapp计数
这是在启用调试模式时处理Lua脚本中的错误的方法。
three.js
Algernon Charles Swinburne的一首诗,背景中有三个旋转的圆环。使用CSS3高斯模糊,使用three.js作为3D图形。
prettify代码美化
美化样本的屏幕截图,由单个Lua脚本提供。
todo小程序
使用Alact和Algernon交互使用