关于webmachine

haogongju、人人IT网、59n南龙、360doc不要抄我的烂博客了,私人备忘用。

基于mochiweb,REST风格的erlang Web容器。流程图见docs目录下的http-headers-status-v3.png。

它适合构建符合REST风格的面向资源的web应用,不适合那种需要HTTP长连接的应用(例如websocket,这也和webmachine基于的web服务器mochiweb支持websocket较弱有关,如果websocket很重要,有mislin和cowboy这两个web服务器可用,这些web服务器的比较见[url=https://github.com/ostinelli/misultin]这里[/url],扯远了)。

不过,它也提供了流(stream)的数据传输,这类数据作为HTTP消息体(HTTP Body)进行传输,包括请求数据和响应数据(HTTP的请求body和响应body),对于比较大的数据可以裁成一节一节的数据流进行传输。见[url=http://wiki.basho.com/Webmachine-Streamed-Body.html]Webmachine Streamed Body[/url]


[size=xx-large]hello, webmachine[/size]

webmachine提供了new_webmachine.sh脚本用于生成我们的webmachine应用骨架(一个标准的erlang OTP应用程序骨架、负责依赖管理和编译的rebar及其rebar配置,,make脚本,以及一个启动脚本),目录结构如下:
mywebdemo$ tree -L 2

.
├── deps/
│   ├── mochiweb
│   └── webmachine
├── ebin/
├── Makefile
├── priv/
│   ├── [color=red]dispatch.conf[/color]
│   ├── log/
│   └── www/
├── README
├── rebar
├── rebar.config
├── src/
│   ├── [b]mywebdemo.app.src[/b]
│   ├── [color=blue]mywebdemo_app.erl[/color]
│   ├── [color=blue]mywebdemo_sup.erl[/color]
│   ├── [color=darkblue]mywebdemo_resource.erl[/color]
│   └── [color=blue][b]mywebdemo.erl[/b][/color]
└── [color=green]start.sh[/color]

基于webmachine的web应用,用颜色标出开发相关部分,蓝色是这个web应用的erlang源代码,绿色为可执行脚本,红色为web应用的配置文件。深蓝色的是我们应用的web资源实现,理想情况下,不用修改其它erl模块,我们通过定义各种资源,并在dispatch.conf文件中设置好这些资源的映射实现我们的web应用。

所有的web请求日志都放在priv/log目录下,这些都是标准的http日志格式。
所有的静态文件都放在priv/www目录下,例如可以把我的web应用的favicon.ico放到这个目录下(这个简单的hello world应用现在还不能处理静态文件访问)

make之后用start.sh启动这个web应用,然后打开http://localhost:8000就可以看到hello world了

实际上这个骨架也可以用rebar生成,进入webmachine的目录后用rebar list-templates可以看到有一个wmskel的模版(就是WebMachine Skeleton的意思),在priv/templates目录下可以看到整个模版的内容,我们的web应用就是由此生成的。

[size=xx-large]基于webmachine的web应用[/size]

webmachine应用的结构如图所示:
[img]http://dl.iteye.com/upload/attachment/0071/9333/484d18e4-1ee5-3912-b1e8-75ea6488edd5.png[/img]

当webmachine应用启动后其supervisor管理的进程树上挂着一个webmachine_router的genserver,这是负责对外(比如我们要开发的web应用)联络的接口。


我们要开发的web应用是通过一个典型的Erlang OTP应用实现:
一个OTP application及其app配置,
一个OTP supervisor,启动webmachine的工作在这个模块的init函数中进行:

启动后的web应用结构如果所示:
[img]http://dl.iteye.com/upload/attachment/0071/7567/f16e9dad-7c68-3c47-9394-16bc2624e24c.png[/img]

webmachine_mochiweb实际上是mochiweb_socket_server的注册名。

此外还包括一个控制模块mywebdemo,它有两个任务:
负责启动web应用依赖的其它应用(inets,crypto,mochiweb,webmachine);
最后启动这个application: mywebdemo。
此外这个模块还提供了stop功能

个人觉得mywebdemo这个模块有点像于C中main函数,在启动脚本start.sh中就直接使用这个模块启动我们的web应用。

不过我们这个由脚本自动生成的web应用骨架其实可以不必太过关注(不过HTTP服务的端口8000是写死在mywebdemo_sup模块中的)。
简单的理解是它负责将webmachine的HTTP处理逻辑嵌到mochiweb服务器中了。此后的HTTP请求都被webmachine接管过来,按照webmachine的逻辑(REST风格)进行处理,也就是docs目录下的那张大图(http-headers-status-v3.png)。

要关心的是如何处理资源。

[size=xx-large]实现REST风格的Web资源访问[/size]

自动生成的web应用骨架是不必修改的,需要做的是“添加”业务逻辑。

我们的web应用对外提供某种资源,对这些资源的处理也就是web应用的业务逻辑。每类资源的处理可以由一个erlang模块实现。


[size=x-large]资源的映射、路由、或者dispatch[/size]

哪个请求对应哪个资源这种映射关系(也就是路由,或者说是dispatch)是在dispatch.conf文件中配置的。(当然也可以调用webmachine_router:add_route/1函数动态添加)

例如,自动生成的mywebdemo_resource模块是一个最简单的hello world文本资源。缺省的dispatch.conf是这个样子:
{[], mywebdemo_resource, []}.
这个tuple中的第一个元素是个list,对应着url中的路径,list中的元素是url路径中的token(也就是/隔开的字符串)。例如对于url:
http://localhost:8000/ab/c/c/dddd/e/f
对应的path tokens就是:
["ab", "c", "c", "dddd", "e", "f"]

对url的dispatch匹配规则:
list中的元素有三种类型:字符串,一个特殊的atom,'*'和其它普通atom

[size=large]1. 字符串完全匹配[/size]
{["[color=red]ab[/color]"], mywebdemo_resource, []}.

只有http://localhost:8000/[color=red]ab[/color]/才能匹配mywebdemo_resource资源,

另外webmachine是区分大小写的,所以http://localhost:8000/Ab不会匹配这个资源。

[size=large]2. 通配符匹配[/size]
如果
{["ab", [color=red]'*'[/color]], mywebdemo_resource, []}.
现在这些url
http://localhost:8000/ab/[color=red]c[/color]
http://localhost:8000/ab/[color=red]cd[/color]
http://localhost:8000/ab/[color=red]c/d[/color]
http://localhost:8000/ab/[color=red]c/d/e[/color]
...
都能匹配资源了,注意'*'匹配了所有的末尾的path token(红色部分)。

对于这个dispatch
{[[color=blue]"ab", "c", "d"[/color], [color=red]'*'[/color]], mywebdemo_resource, []}.
只有这类url匹配了
http://localhost:8000/[color=blue]ab/c/d[/color]/[color=red]e[/color]

当然'*'也可以在中间,例如这个dispatch:
{["ab", [color=red]'*'[/color], "d", '*'], mywebdemo_resource, []}.
路径第一个token是ab,第3个是d的url都匹配这个资源。

'*'在中间与在末尾有一个很微妙的区别。如前所述,在末尾的'*'匹配一系列的path tokens,在中间的'*'只匹配一个path token。例如
{[[color=blue]"ab"[/color], [color=red]'*'[/color], [color=blue]"cd"[/color], [color=red]'*'[/color]], mydemo_resource, []}.

对于这个url
http://localhost:8000/[color=blue]ab[/color]/[color=red]c/pi[/color]/[color=blue]cd[/color]/[color=red]ee/ff[/color]
中间的'*'是没法匹配"c" 和"pi"这两个path tokens的,当然最后的'*'没有这个限制。

[size=large]3. 带名字绑定的统配[/size]

普通atom用在程序中,用于与路径token字符串建立映射。简单的讲这是个更高级的'*',它提供了路径的名字绑定:'*'是一种万能匹配,但是有时候我们想知道匹配的那部分path token怎么办,这时候名字绑定就可以用上了。举个例子,下面的atom是foo,对应的是ab之后紧跟的路径token,
{["ab", [color=red]foo[/color], "d", '*'], mywebdemo_resource, []}.
在程序中通过
V = wrq:path_info([color=red]foo[/color], ReqData)
就可以得到url中foo对应的路径token,例如url是
http://localhost:8000/ab/[color=red]werqwerqw[/color]/d/
那么V就是"werqwerqw"


[size=x-large]资源的实现[/size]

mywebdemo_resource是资源的缺省实现模块,内容如下
-module(mywebdemo_resource).
-export([init/1, to_html/2]).

-include_lib("webmachine/include/webmachine.hrl").

init([]) -> {ok, undefined}.

to_html(ReqData, State) ->
{"<html><body>Hello, new world</body></html>", ReqData, State}.


更多见[url=http://wiki.basho.com/Webmachine-Resource.html]这里[/url],比较枯燥。

[size=medium]对资源的访问[/size]

对资源的访问流程详见 http://wiki.basho.com/images/http-headers-status-v3.png

REST方式通过HTTP方法控制对资源的访问方式:创建(PUT),获取(GET)、修改(PUT/POST)还是删除(DELETE)资源。资源如果要支持以上方式就要自己提供相应的逻辑实现。

在REST之前,比较常见、也是比较直接的做法是,用户请求来之后,通过分析请求头的方法(即HTTP Method),调用对应的函数,(一个典型的例子如JEE的servlet,有对应的doGet,doPost等方法)。

但是webmachine不完全是通过HTTP Method分派处理的,它是通过content_types_provided和conttent_types_accepted提供对内容的处理方式。

前者指定对应的资源内容生成方式。也就是说根据HTTP客户请求的Accept消息头(HTTP Request Header)判断提供什么样的资源给用户。这种方式被称为Content negotiation
对应着资源的访问控制HTTP方法(GET)

后者通过HTTP客户请求的Content-Type消息头判断用户提供的数据是什么MIME类型的。
常用的对资源的访问控制HTTP方法(PUT/POST 等)都被分派到这个函数的处理上了。

DELETE方法倒是有对应的delete_resource

参考
http://wiki.basho.com/Webmachine-Quickstart.html
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值