-
-
Save Kali-lightsaber/e006c358d98a182eb52e42f285e185fa to your computer and use it in GitHub Desktop.
openresty
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
user nginx; | |
worker_processes 1; | |
error_log logs/error.log info; | |
pid logs/nginx.pid; | |
events { | |
worker_connections 1024; | |
} | |
http { | |
include mime.types; | |
default_type application/octet-stream; | |
lua_package_path '/usr/local/nginx/lua/?.lua;lua/?.lua;;'; | |
lua_code_cache on; | |
resolver 8.8.8.8; | |
log_format main '$remote_addr - $remote_user [$time_local] "$request" ' | |
'$status $body_bytes_sent "$http_referer" ' | |
'"$http_user_agent" "$http_x_forwarded_for"'; | |
access_log /var/log/nginx/access.log main; | |
gzip on; | |
gzip_min_length 1k; | |
gzip_buffers 4 16k; | |
gzip_comp_level 5; | |
gzip_types text/plain application/json application/javascript text/css application/xml text/javascript; | |
client_max_body_size 10M; | |
client_body_buffer_size 128k; | |
sendfile on; | |
tcp_nopush on; | |
tcp_nodelay on; | |
keepalive_timeout 65; | |
types_hash_max_size 2048; | |
server { | |
listen 80; | |
server_name localhost; | |
default_type text/html; | |
location / { | |
-- access_by_lua_file 参数验证阶段 | |
-- content_by_lua_block 内容生成阶段。可以在里面写lua代码。类似的还有content_by_lua_file,通过指定一个外部的文件。 | |
content_by_lua_block { | |
-- ngx.say 和 nginx.print 都是输出响应体。ngx.say 会对输出响应体多输出一个 \n。 | |
-- 如果要记录日志使用ngx.log(level, ...)。日志级别有ngx.INFO/ERR/WARN/DEBUG | |
ngx.say("hello, world."); | |
} | |
} | |
location = /sum { | |
internal; | |
content_by_lua_block { | |
-- 获取url上面的参数 | |
local args = ngx.req.get_uri_args(); | |
ngx.say(tonumber(args.a) + tonumber(args.b)); | |
} | |
} | |
location = /test1 { | |
content_by_lua_block { | |
-- ngx.location.capture 内部子查询。子请求只是模拟 HTTP 接口的形式,没有额外的 HTTP/TCP 流量 | |
-- ngx.location.capture_multi 并行内部查询。 | |
local res = ngx.location.capture( | |
-- ngx.encode_args 可以对传递的参数转义 | |
"/sum", { | |
-- method = ngx.HTTP_GET, | |
args = { | |
a = 3, | |
b = 8 | |
} | |
-- body = {} | |
} | |
); | |
ngx.say("status: ", res.status, " response: ", res.body); | |
} | |
} | |
location = /test2_1 { | |
content_by_lua_block { | |
ngx.say([[hello, test2]]); | |
} | |
} | |
location = /test2 { | |
rewrite_by_lua_block { | |
-- redirect 重定向。第二个参数可以设置状态码,默认 302 | |
-- ngx.exec 可以实现内部调整(内部重定向) | |
ngx.redirect("/test2_1"); | |
} | |
} | |
location = /test3 { | |
content_by_lua_block { | |
-- ngx.req.get_uri_args 获取query上面的参数 | |
-- ngx.req.get_post_args 获取post Body参数 | |
-- ngx.req.get_headers 获取请求头参数 | |
local args = ngx.req.get_uri_args(); | |
for k, v in pairs(args) do | |
ngx.say("[GET] key: ", k, ", val: ", v); | |
end | |
-- 解析请求体参数 需要先调用一次 read_body | |
ngx.req.read_body(); | |
args = ngx.req.get_post_args(); | |
for k, v in pairs(args) do | |
ngx.say("[POST] key: ", k, ", val: ", v); | |
end | |
} | |
} | |
# 加法 | |
location = /addition { | |
content_by_lua_block { | |
local args = ngx.req.get_uri_args(); | |
ngx.say(args.a + args.b); | |
} | |
} | |
# 减法 | |
location = /subtraction { | |
content_by_lua_block { | |
local args = ngx.req.get_uri_args(); | |
ngx.say(args.a - args.b); | |
} | |
} | |
# 乘法 | |
location = /multipication { | |
content_by_lua_block { | |
local args = ngx.req.get_uri_args(); | |
ngx.say(args.a * args.b); | |
} | |
} | |
# 除法 | |
location = /division { | |
content_by_lua_block { | |
local args = ngx.req.get_uri_args(); | |
ngx.say(args.a / args.b); | |
} | |
} | |
} | |
server { | |
listen 10.0.1.4:80 default; | |
default_type text/html; | |
location / { | |
content_by_lua_block { | |
ngx.say('Hello, World.'); | |
} | |
} | |
location = /redis { | |
content_by_lua_block { | |
local redis = require 'redis'; | |
local red = redis:new(); | |
red:set_timeout(1000); | |
local ok, err = red:connect('10.0.1.3', 6379); | |
if not ok then | |
ngx.say('connect err: ', err); | |
return; | |
end | |
local times; | |
-- 连接池 复用 如果times是0,代表第一次。如果需要授权,此时应该加上授权的逻辑。 | |
times, err = red:get_reused_times(); | |
if err then | |
ngx.say('get reused times err: ', err); | |
return; | |
end | |
ok, err = red:set('now', ngx.now() * 1000); | |
if not ok then | |
ngx.say('set err, ', err); | |
return; | |
end | |
ok, err = red:set_keepalive(10000, 10); | |
if not ok then | |
ngx.say('keepalive err, ', err); | |
return; | |
end | |
ngx.say('now: ', ngx.now() * 1000, ' times: ', times); | |
} | |
} | |
location = /mysql { | |
content_by_lua_block { | |
local mysql = require 'mysql'; | |
local db, err = mysql:new(); | |
if not db then | |
ngx.say('failed to instantiate mysql: ', err); | |
return; | |
end | |
db:set_timeout(1000); | |
local ok, err, errcode, sqlstate = db:connect{ | |
host = '127.0.0.1', | |
port = 3306, | |
database = 'ngx', | |
user = 'root', | |
password = 'root', | |
max_packet_size = 1024 * 1024 | |
} | |
if not ok then | |
ngx.say('failed to connect: ', err, ': ', errcode, ' ', sqlstate); | |
return; | |
end | |
ngx.say('connect to mysql'); | |
res, err, errcode, sqlstate = db:query('select * from user'); | |
if not res then | |
ngx.say("bad result: ", err, ": ", errcode, ": ", sqlstate, "."); | |
return; | |
end | |
local cjson = require "cjson"; | |
ngx.say("result: ", cjson.encode(res)); | |
local ok, err = db:set_keepalive(10000, 100) | |
if not ok then | |
ngx.say("failed to set keepalive: ", err); | |
return; | |
end | |
} | |
} | |
# /l/10001/1/index.html | |
location ~ ^/l/(\d+)/(\d+)/ { | |
-- 从正则匹配中取值 | |
set $lesson_id $1; | |
set $page_no $2; | |
content_by_lua_block { | |
-- ngx.var | |
ngx.say(ngx.var.lesson_id, ngx.var.page_no); | |
} | |
} | |
# /l/11011/index.html | |
location ~ ^/l/(\d+)/ { | |
set $lesson_id $1; | |
content_by_lua_block { | |
ngx.say(ngx.var.lesson_id); | |
} | |
} | |
# /p/1/index.html | |
location ~ ^/p/(\d+)/ { | |
set $page_id $1; | |
content_by_lua_block { | |
local cjson = require "cjson"; | |
local mysql = require 'mysql'; | |
local OSS_DOMAIN = "oss.oss-cn-beijing.aliyuncs.com"; | |
local db, err = mysql:new(); | |
if not db then | |
ngx.say('failed to instantiate mysql: ', err); | |
return; | |
end | |
db:set_timeout(1000); | |
local ok, err, errcode, sqlstate = db:connect{ | |
host = '172.16.0.107', | |
port = 3306, | |
database = 'ccsbase_vps', | |
user = 'root', | |
password = '51talk!#mysql', | |
max_packet_size = 1024 * 1024 | |
} | |
if not ok then | |
ngx.say('failed to connect: ', err, ': ', errcode, ' ', sqlstate); | |
return; | |
end | |
local times; | |
times, err = db:get_reused_times(); | |
ngx.log(ngx.INFO, 'times: ', times); | |
-- 连接复用 第一次做初始化工作 | |
if 0 == times then | |
db:query("SET NAMES utf8"); | |
end; | |
local res; | |
res, err, errcode, sqlstate = db:query('select * from page where id = ' .. ngx.quote_sql_str(ngx.var.page_id)); | |
if not res then | |
ngx.say("bad result: ", err, ": ", errcode, ": ", sqlstate, "."); | |
return; | |
end | |
local page = res[1]; | |
local template_id; | |
if nil ~= page then | |
template_id = page.templateid; | |
if ngx.null == template_id then | |
ngx.say("没有选择模板"); | |
return; | |
end | |
end | |
ngx.log(ngx.INFO, "page: ", cjson.encode(page)); | |
-- quote_sql_str 防止sql注入 | |
res, err, errcode, sqlstate = db:query('select * from template where id = ' .. ngx.quote_sql_str(template_id)); | |
if not res then | |
ngx.say("bad result: ", err, ": ", errcode, ": ", sqlstate, "."); | |
return; | |
end | |
local template = res[1]; | |
if nil ~= template then | |
if ngx.null == template.version then | |
ngx.say("模板没有上传代码"); | |
return; | |
end | |
end | |
local resource = string.sub(ngx.var.uri, string.len("/p/" .. ngx.var.page_id .. "/")); | |
-- content.js | |
if resource == "/content.js" then | |
ngx.header["Content-Type"] = "text/javascript; charset=UTF-8"; | |
ngx.log(ngx.INFO, "content: ", page.content); | |
ngx.say("var configData = " .. page.content); | |
return; | |
end; | |
-- index | |
if resource == "/" then | |
resource = "/index.html"; | |
end; | |
local uri; | |
if string.sub(resource, 1, string.len("/data")) == "/data" then | |
-- uri = "http://" .. OSS_DOMAIN .. "/" .. page.data .. string.sub(resource, string.len("/data") + 1); | |
uri = "/" .. page.data .. string.sub(resource, string.len("/data") + 1); | |
else | |
-- uri = "http://" .. OSS_DOMAIN .. "/" .. template.version .. resource; | |
uri = "/" .. template.version .. resource; | |
end; | |
ngx.log(ngx.INFO, "uri: ", uri); | |
local http = require "resty.http"; | |
local httpc = http.new(); | |
httpc:set_timeout(60 * 1000); | |
httpc:connect(OSS_DOMAIN, 80); | |
-- And request using a path, rather than a full URI. | |
res, err = httpc:request{ | |
path = uri | |
} | |
-- res, err = httpc:request_uri(uri); | |
if not res then | |
ngx.say("failed to request: ", err); | |
return; | |
end | |
ngx.status = res.status; | |
ngx.log(ngx.INFO, 'header: ', cjson.encode(res.headers)); | |
-- 设置响应头 | |
for k,v in pairs(res.headers) do | |
ngx.header[k] = v; | |
end | |
ngx.header["author"] = "tyk"; | |
local reader = res.body_reader; | |
repeat | |
local chunk, err = reader(1024); | |
if err then | |
ngx.log(ngx.ERR, err); | |
break | |
end | |
if chunk then | |
ngx.print(chunk); | |
end | |
until not chunk | |
local ok, err = db:set_keepalive(10000, 100) | |
if not ok then | |
ngx.say("failed to set keepalive: ", err); | |
return; | |
end | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment