美文网首页API网关Kong实践笔记
Kong[nginx]-19 玩转ngx.redirect

Kong[nginx]-19 玩转ngx.redirect

作者: 国服最坑开发 | 来源:发表于2019-08-25 18:42 被阅读7次

KONG专题目录


NR;TL

今天我们要实现的需求如下:

App组的小伙伴们会不定期发布一个新产品, 包含iOSAndroid两个平台.
他们希望后端提供一个统一的下载链接, 可以根据手机的不同, 自动返回相应的实现下载地址.

本文会以Kong插件的形式提供一个解决方案.

0x01 以终为始,我们的效果是什么?

我们会提供一个这样的统一入口URL:

http://aaa.com/app/url/{appName}

当我们的插件监听到这个路由的请求时,
通过分析Header里的User-Agent来区分手机设备类型.
然后跳转到与appName相应平台的下载结果.
这里会用到一个方法ngx.redirect

ngx.redirect
syntax: ngx.redirect(uri, status?)

context: rewrite_by_lua, access_by_lua, content_by_lua*

Issue an HTTP 301 or 302 redirection to uri.

Redirecting arbitrary external URLs is also supported, for >example:

return ngx.redirect("http://www.google.com")

说一下重点:

  • access()方法中可以使用
  • 支持完整路径URL跳转
0x02 代码实现

为了方便理解代码实现, 我们先看一下使用效果图
插件配置时, 我们需要配置一个参数项: appSettings
它可以接收多个值.
每一个值的字符格式为 : appName`android下载地址`iOS下载地址`
注意的是, 我使用了反引号作为字符串分隔符

插件参数配置

然后需要说明的地方就是这个配置参数加载的时候
我做了两步:

  • 把每一行参数先转换成一个lua table
  • 把所有参数放到一个大的 table里,key 就是 appName, 值就是上面的完整的table

这一部分的代码实现受限于目前对lua的熟悉程序, 请小伙伴们自行优化完善.


  • handler.lua
local BasePlugin = require "kong.plugins.base_plugin"

local Handler    = BasePlugin:extend()

Handler.VERSION  = "1.0.0"
Handler.PRIORITY = 10

local iOSDevices = {
    'iPhone',
    'iPad',
    'iPod',
    'iOS',
}

local function splitStr (inputStr, sep)
    if sep == nil then
        sep = "%s"
    end
    local t={}
    for str in string.gmatch(inputStr, "([^"..sep.."]+)") do
        table.insert(t, str)
    end
    return t
end

local function not_found()
    return kong.response.exit(404, "404 Not Found", {
        ["Content-Type"]     = "text/plain",
    })
end

function Handler:access(config)
    Handler.super.access(self)

    -- 查找{appName}参数
    local pathVars = splitStr(kong.request.get_path(), '/')
    if #pathVars < 3 then
        not_found()
    end

    local appName = pathVars[3]

    -- 判断客户端设备类型
    local userAgent = kong.request.get_header("User-Agent") or 'android'
    local isAndroid = true
    for _, v in ipairs(iOSDevices) do
        if string.find(userAgent, v) then
            isAndroid = false
        end
    end

    kong.log(isAndroid)

    -- 加载插件配置
    local appUrlTable = {}
    for _, v in ipairs(config.appSettings) do
        local _app = splitStr(v, '`')
        appUrlTable[_app[1]] = _app
    end

    -- 查找appName
    local appNameUrls = appUrlTable[appName]
    if appNameUrls == nil then
        not_found()
    end

    -- 根据类型返回相应实际下载URL
    if isAndroid then
        ngx.redirect(appNameUrls[2])
    else
        ngx.redirect(appNameUrls[3])
    end

end

return Handler
  • schema.lua
local typedefs     = require "kong.db.schema.typedefs"

local string_array = {
    type     = "array",
    default  = {},
    elements = { type = "string" },
}

return {
    name   = "app-url",
    fields = {
        { protocols = typedefs.protocols_http },
        { config = {
            type   = "record",
            fields = {
                { appSettings = string_array },
            },
        },
        },
    },
}

0x03 插件使用

插件安装部分, 这里略过, 前文已经多次提及, 这里真的不想写了 - -!

  • 添加一个Service:

    service
  • 添加一个Router

    route
  • Router绑定插件

    绑定插件
  • 插件参数配置

输入内容为 jianshu`http://www.android.com`http://www.apple.com

配置
0x04 验证
  • 先来看一下正常系测试 :


    命令行测试
  • 再来看看异常系测试:
    主要看看URL格式不正确, 和没有配置项时的表现

    404测试
  • 浏览器测试
    先改代理, 模拟iPhone手机请求

    改代理
    失败时的请求: http://aaa.com/app/url/lala
    异常请求

成功时的请求: http://aaa.com/app/url/jianshu

成功时效果

android.com 网站打不开, 看不到效果, 哇哈哈哈, 不想改地址重测了.

0x05 小结

是的, 我们做到了, 技术难度不大, 但真的在API网关层面做完了..
不需要后端服务开发, 而且还带UI配置界面, 使用体验极好 :)

PS: 昨天中午午觉后,突发耳鸣,唉, 我真的想静静了


KONG专题目录


相关文章

  • Kong[nginx]-19 玩转ngx.redirect

    KONG专题目录 NR;TL 今天我们要实现的需求如下: App组的小伙伴们会不定期发布一个新产品, 包含iOS和...

  • kong 专题目录

    0x01 环境篇 Kong[nginx]-01 CentOS7 图文安装 Kong[nginx]-02 CentO...

  • Kong网关-初探

    1 Kong网关介绍 Kong是在Nginx的基础上构建的,更确切的说Kong是在Nginx中运行的Lua应用程序...

  • API网关——Kong实践分享

    概述 01 什么是Kong Kong是一个在Nginx中运行的Lua应用程序,可以通过lua-nginx模块实现,...

  • Kong自定义日志格式

    一、背景 Kong使用nginx作为运行时,因此把nginx的配置文件也进行了封装,当你在使用kong的时候,不需...

  • 架构

    技术选型 网关:Nginx[http://www.w3cjava.com/?s=nginx]、Kong、Zuul[...

  • Kong&Konga - Docker安装部署

    简介 kong在openresty基础上进行的开发,而openresty基于nginx,所以kong的很多概念和用...

  • API 网关 Kong 实战

    1.Kong 介绍 Kong 是一款基于 OpenResty(Nginx + Lua 模块)编写的高可用、易扩展的...

  • kong 开启 gzip

    vim /usr/local/share/lua/5.1/kong/templates/nginx.lua

  • kong技术方案

    kong的介绍 kong基于nginx开发的API Gateway(可以认为是一个OpenResty应用程序),可...

网友评论

    本文标题:Kong[nginx]-19 玩转ngx.redirect

    本文链接:https://www.haomeiwen.com/subject/gnqkectx.html