您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > Go语言

实现一个 Golang Module Proxy

时间:2019-09-02 14:17:55  来源:  作者:
实现一个 Golang Module Proxy

 

在前两篇文章(Golang 模块获取包modfetch研读,Golang模块代理goproxy.io源码研读),我们学习了Golang Module Proxy的工作原理以及实现原理。

本文尝试独立实现一个Golang Module Proxy服务。

实现逻辑主要涉及这几块内容:

a)main.go 负责服务启动,服务优雅终止;

b)generate.sh 负责将$GOROOT中的internal包拷贝至当前项目并替换引用路径;

c)proxy.go 核心逻辑部分,负责工作目录设定,路径检查,Module请求处理。

下面详细看一下这几部分的代码。

1 main.go

头部的//go:generate注释指定脚本generate.sh,当执行go generate时,其会调用generate.sh将modfetch包及其依赖包从$GOROOT中的internal文件夹拷贝至当前项目,然后即可以在当前项目直接使用了。

初始化一个http.Server,其Handler使用proxy.go的proxy.Proxy函数。

启动一个goroutine监听中断信号,以便优雅的终止服务(如何优雅的终止一个服务?)。

//go:generate sh generate.sh
package main
import (
 ...
 "github.com/olzhy/goproxy/pkg/proxy"
)
var port = flag.String("serverPort", ":8080", "server port")
func main() {
 // server
 srv := http.Server{
 Addr: *port,
 Handler: proxy.Proxy(),
 }
 // server startup / gracefully shutdown
 ...
 srv.ListenAndServe()
 ...
}

2 generate.sh

generate.sh负责将$GOROOT中的internal包拷贝至当前项目并将引用路径替换为新的引用路径。

#!/bin/bash
mkdir internal
# copy dependencies
cp -r $GOROOT/src/cmd/go/internal/modfetch ./internal/
...
cp -r $GOROOT/src/cmd/internal/sys ./internal/
...
# replace import paths
find . -type f -name "*.go" -exec sed -i '' 's#cmd/go/internal/#github.com/olzhy/goproxy/internal/#g' {} ; 
...

3 proxy.go

pkg/proxy/proxy.go提供proxy.Proxy函数。

proxy.go首先会设置工作目录,启动后对于一个GET请求,首先会校验请求路径,对不满足规则的请求直接返回404,然后仅对这几类符合Module请求格式的请求作处理:

a)后缀为“/@v/list”

如GET github.com/olzhy/quote/@v/list

从请求路径截取mod名称,调用modfetch.Lookup函数返回所有可用版本。

b)后缀为“/@latest”

如GET github.com/olzhy/quote/@latest

从请求路径截取mod名称,调用modfetch.Lookup函数获取最近一次提交信息。

c)后缀为“.info”

如GET github.com/olzhy/quote/@v/v1.0.0.info

从请求路径截取mod及version信息,调用modfetch.Stat函数获取info。

d)后缀为“.mod”

如GET github.com/olzhy/quote/@v/v1.0.0.mod

从请求路径截取mod及version信息,调用modfetch.GoMod函数获取mod内容。

e)后缀为“.zip”

如GET github.com/olzhy/quote/@v/v1.0.0.zip

从请求路径截取mod及version信息,调用modfetch.DownloadZip函数获取zip文件路径名称并提供下载。

package proxy
import (
 ...
 "github.com/olzhy/goproxy/internal/modfetch"
 ...
)
const (
 ListSuffix = "/@v/list"
 LatestSuffix = "/@latest"
 InfoSuffix = ".info"
 ModSuffix = ".mod"
 ZipSuffix = ".zip"
 VInfix = "/@v/"
)
func init() {
 modfetch.PkgMod = ...
 codehost.WorkRoot = ...
}
func Proxy() http.HandlerFunc {
 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 path := strings.Trim(r.RequestURI, "/")
 // req path validation
 if err := pathValidation(path); nil != err {
 w.WriteHeader(http.StatusBadRequest)
 fmt.Fprintln(w, err)
 return
 }
 switch {
 // suffix is /@v/list
 case strings.HasSuffix(path, ListSuffix):
 ...
 // call modfetch.Lookup(mod)
 lookupVersions(mod)
 ...
 return
 // suffix is /@latest
 case strings.HasSuffix(path, LatestSuffix):
	 ...
 // modfetch.Lookup(mod)
 lookupLatestRev(mod)
 ...
 return
 // suffix is .info
 case strings.HasSuffix(path, InfoSuffix):
 ...
 // call modfetch.Stat(mod, rev)
 loadRev(mod, ver)
 ...
	 return
 // suffix is .mod
 case strings.HasSuffix(path, ModSuffix):
 ...
 // call modfetch.GoMod(mod, rev)
	 loadModContent(mod, ver)
 ...
	 return
 // suffix is .zip
 case strings.HasSuffix(path, ZipSuffix):
 ...
 // call modfetch.DownloadZip(module.Version{Path: mod, Version: rev})
 loadZip(mod, ver)
 ...
	 return
 default:
	 w.WriteHeader(http.StatusBadRequest)
	 fmt.Fprintln(w, "please give me a correct module query")
 }
 })
}

完整实现代码已提交至GitHub(github.com/olzhy/goproxy),欢迎大家关注。

参考资料

[1] https://github.com/olzhy/goproxy

原文链接:https://leileiluoluo.com/posts/implement-a-golang-module-proxy.html

本文作者:磊磊落落的博客,原创授权发布



Tags:Golang   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
golang context 很好用,就使用php实现了github地址 : https://github.com/qq1060656096/php-go-context context使用闭坑指南1. 将一个Context参数作为第一个参数传递给传入和...【详细内容】
2021-11-05  Tags: Golang  点击:(41)  评论:(0)  加入收藏
简介工作中经常有定时执行某些代码块的需求,如果是PHP代码,一般写个脚本,然后用Cron实现。Go里提供了两种定时器:Timer(到达指定时间触发且只触发一次)和 Ticker(间隔特定时间触发)...【详细内容】
2021-05-10  Tags: Golang  点击:(310)  评论:(0)  加入收藏
不管你学没学过golang,都不妨碍这个21世纪的c语言正变得越来越流行,越来越多的平台服务使用golang来构建,我们熟知的docker就是采用golang语言进行开发设计的。谷歌作为golang...【详细内容】
2021-05-10  Tags: Golang  点击:(505)  评论:(0)  加入收藏
之前用 go 写一个小工具的时候, 用到了多个协程之间的通信, 当时随手查了查, 结果查出来一大坨, 简单记录一下. golang中多个协程之间是如何进行通信及数据同步的嘞.共享变...【详细内容】
2021-02-25  Tags: Golang  点击:(423)  评论:(0)  加入收藏
12月初,我们发现了一种新的用Golang编写的蠕虫。该蠕虫延续了 Golang在2020年流行的多平台恶意软件趋势。...【详细内容】
2021-01-05  Tags: Golang  点击:(175)  评论:(0)  加入收藏
本文主要研究一下golang的zap的ReflectType sweetenFieldszap@v1.16.0/sugar.gofunc (s *SugaredLogger) sweetenFields(args []interface{}) []Field { if len(args) ==...【详细内容】
2020-12-22  Tags: Golang  点击:(64)  评论:(0)  加入收藏
Golang的匿名结构是什么?匿名结构就像普通结构一样,但是它没有名称定义,因此不能在代码的其他地方引用。Go中的结构类似于C等其他语言中的结构。它们是字段的类型化集合,用于将...【详细内容】
2020-12-17  Tags: Golang  点击:(140)  评论:(0)  加入收藏
前文《理解 Paxos》只包含伪代码,帮助了理解但又不够爽,既然现在都讲究 Talk is cheap. Show me the code.这次就把文章中的伪代码用 Go 语言实现出来,希望能帮助各位朋友更直...【详细内容】
2020-12-15  Tags: Golang  点击:(116)  评论:(0)  加入收藏
今天逛github超市时,发现一个非常不错的数据可视化库go-echarts,特分享给大家。介绍在 Golang 这门语言中,目前数据可视化的第三方库还是特别少,go-echarts的开发就是为了填补这...【详细内容】
2020-12-15  Tags: Golang  点击:(88)  评论:(0)  加入收藏
由于Golang的语言设计的原因,不管是不是愿意,每个golang开发者的几乎每一段代码都需要与error做缠斗。下面我就简单分析一下golang中的error相关。...【详细内容】
2020-12-02  Tags: Golang  点击:(86)  评论:(0)  加入收藏
▌简易百科推荐
zip 是一种常见的归档格式,本文讲解 Go 如何操作 zip。首先看看 zip 文件是如何工作的。以一个小文件为例:(类 Unix 系统下)$ cat hello.textHello!执行 zip 命令进行归档:$ zip...【详细内容】
2021-12-17  Go语言中文网    Tags:Go语言   点击:(13)  评论:(0)  加入收藏
大家好,我是 polarisxu。前段时间,Russ Cox 明确了泛型相关的事情,原计划在标准库中加入泛型相关的包,改放到 golang.org/x/exp 下。目前,Go 泛型的主要设计者 ianlancetaylor 完...【详细内容】
2021-11-30  Go语言中文网    Tags:slices 包   点击:(24)  评论:(0)  加入收藏
前言最近因为项目需要写了一段时间的 Go ,相对于 Java 来说语法简单同时又有着一些 Python 之类的语法糖,让人大呼”真香“。 但现阶段相对来说还是 Python 写的多一些,偶尔还...【详细内容】
2021-11-25  crossoverJie    Tags:Go   点击:(29)  评论:(0)  加入收藏
go-micro是基于 Go 语言用于开发的微服务的 RPC 框架,主要功能如下:服务发现,负载均衡 ,消息编码,请求/响应,Async Messaging,可插拔接口,最后这个功能牛p安装步骤安装proto...【详细内容】
2021-09-06    石老师小跟班  Tags:go-micro   点击:(197)  评论:(0)  加入收藏
GoLand 2021.2 EAP 5 现已发布。用户可以从工具箱应用程序中获得 EAP 构建,也可以从官方网站手动下载。并且从此 EAP 开始,只有拥有有效的 JetBrains 帐户才能加入该计划。手...【详细内容】
2021-06-29  IT实战联盟  今日头条  Tags:GoLand   点击:(185)  评论:(0)  加入收藏
作者:HDT3213今天给大家带来的开源项目是 Godis:一个用 Go 语言实现的 Redis 服务器。支持: 5 种数据结构(string、list、hash、set、sortedset) 自动过期(TTL) 发布订阅、地理位...【详细内容】
2021-06-18  HelloGitHub  今日头条  Tags:Go   点击:(125)  评论:(0)  加入收藏
统一规范篇合理规划目录本篇主要描述了公司内部同事都必须遵守的一些开发规矩,如统一开发空间,既使用统一的开发工具来保证代码最后的格式的统一,开发中对文件和代码长度的控制...【详细内容】
2021-05-18  1024课堂    Tags:Go语言   点击:(232)  评论:(0)  加入收藏
闭包概述 闭包不是Go语言独有的概念,在很多编程语言中都有闭包 闭包就是解决局部变量不能被外部访问的一种解决方案 是把函数当作返回值的一种应用 代码演示总体思想:在函数...【详细内容】
2021-05-14  HelloGo  今日头条  Tags:Go语言   点击:(223)  评论:(0)  加入收藏
一时想不开,想了解一下Go语言,于是安装了并体验了一下。下载1. 进入golang.google.cn 点击Download Go 2.选择对应的操作系统,点击后开始下载。 安装1. windows下执行傻瓜式安...【详细内容】
2021-05-12  程序员fearlazy  fearlazy  Tags:Go语言   点击:(236)  评论:(0)  加入收藏
1.简介channel是Go语言的一大特性,基于channel有很多值得探讨的问题,如 channel为什么是并发安全的? 同步通道和异步通道有啥区别? 通道为何会阻塞协程? 使用通道导致阻塞的协程...【详细内容】
2021-05-10  程序员麻辣烫  今日头条  Tags:Go通道   点击:(274)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条