iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > GO >基于Go语言实现的简易api网关的示例代码
  • 798
分享到

基于Go语言实现的简易api网关的示例代码

GO示例go语言api 2022-06-07 20:06:07 798人浏览 安东尼
摘要

浏览器的请求去请求目标地址,然后获得结果它再发送给浏览器。对于Go语言来说,实现转发只需要简单的一行代码即可实现,如下所示: Httputil.NewSingleHostR

浏览器的请求去请求目标地址,然后获得结果它再发送给浏览器。对于Go语言来说,实现转发只需要简单的一行代码即可实现,如下所示:


Httputil.NewSingleHostReverseProxy(address)

基于此功能,进行简单包装,实现从远端admin管理中心获取需要转发的路由信息或者可以从本地配置文件中获取,实现动态转发。后续可以根据业务情况,可以实现如下功能:
开发接口,实现动态添加代理规则,进行转发

过滤不合法的接口

接口限流

统一日志记录

代码如下:


package main
import (
"encoding/JSON"
"flag"
"fmt"
"GitHub.com/gin-gonic/gin"
"io"
"io/ioutil"
"log"
"net/http"
"net/http/httputil"
"net/url"
"os"
"strings"
)
type Respond struct {
Success bool
Status  string
Data    []Proxy
}
type Proxy struct {
Remark        string //描述
Prefix        string //转发的前缀判断
Upstream      string //后端 Nginx 地址或者ip地址
RewritePrefix string //重写
}
var (
InfoLog  *log.Logger
ErrorLog *log.Logger
proxyMap = make(map[string]Proxy)
)
var adminUrl = flag.String("adminUrl", "", "admin的地址")
var profile = flag.String("profile", "", "环境")
var proxyFile = flag.String("proxyFile", "", "测试环境的数据")
//日志初始化
func initLog() {
errFile, err := os.OpenFile("errors.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
infoFile, err := os.OpenFile("info.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
log.Fatalln("打开日志文件失败:", err)
}
InfoLog = log.New(io.MultiWriter(os.Stderr, infoFile), "Info:", log.LstdFlags|log.Lmicroseconds|log.Lshortfile)
ErrorLog = log.New(io.MultiWriter(os.Stderr, errFile), "Error:", log.LstdFlags|log.Lmicroseconds|log.Lshortfile)
}
func main() {
router := gin.Default() //创建一个router
flag.Parse()
initLog()
if *profile != "" {
InfoLog.Printf("加载远端数据: %s ", *adminUrl)
initProxyList()
} else {
InfoLog.Printf("加载本地配置数据: %s", *proxyFile)
loadProxyListFromFile()
}
router.Any("/*action", Forward) //所有请求都会经过Forward函数转发
router.Run(":8000")
}
func initProxyList() {
resp, _ := http.Get(*adminUrl)
if resp != nil && resp.StatusCode == 200 {
bytes, err := ioutil.ReadAll(resp.Body)
defer resp.Body.Close()
if err != nil {
fmt.Println("ioutil.ReadAll err=", err)
return
}
var respond Respond
err = json.Unmarshal(bytes, &respond)
if err != nil {
fmt.Println("json.Unmarshal err=", err)
return
}
proxyList := respond.Data
for _, proxy := range proxyList {
//追加 反斜杠,为了动态匹配的时候 防止 /proxy/test  /proxy/test1 无法正确转发
proxyMap[proxy.Prefix+"/"] = proxy
}
}
}
func Forward(c *gin.Context) {
HostReverseProxy(c.Writer, c.Request)
}
func HostReverseProxy(w http.ResponseWriter, r *http.Request) {
if r.RequestURI == "/favicon.ico" {
io.WriteString(w, "Request path Error")
return
}
//从内存里面获取转发的url
var upstream = ""
if value, ok := proxyMap[r.RequestURI]; ok {
//如果转发的地址是 / 开头的,需要去掉
if strings.HasSuffix(value.Upstream, "/") {
upstream += strings.TrimRight(value.Upstream, "/")
} else {
upstream += value.Upstream
}
//如果首位不是/开头,则需要追加
if !strings.HasPrefix(value.RewritePrefix, "/") {
upstream += "/" + value.RewritePrefix
} else {
upstream += value.RewritePrefix
}
//去掉开头
r.URL.Path = strings.ReplaceAll(r.URL.Path, r.RequestURI, "")
}
// parse the url
remote, err := url.Parse(upstream)
InfoLog.Printf("RequestURI %s upstream %s remote %s", r.RequestURI, upstream, remote)
if err != nil {
panic(err)
}
r.URL.Host = remote.Host
r.URL.Scheme = remote.Scheme
r.Header.Set("X-Forwarded-Host", r.Header.Get("Host"))
r.Host = remote.Host
httputil.NewSingleHostReverseProxy(remote).ServeHTTP(w, r)
}
func loadProxyListFromFile() {
file, err := os.Open(*proxyFile)
if err != nil {
ErrorLog.Println("err:", err)
}
var respond Respond
// 创建json解码器
decoder := json.NewDecoder(file)
err = decoder.Decode(&respond)
if err != nil {
fmt.Println("LoadProxyListFromFile failed", err.Error())
}
proxyList := respond.Data
for _, proxy := range proxyList {
proxyMap[proxy.Prefix+"/"] = proxy
}
}

proxy_data.json 格式如下:


{
  "success":true,
  "status": "ok",
  "data": [
    {
      "remark": "测试环境",
      "prefix": "/division",
      "upstream": "http://test.xxxxx.cn/",
      "rewritePrefix": "/api/division"
    },
    {
      "remark": "测试环境1",
      "prefix": "/division1",
      "upstream": "http://test.xxxx.cn/",
      "rewritePrefix": ""
    },
    {
      "remark": "测试环境2",
      "prefix": "/division3",
      "upstream": "http://test.xxxxxx.cn/",
      "rewritePrefix": "/api/division"
    }
  ]
}

启动脚本


## 加载本地配置文件数据
go run proxy_agent.go -proxyFile ./proxy_data.json
## 启动从配置中心获取数据
go run proxy_agent.go -profile prod -adminUrl http://localhost:3000/proxy/findAll

到此这篇关于基于Go语言实现的简易api网关的示例代码的文章就介绍到这了,更多相关Go api网关 内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!


您可能感兴趣的文档:

--结束END--

本文标题: 基于Go语言实现的简易api网关的示例代码

本文链接: https://www.lsjlt.com/news/30739.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 基于Qt实现简易GIF播放器的示例代码
    目录一、项目介绍二、项目基本配置三、UI界面设计四、主程序实现4.1 mainwindow.h头文件4.2 mainwindow.cpp源文件五、效果演示一、项目介绍 利用Qt设计一...
    99+
    2024-04-02
  • 基于C语言实现关机小游戏的示例代码
    目录关机会写吧猜数字会写吧那么合起来实际效果关机会写吧 #include <stdlib.h> #include <string.h> #include &l...
    99+
    2024-04-02
  • C语言实现简易贪吃蛇游戏的示例代码
    目录前言一、构造小蛇二、小蛇的移动三、控制小蛇移动四、判断游戏失败五、吃食物增加长度六、完整代码前言 实现一个经典的小游戏——贪吃蛇,如图所示。读者可以先自己...
    99+
    2022-11-13
    C语言贪吃蛇游戏 C语言贪吃蛇 C语言 游戏
  • 基于C语言实现迷宫游戏的示例代码
    目录C语言迷宫游戏定义地图打印地图方法一打印地图方法二定义起点和终点位置实现读取按键实现小球下向下移动一步总结小球移动规律实现重新打印地图实现连续移动实现小球下向上下左右移动实现小球...
    99+
    2024-04-02
  • Go语言实现枚举的示例代码
    在编程领域里,枚举用来表示只包含有限数量的固定值的类型,在开发中一般用于标识错误码或者状态机。拿一个实体对象的状态机来说,它通常与这个对象在数据库里对应记录的标识状态的字段值相对应。...
    99+
    2024-04-02
  • 基于C语言实现高级通讯录的示例代码
    目录前言创建通讯录打印菜单初始化通讯录实现加载功能实现添加功能实现增容功能实现删除功能实现查询功能实现修改功能实现查询所有联系人功能实现排序功能实现清空功能实现保存功能实现退出功能通...
    99+
    2023-01-30
    C语言实现高级通讯录 C语言高级通讯录 C语言 通讯录
  • 基于C语言实现静态通讯录的示例代码
    目录一、项目要求二、Contact.h三、Contact.c1、静态函数2、初始化通讯录3、打印4、增加联系人信息5、通过名字查找6、删除联系人信息7、修改信息8、排序通讯录9、清空...
    99+
    2024-04-02
  • 基于C语言实现三子棋游戏的示例代码
    1.创建文件  test.c (游戏的测试逻辑)game.c(游戏的实现逻辑)gane.h(游戏实现函数的声明) game.c 和game.h属于游戏实现 test.c属于...
    99+
    2024-04-02
  • 基于C语言实现钻石棋游戏的示例代码
    目录游戏规则实现代码游戏规则 这是一个单人钻石棋游戏,游戏中有两种颜色的棋子:红色和绿色。每个玩家在游戏进行中轮流选择一个空格,并在该空格上放置自己的棋子。游戏的目的是尽可能地连成一...
    99+
    2023-02-26
    C语言实现钻石棋游戏 C语言钻石棋游戏 C语言钻石棋 C语言游戏
  • 基于C语言实现简易的扫雷游戏
    对于C语言学习者来说,在完成C语言初级学习之后,扫雷游戏是一个很好的知识的总结和练习。 扫雷即在一个棋盘中,随机放入一定数量的雷,玩家通过输入坐标,得到坐标上的信息(以此点为中心四周...
    99+
    2024-04-02
  • go语言实现全排列的示例代码
    目录思路:回溯过程:代码:思路: 首先画出全排列的树形结构,以123为例,一开始排列为空列表,第一个位置有三种可能,分别是1、2、3,画出三个分支;由于第一个位置已经被占用,那么第二...
    99+
    2023-03-07
    go语言全排列
  • Python实现简易凯撒密码的示例代码
    目录概念及原理实现过程破解原理及实现概念及原理 根据百度百科上的解释,凯撒密码是一种古老的加密算法。 密码的使用最早可以追溯到古罗马时期,《高卢战记》有描述恺撒曾经使用密码来传递信息...
    99+
    2024-04-02
  • C#实现简易画图板的示例代码
    编程环境 VS2019、C# 画板功能演示 实现简单画图 打开功能 可打开jpg格式的文件 保存功能 可将绘画的内容保存为jpg文件 颜色选择功能 用户可自由选择所需的颜色...
    99+
    2024-04-02
  • Qt实现简易计时器的示例代码
    目录一、项目介绍二、项目基本配置三、UI界面设计四、主程序实现4.1 mainwindow.h头文件4.2 mainwindow.cpp源文件五、效果演示一、项目介绍 计时器实现四个...
    99+
    2024-04-02
  • 基于C语言实现见缝插针游戏的示例代码
    目录游戏说明亮点期待效果图代码游戏说明 使用鼠标左键点击发射针,当两个针的夹角小于一定限制时,游戏结束。 亮点 这个游戏比较创新的地方就是可以用鼠标控制一个动态的过程,在循环中使用鼠...
    99+
    2022-11-13
    C语言 见缝插针游戏 C语言见缝插针 C语言 游戏
  • go语言实现屏幕截图的示例代码
    目录借助第三方库安装自定义截图 Capture全屏截图 CaptureDisplay获取活动显示器数量 NumActiveDisplays获取指定屏幕显示范围 GetDisplayB...
    99+
    2024-04-02
  • GO语言实现TCP服务器的示例代码
    interface/tcp/Handler.go type Handler interface { Handle(ctx context.Context, conn net.C...
    99+
    2023-03-24
    GO编写TCP服务器 GO TCP服务器 GO TCP
  • GO语言实现文件上传的示例代码
    目录前言文件上传表单操作服务端操作流程实现小结前言 最近在写一个文件上传的功能,现在来进行整理总结一下go语言如何上传文件的,本文主要分享一下golang实现文件上传的流程和具体代码...
    99+
    2024-04-02
  • Go语言实现Sm2加解密的示例代码
    在 Go 语言中,可以使用 github.com/tjfoc/gmsm/sm2 包来实现 SM2 加密和解密。 示例代码如下: package main import (     ...
    99+
    2023-03-19
    Go Sm2加解密 Go Sm2
  • 如何使用Go语言实现的api网关
    小编给大家分享一下如何使用Go语言实现的api网关,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!浏览器的请求去请求目标地址,然后获得结果它再发送给浏览器。对于Go语言来说,实现转发只需要简单的一行代码即可实现,如下所示:h...
    99+
    2023-06-21
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作