openresty 前端开发进阶一之http后端

####做前端开发,大多数情况下,都需要跟后端打交道,而最常见的方式则是通过http请求,进行通信。

在openresty中,通过http跟后端整合通信的方式又很多种,各有各的好处,可以根据情况交叉使用

##1、直接proxy

这种方式最简单,也是我们最熟悉的,直接配置一个反向代理,跟nginx的用法一致

比如我们有一个后端服务,提供用户相关接口,是java写的,端口8080,为了简单起见,我直接在openresty里面配置一个server,模拟java端,通过一个简单的案例的来说明情况

nginx.conf

```

worker_processes1;

error_loglogs/error.log;

events{

worker_connections1024;

}

http{

lua_package_path"/Users/john/opensource/openresty-web-dev/demo7/lua/?.lua;/usr/local/openresty/lualib/?.lua";

server{

listen80;

server_namelocalhost;

lua_code_cacheoff;

location/{

roothtml;

indexindex.html;

}

location~^/user{

proxy_passhttp://127.0.0.1:8080;

}

}

#这个只是模拟后端

server{

listen8080;

server_namelocalhost;

lua_code_cacheoff;

location~/user/(.+){

default_typetext/html;

content_by_lua_filelua/$1.lua;

}

}

}

```

上面配置了两个location,将所有以/user开头的请求都转到后端的8080服务器,其他的则是静态页面,直接从html目录读取,然后返回,从这里开始就是前端开发了

为了简单起见,假设后端提供了一个登陆接口,我们这里直接用lua来实现一下就好了,检查用户名跟密码是admin,就返回成功,否则返回失败

lua/login.lua

```

localreq=require"req"

localcjson=require"cjson"

localargs=req.getArgs()

localusername=args['username']

localpassword=args['password']

localres={}

ifusername=="admin"andpassword=="admin"then

res['ret']=true

res['token']=ngx.md5('admin/'..tostring(ngx.time()))

else

res['ret']=false

end

ngx.say(cjson.encode(res))

```

index.html

```

<html>

<head>

<metacharset="UTF-8">

<title>LoginPage</title>

</head>

<body>

UserName:<inputtype="text"id="username"value="admin">

Password:<inputtype="password"id="password"value="admin">

<ahref="javascript:void(0)"onclick="login()">Login</a>

<scriptsrc="//cdn.bootcss.com/jquery/2.2.4/jquery.min.js"></script>

<script>

functionlogin(){

varusername=$('#username').val();

varpassword=$('#password').val();

$.post('/user/login',{username:username,password:password},function(res){

console.log(res)

varmsg=res.ret?"登录成功":"登录失败"

alert(msg)

},'json')

}

</script>

</body>

</html>

```

2、使用ngx.location.captrue

这个方法主要用于发送内部请求,即请求当前server内的其他location,默认会将当前请求的参数带过去,也可以手动指定参数,GET参数通过args传递,post参数通过body传递

如:

localreq=require"req"

localargs=req.getArgs()

GET调用

localres=ngx.location.capture('/user/login',{

method=ngx.HTTP_GET,

args=args,

});

POST调用

localres=ngx.location.capture('/user/login',{

method=ngx.HTTP_POST,

body=ngx.encode_args(args),

});

现在我们自己写一个lua来调用后台接口实现登陆,然后对请求做一点处理,实现一些额外的逻辑,比如在原来的参数上面加上一个from字段

lua/local-login.lua

```

localreq=require"req"

localcjson=require"cjson"

localargs=req.getArgs()

--GET

localres=ngx.location.capture('/user/login',{method=ngx.HTTP_GET,args=args})

--POST

--localres=ngx.location.capture('/user/login',{method=ngx.HTTP_POST,body=ngx.encode_args(args)})

--print(res.status)--状态码

ifres.status==200then

localret=cjson.decode(res.body)

ret['from']='local'

ngx.say(cjson.encode(ret))

else

print(res.body)

ngx.say('{"ret":false,"from":"local"}')

end

```

index.html也需要改一下,多加一个按钮,调用本地登陆接口

```

<html>

<head>

<metacharset="UTF-8">

<title>LoginPage</title>

</head>

<body>

UserName:<inputtype="text"id="username"value="admin">

Password:<inputtype="password"id="password"value="admin">

<ahref="javascript:void(0)"onclick="login()">Login</a>

<ahref="javascript:void(0)"onclick="local_login()">LocalLogin</a>

<scriptsrc="//cdn.bootcss.com/jquery/2.2.4/jquery.min.js"></script>

<script>

functionlogin(){

varusername=$('#username').val();

varpassword=$('#password').val();

$.post('/user/login',{username:username,password:password},function(res){

console.log(res)

varmsg=res.ret?"登录成功":"登录失败"

alert(msg)

},'json')

}

functionlocal_login(){

varusername=$('#username').val();

varpassword=$('#password').val();

$.post('/lua/local-login',{username:username,password:password},function(res){

console.log(res)

varmsg=res.ret?"本地登录成功":"本地登录失败"

alert(msg)

},'json')

}

</script>

</body>

</html>

```

3、第三方模块[lua-resty-http](https://github.com/pintsized/lua-resty-http)

这种方式跟上面那种不同的地方是调用的时候,不会带上本地请求的请求头、cookie、以及请求参数,不过这也使得请求更纯粹,不会带上那些没必要的东西,减少数据传输

最后local-login.lua变成如下

```

localreq=require"req"

localcjson=require"cjson"

localhttp=require"resty.http"

localargs=req.getArgs()

--GET

--localres=ngx.location.capture('/user/login',{method=ngx.HTTP_GET,args=args})

--POST

--localres=ngx.location.capture('/user/login',{method=ngx.HTTP_POST,body=ngx.encode_args(args)})

--http

localhttpc=http.new()

localres=httpc:request_uri("http://127.0.0.1:8080/user/login",{

method="POST",

body=ngx.encode_args(args),

headers={

["Accept"]="application/json",

["Accept-Encoding"]="utf-8",

["Cookie"]=ngx.req.get_headers()['Cookie'],

["Content-Type"]="application/x-www-form-urlencoded",

}

})

httpc:set_keepalive(60)

print(res.status)--状态码

ifres.status==200then

localret=cjson.decode(res.body)

ret['from']='local'

ngx.say(cjson.encode(ret))

else

print(res.body)

ngx.say('{"ret":false,"from":"local"}')

end

```

到此,基本上已经能通过openresty,做一些前后端的交互了,下次介绍怎么使用openresty模板渲染,以及搭配react开发前端。

[示例代码](https://github.com/362228416/openresty-web-dev)参见demo7部分

相关推荐