A Rate-Limiting HTTP Proxy(4)HTTP MVC

A Rate-Limiting HTTP Proxy(4)HTTP MVC


HTTP
There are several HTTP handling method
Proxy - nginx work as an Proxy
location ~ ^/user {
    proxy_pass http://127.0.0.1:8080;
}

I try to make NGINX running on 80 port, but I get this error message:
[emerg] 73020#2236172: bind() to 0.0.0.0:80 failed (13: Permission denied)

Add this to the nginx.conf, restart it with sudoer
user root;

Exception:
nginx: [emerg] getgrnam("root") failed in /opt/luaweb/conf/nginx.conf:1

Solution:
http://blog.csdn.net/u013091013/article/details/51860303
I should as this line to the top.
user root owner;

Add HTML Editor to my Eclipse, add this URL to the plugin list http://download.eclipse.org/releases/mars/ - only select the HTML editor and JS editor

Here is the whole script - nginx.conf
user root owner;
worker_processes  1;
error_log  logs/error.log  notice;
events {
    worker_connections 1024;
}
http {
server {
listen 80;
location / {
root html;
index index.html;
}
location ~ ^/user {
proxy_pass http://localhost:8080;
}
}

lua_package_path "/opt/luaweb/lua/?.lua;;";
    server {
        listen 8080;
        lua_code_cache off;
        location ~ /user/(.+) {
            default_type text/html;
            content_by_lua_file lua/$1.lua;
        }
    }
}

index.html page to Show the Look and Feel
<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>

Here the LUA Script to handle the Login, that can be JAVA,PYTHON or any Other Backend.
lua/login.lua mock the Backend Logic
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

Module ngx.location.capture
We can do something on the params level.
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), });

Exception if we do GET without Post Body
no request body found; maybe you should turn on lua_need_request_body?

Solution:
That is because the HTTP method is not match in the jQuery. If it is using GET, then lua should be GET, or POST together.

Here is the final local-login.lua
local req = require "req"
local cjson = require "cjson"

local args = req.getArgs()

-- GET
local res = ngx.location.capture('http://localhost/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) -- status code

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

HTML button and command in index.html
<a href="javascript:void(0)" onclick="local_login()">Local Login</a>
function local_login() {
var username = $('#username').val();
var password = $('#password').val();
$.get('/user/local-login', {username: username, password: password}, function(res){
console.log(res)
var msg = res.ret ? "本地登录成功" : "本地登录失败"
alert(msg)
}, 'json')
}

Third Party Module lua-resty-http
https://github.com/pintsized/lua-resty-http

Exception:
2017/05/18 13:48:18 [error] 19934#2742039: *53 lua entry thread aborted: runtime error: /opt/luaweb/lua/local-login.lua:3: module 'resty.http' not found:

Solution:
https://moonbingbing.gitbooks.io/openresty-best-practices/ngx_lua/how_use_third_lib.html
Copy the lua module script in openresty
>cp ~/Downloads/lua-resty-http-master/lib/resty/*.lua ./

Updated local-login.lua to support Third Party
local req = require "req"
local cjson = require "cjson"
local http = require "resty.http"

local args = req.getArgs()

-- GET
-- local res = ngx.location.capture('http://localhost/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) -- status code

DispatherServlet — MVC
https://github.com/362228416/openresty-web-dev/tree/master/demo8

nginx.conf
http {
lua_package_path "$prefix/lua/?.lua;$prefix/lualib/?.lua;;";
    server {
        listen 80;
        server_name localhost;
        lua_code_cache off;

        location / {
        default_type "text/html; charset=utf-8";
        content_by_lua_file lualib/lite/mvc.lua;
        }

        location ~ ^/js/|^/css/|\.html {
        root html;
        }
    }
}

lualib/lite/mvc.lua is handle the moduleName/methodName
local uri = ngx.var.uri
-- home page
if uri == "" or uri == "/" then
    local res = ngx.location.capture("/index.html", {})
    ngx.say(res.body)
    return
end

local m, err = ngx.re.match(uri, "([a-zA-Z0-9-]+)/*([a-zA-Z0-9-]+)*")

local is_debug = true     

local moduleName = m[1]     -- module
local method = m[2]         -- method

if not method then
    method = "index"        -- default method index
else
    method = ngx.re.gsub(method, "-", "_")   
end

-- controller is under web
local prefix = "web."      
local path = prefix .. moduleName

-- input the module web.user
local ret, ctrl, err = pcall(require, path)

if ret == false then
    if is_debug then
        ngx.status = 404
        ngx.say("<p style='font-size: 50px'>Error: <span style='color:red'>" .. ctrl .. "</span> module not found !</p>")
    end
    ngx.exit(404)
end

-- method of the module, get, index
local req_method = ctrl[method]

if req_method == nil then
    if is_debug then
        ngx.status = 404
        ngx.say("<p style='font-size: 50px'>Error: <span style='color:red'>" .. method .. "()</span> method not found in <span style='color:red'>" .. moduleName .. "</span> lua module !</p>")
    end
    ngx.exit(404)
end

-- call lua method
ret, err = pcall(req_method)

if ret == false then
    if is_debug then
        ngx.status = 404
        ngx.say("<p style='font-size: 50px'>Error: <span style='color:red'>" .. err .. "</span></p>")
    else
        ngx.exit(500)
    end
end

2 Methods in lua/web/user.lua
local cjson = require "cjson"
local req = require "lite.req"

local _M = {}

local users = {"Mr Li", "Mr Luo", "Mr Kang"}

function _M.index()
  ngx.say(cjson.encode(users))
end

function _M.get()
  local args = req.getArgs()
  local index = tonumber(args['index'])
  if not index then
    index = 1
  end
  ngx.say(users[index])
end

return _M

We can visit page URL like this
http://localhost/user   — lua/web/user.lua method index
http://localhost/user/get?index=1   — lua/web/user.lua method get

Home Page index.html and index.js index.css are as follow:
<html>
<head>
<meta charset="UTF-8">
<title>Home Page</title>
<link rel="stylesheet" href="/css/index.css">
</head>
<body>
<div class="container">
<h1>UserLists</h1>
<ul id="users"></ul>
<p>Second<span id="user"></span></p>
</div>
<script src="//cdn.bootcss.com/jquery/2.2.4/jquery.min.js"></script>
<script src="/js/index.js"></script>
</body>
</html>

.container {
width: 1000px;
margin: 0 auto;
text-align: center;
}

(function(){
$.getJSON('/user/', function(data){
$('#users').html(data.join(','))
console.log(data)
})
$.get('/user/get', {index: 2}, function(data){
$('#user').html(data)
console.log(data)
})
})()


References:
https://github.com/362228416/openresty-web-dev/tree/master/demo7

https://moonbingbing.gitbooks.io/openresty-best-practices/


Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326644250&siteId=291194637