实现一个 Golang Module Proxy

用户头像
北京/设计爱好者/4年前/46浏览
实现一个 Golang Module Proxy
用户头像
dasein58

实现一个 Golang Module Proxy

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

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

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

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

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

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

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

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

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

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

  //go:generate sh generate.sh

  package main

  import (

  ...

  "github/olzhy/goproxy/pkg/proxy"

  )

  var port=flag.String("serverPort", ":8080", "server port")

  func main() {

  // server

  srv :=http.Server{

  Addr: *port,

  Handler: proxyxy(),

  }

  // server startup / gracefully shutdown

  ...

  srv.ListenAndServe()

  ...

  }

  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/olzhy/goproxy/internal/#g' {} \;

  ...

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

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

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

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

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

  b)后缀为“/@latest”

  如GET github/olzhy/quote/@latest

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

  c)后缀为“”

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

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

  d)后缀为“.mod”

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

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

  e)后缀为“.zip”

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

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

  package proxy

  import (

  ...

  "github/olzhy/goproxy/internal/modfetch"

  ...

  )

  const (

  ListSuffix="/@v/list"

  LatestSuffix="/@latest"

  InfoSuffix=""

  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

  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")

  }

  })

  }




0
阅读原文
|
举报
|
收藏
分享
相关推荐
评论
用户头像
评论你的想法~
表情
喜欢TA的作品吗?喜欢就快来夸夸TA吧!
推荐素材
中国风书法汉字字体设计其他
卡通兔子插画
汉堡插画
木纹贴图设计师常用
新能源腊八节海报
中秋佳节花好月圆
乐陶创意体验工坊标志设计
小青龙IP吉祥物系列插画设计
炫光
苏门答腊虎母子插画
船坞民宿概方案
女生半身插画
红黑色简约现代风格|个人作品集排版简历模板
人物网球运动、棒球运动动态插画
彩灯_花灯_春节彩灯_春节花灯_马年彩灯_马年花灯
像素兵马俑怪物动画序列帧
 ps常用偷懒笔刷
国画水墨人物水墨画放牛娃画江南风景乡村墙绘素材
国画水墨江南山水画装饰画电视背景墙装饰画
二十四节气图片之霜降
浙江省区位分析图
头发1
我要奋斗
宠物纪念相册H5模板系列 · 温馨治愈系 · 三款主题
love玫瑰花
你可能喜欢
相关收藏夹
大家都在看
登录注册