openresty 前端开发进阶一之http后端
做前端开发,大多数情况下,都需要跟后端打交道,而最常见的方式则是通过http请求,进行通信。
在openresty中,通过http跟后端整合通信的方式又很多种,各有各的好处,可以根据情况交叉使用
1、直接proxy
这种方式最简单,也是我们最熟悉的,直接配置一个反向代理,跟nginx的用法一致
比如我们有一个后端服务,提供用户相关接口,是java写的,端口8080,为了简单起见,我直接在openresty里面配置一个server,模拟java端,通过一个简单的案例的来说明情况
nginx.conf
worker_processes 1; error_log logs/error.log; events { worker_connections 1024; } http { lua_package_path "/Users/john/opensource/openresty-web-dev/demo7/lua/?.lua;/usr/local/openresty/lualib/?.lua"; server { listen 80; server_name localhost; lua_code_cache off; location / { root html; index index.html; } location ~ ^/user { proxy_pass http://127.0.0.1:8080; } } # 这个只是模拟后端 server { listen 8080; server_name localhost; lua_code_cache off; location ~ /user/(.+) { default_type text/html; content_by_lua_file lua/$1.lua; } } }
上面配置了两个location,将所有以/user开头的请求都转到后端的8080服务器,其他的则是静态页面,直接从html目录读取,然后返回,从这里开始就是前端开发了
为了简单起见,假设后端提供了一个登陆接口,我们这里直接用lua来实现一下就好了,检查用户名跟密码是admin,就返回成功,否则返回失败
lua/login.lua
local req = require "req" local cjson = require "cjson" local args = req.getArgs() local username = args['username'] local password = args['password'] local res = {} if username == "admin" and password == "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> <meta charset="UTF-8"> <title>Login Page</title> </head> <body> UserName: <input type="text" id="username" value="admin"> Password: <input type="password" id="password" value="admin"> <a href="javascript:void(0)" onclick="login()">Login</a> <script src="//cdn.bootcss.com/jquery/2.2.4/jquery.min.js"></script> <script> function login() { var username = $('#username').val(); var password = $('#password').val(); $.post('/user/login', {username: username, password: password}, function(res){ console.log(res) var msg = res.ret ? "登录成功" : "登录失败" alert(msg) }, 'json') } </script> </body> </html>
2、使用ngx.location.captrue
这个方法主要用于发送内部请求,即请求当前server内的其他location,默认会将当前请求的参数带过去,也可以手动指定参数,GET参数通过args传递,post参数通过body传递
如:
local req = require "req"
local args = req.getArgs()
GET 调用
local res = ngx.location.capture('/user/login', {
method = ngx.HTTP_GET, args = args,
});
POST 调用
local res = ngx.location.capture('/user/login', {
method = ngx.HTTP_POST, body = ngx.encode_args(args),
});
现在我们自己写一个lua来调用后台接口实现登陆,然后对请求做一点处理,实现一些额外的逻辑,比如在原来的参数上面加上一个from字段
lua/local-login.lua
local req = require "req" local cjson = require "cjson" local args = req.getArgs() -- GET local res = ngx.location.capture('/user/login', {method = ngx.HTTP_GET, args = args}) -- POST -- local res = ngx.location.capture('/user/login', {method = ngx.HTTP_POST, body = ngx.encode_args(args)}) -- print(res.status) -- 状态码 if res.status == 200 then local ret = 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> <meta charset="UTF-8"> <title>Login Page</title> </head> <body> UserName: <input type="text" id="username" value="admin"> Password: <input type="password" id="password" value="admin"> <a href="javascript:void(0)" onclick="login()">Login</a> <a href="javascript:void(0)" onclick="local_login()">Local Login</a> <script src="//cdn.bootcss.com/jquery/2.2.4/jquery.min.js"></script> <script> function login() { var username = $('#username').val(); var password = $('#password').val(); $.post('/user/login', {username: username, password: password}, function(res){ console.log(res) var msg = res.ret ? "登录成功" : "登录失败" alert(msg) }, 'json') } function local_login() { var username = $('#username').val(); var password = $('#password').val(); $.post('/lua/local-login', {username: username, password: password}, function(res){ console.log(res) var msg = res.ret ? "本地登录成功" : "本地登录失败" alert(msg) }, 'json') } </script> </body> </html>
3、第三方模块lua-resty-http
这种方式跟上面那种不同的地方是调用的时候,不会带上本地请求的请求头、cookie、以及请求参数,不过这也使得请求更纯粹,不会带上那些没必要的东西,减少数据传输
最后local-login.lua 变成如下
local req = require "req" local cjson = require "cjson" local http = require "resty.http" local args = req.getArgs() -- GET -- local res = ngx.location.capture('/user/login', {method = ngx.HTTP_GET, args = args}) -- POST -- local res = ngx.location.capture('/user/login', {method = ngx.HTTP_POST, body = ngx.encode_args(args)}) -- http local httpc = http.new() local res = 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) -- 状态码 if res.status == 200 then local ret = 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开发前端。
示例代码 参见demo7部分
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Python pygame如何安装?
Python pygame如何安装? 很多小伙伴各处找资料,花了很长时间也没有解决,所以我把自己学习的一点东西分享出来,供大家参考,有问题欢迎大家在下方提问. Linux 下安装: python2 下执行 $sudo pip2 install pygame 验证是否安装成功 $python2 -m pygame.examples.aliens python3 下执行 $sudo pip3 install pygame 验证是否安装成功 $python3 -m pygame.examples.aliens Windows 下安装: 注意:安装python的时候选择 add python to path 或者手动添加环境变量 然后在cmd中执行,不区分是32位还是64位系统 python2 下执行 pip install pygame python3 下执行 pip3 install pygame 在python3以上的版本,当然也可以使用pygame官方提供的命令进行安装 py -m pip install -U pygame 验证是否安装成功 py -m pygame.examples...
- 下一篇
python-面向对象进阶
一、isinstance(obj,cls)和issubclass(sub,super) isinstance(obj,cls)检查obj是否是cls的对象 issubclass(sub,super)检查sub是否是super的派生类 class Bar: pass class Foo(Bar): pass obj =Foo() print(isinstance(obj,Foo))#True print(issubclass(Foo,Bar))#True 二、反射 python面向对象中的反射:通过字符串的形式操作对象相关的属性 通过下面四个函数可以实现,适用于类和对象 hasattr(object,name):判断一个object中有没有name属性或者方法 getatrr(object,name,default=None):获取object中的name属性或方法,设置defult=None时没找到返回None,没设置报错 setattr(x,y,z)修改x中y的值为z,当y不存在时添加y的值为z delattr(x,y)删除x中的y属性或方法 演示代码: class BlackMed...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
-
Docker使用Oracle官方镜像安装(12C,18C,19C)
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8编译安装MySQL8.0.19
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
推荐阅读
最新文章
- CentOS7设置SWAP分区,小内存服务器的救世主
- 设置Eclipse缩进为4个空格,增强代码规范
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS6,CentOS7官方镜像安装Oracle11G
- Hadoop3单机部署,实现最简伪集群
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- CentOS7安装Docker,走上虚拟化容器引擎之路