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

作前端开发,大多数状况下,都须要跟后端打交道,而最多见的方式则是经过http请求,进行通讯。

在openresty中,经过http跟后端整合通讯的方式又不少种,各有各的好处,能够根据状况交叉使用javascript

一、直接proxy

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

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

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目录读取,而后返回,从这里开始就是前端开发了java

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

lua/login.luajquery

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.htmlnginx

<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>

二、使用ngx.location.captruegit

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

如:

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>

三、第三方模块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部分

相关文章
相关标签/搜索