专栏首页飞雪无情的博客Golang Gin 实战(十四)| 文件托管、反向代理百度网站、自实现API网关

Golang Gin 实战(十四)| 文件托管、反向代理百度网站、自实现API网关

Golang Gin作为一个优秀的框架,不仅为我们提供了托管文件的能力,还为我们提供了从io.Reader,这篇文章除了介绍文件托管的使用和原理外,我们还会利用其托管io.Reader的能力,反向代理www.baidu.com网站,也就是说,我们在浏览器里访问http://localhost:8080/就可以看到百度的网站的内容了,就像百度的镜像一样。

通过这篇文章你可以学到(6000多字大章):

  1. 托管一个静态文件
  2. 托管一个目录
  3. 如何实现FTP服务器效果
  4. 自定义托管内容类型
  5. 托管一个Reader
  6. 静态文件托管原理分析
  7. Gin是如何禁止目录列表的
  8. 镜像百度网站
  9. 封装一个直接拿来用的镜像服务代理
  10. 多域名API服务聚合(API 网关?),解决CROS跨域问题

托管一个静态文件

在项目的开发中,你可能需要这么一个功能:把服务器上的JS文件暴露出来以供访问,比如让网站调用里面的JS函数等。对于这种情形,我们可以使用Gin提供的StaticFile方法很方便的完成。

func main() {
	router := gin.Default()
	router.StaticFile("/adobegc.log", "/tmp/adobegc.log")
	router.Run(":8080")
}

通过StaticFile方法,把文件/tmp/adobegc.log托管在网络上,并且设置访问路径为/adobegc.log,这样我们通过http://localhost:8080/adobegc.log就可以访问这个文件,看到它的内容了。

通过这种方式可以托管任何类型的文件,并且我们不用指定Content-Type,因为会自动识别。

现在我们又有一个需求,想托管很多静态文件,如果使用StaticFile方法一个个的设置会很繁琐,有没有更简单的方法呢?接着往下看。

托管一个目录

一般情况下,我们会把我们的静态文件放在一个目录中,比如我们使用Gin做网站开发的时候,可以把CSS、JS和Image这些静态资源文件都放在一个目录中,然后使用Static方法把整个目录托管,这样就可以自由访问这个目录中的所有文件了。

router.Static("/static", "/tmp")

只需要新增这样一行代码就可以实现,非常简单。Static方法的第一个参数是设置的相对路径,第二个参数是本机目录的绝对路径。

现在我们就可以通过http://localhost:8080/static/adobegc.log访问上一节里演示的那个adobegc.log的内容了,和直接访问http://localhost:8080/adobegc.log效果是一样的。

实现一个FTP服务器

上一节的例子,如果你在浏览器里访问http://localhost:8080/static/,你会得到404的错误,这是因为Gin做了安全措施,防止第三方恶意罗列获取你服务器上的所有文件。

但是你的需求正好是要搭建一个类似FTP的服务器,就是想把服务器上的文件件共享给其他人使用,比如下载电影等。这时候你就需要一个可以列出目录的功能了,也就是我们访问http://localhost:8080/static/可以看到/tmp/目录下的所有文件(包括文件夹),点击文件夹还可以展开看到里面的文件和文件夹,选择合适的文件进行下载,这样就是一个完整的FTP服务器了。

router.StaticFS("/static1", gin.Dir("/tmp", true))

这里我们用到了StaticFS方法,也是一行代码就可以搞定,为了和上个例子区分,我这里采用/static1作为相对路径。

这里的关键点在于gin.Dir函数的第二个参数,true代表可以列目录的意思。

// if listDirectory == true, then it works the same as http.Dir() otherwise it returns
// a filesystem that prevents http.FileServer() to list the directory files.
func Dir(root string, listDirectory bool) http.FileSystem 

现在我们启动访问http://localhost:8080/static1/就可以看到文件和文件夹列表了,和FTP服务器是类似的。

自定义托管内容类型

以上的示例都是托管一个静态文件或者目录,我们并没有太多的自定义能力,比如设置内容类型,托管一个文件的部分内容等等。

对于这类需求,Gin为我们提供了Data方法来实现,以第一节中的adobegc.log为例。

router.GET("/adobegc.log", func(c *gin.Context) {
	data, err := ioutil.ReadFile("/tmp/adobegc.log")
	if err != nil {
		c.AbortWithError(500, err)
	} else {
		c.Data(200, "text/plain; charset=utf-8", data)
	}
})

这个例子实现的效果和上面的是一样的,不一样的是我们通过c.Data这个方法来实现,这个方法有三个参数:

func (c *Context) Data(code int, contentType string, data []byte) 

这就为为我们自定义提供了便利,比如可以指定contentType和内容data,这种能力很有用,比如我们可以把我们储存在数据库中的图片二进制数据,作为一张图片显示在网站上。

功能更强大的Reader托管。

除了可以从一个字节数组[]byte中读取数据显示外,Gin还为我们提供了从一个io.Reader中获取数据,并且提供了更强大的自定义能力,它就是DataFromReader方法。

func (c *Context) DataFromReader(code int, contentLength int64, contentType string, reader io.Reader, extraHeaders map[string]string)

从上面的方法签名我们可以看到我们可以自定义的内容:

  1. 要显示的内容长度
  2. 内容的类型
  3. 一个内容源Reader
  4. 响应的头信息extraHeaders

尤其是自定义的头信息,可以让我们做很多事情,比如缓存等。这个方法的使用比较简单,和上面的Data方法差不多,这里不再举例,后面我们会通过镜像百度网站这个示例来演示它的使用

基于源代码分析原理

会使用和知道原理是两码事,面试的时候,面试官也喜欢问具体的源代码实现,这样才能更看出一个人的能力。接下来我们就基于源代码来分析静态文件是如何托管成文件服务的、Gin如果实现安全的防目录列表的;然后会通过Gin的这些能力,镜像一个百度的网站(反向代理),让你访问localhost:8080就可以访问百度网站;最后会提供一个封装好的类库(直接拿来用),可以非常方便的通过Gin反向代理任意服务,通过它你可以实现聚和多个域名上的API服务,可以解决浏览器跨域的问题。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Go语言经典库使用分析(四)| Gorilla Handlers 源代码实现分析

    上一篇 Go语言经典库使用分析(三)| Gorilla Handlers 详细介绍 中介绍了Handlers常用中间件的使用,这一篇介绍下这些中间件实现的原理...

    飞雪无情
  • Go语言经典库使用分析(七)| 高性能可扩展 HTTP 路由 httprouter

    Go语言(golang)的一个很大的优势,就是很容易的开发出网络后台服务,而且性能快,效率高。在开发后端HTTP网络应用服务的时候,我们需要处理很多HTTP的请...

    飞雪无情
  • Go语言中间件框架 Negroni 的静态文件处理源码分析

    Negroni是一个非常棒的中间件,尤其是其中间件调用链优雅的设计,以及对GO HTTP 原生处理器的兼容。我以前写过两篇文章,对Negroni进行了专门的分析...

    飞雪无情
  • 【AI 引擎】美国科学家利用DNA碎片创造纳米机器人 | Facebook 开放人工智能研究 | 日本电影让机器人演机器人

    1、美国科学家利用DNA碎片创造纳米机器人 ? 美国科学家团队创造了一个不同寻常的纳米级“机器人”。这种机器人是由DNA碎片装配而来的,它有一个“身体”和两个“...

    新智元
  • 借助开源项目,又好又快的实现视频文件”剧情连拍(剧情截图)”功能

    hbstream
  • Leetcode 91. Decode Ways 解码方法(动态规划,字符串处理)

    给一串包含数字的加密报文,求有多少种解码方式 举个例子,已知报文"12",它可以解码为AB(1 2),也可以是L (12) 所以解码方式有2种。

    racaljk
  • ajax中window.location.href不跳转

    $.ajax({ url: '/Ajax/System/ajaxcheshi.ashx', dataType:'text', // datatype: ...

    似水的流年
  • P1474 货币系统 Money Systems

    题目描述 母牛们不但创建了它们自己的政府而且选择了建立了自己的货币系统。由于它们特殊的思考方式,它们对货币的数值感到好奇。 传统地,一个货币系统是由1,5,10...

    attack
  • 真的!人工智能可以预测死亡时间

    使用人工智能来预测患者死亡的时间听起来像反乌托邦科幻电视剧“黑镜”中的一幕。但是斯坦福大学的研究人员认为,AI 的这个用途,可以给医生和病人及早地开始必要的临终...

    机器人网
  • javascript计算几天前,几小时前,几分钟前,几秒前

    本来没什么事,但看到有人用一大堆的 if-else 控制语句就有点火了,也不想想:用一个变量一次次除以虽然不同但有规律的数字,也不嫌累,纯粹一码农,没有任何脑子...

    挨踢小子部落阁

扫码关注云+社区

领取腾讯云代金券