dao.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. package dao
  2. import (
  3. "archive/tar"
  4. "bytes"
  5. "compress/gzip"
  6. "context"
  7. "crypto/md5"
  8. "encoding/hex"
  9. "errors"
  10. "fmt"
  11. "io"
  12. "io/ioutil"
  13. "net/http"
  14. "net/url"
  15. "os"
  16. "path"
  17. "strings"
  18. "time"
  19. "go-common/app/service/main/location/conf"
  20. "go-common/app/service/main/location/model"
  21. "go-common/library/cache/redis"
  22. "go-common/library/database/sql"
  23. "go-common/library/ecode"
  24. "go-common/library/log"
  25. httpx "go-common/library/net/http/blademaster"
  26. "go-common/library/net/metadata"
  27. )
  28. const (
  29. _anonym = "/app/geoip_download"
  30. _checkip = "/ipip/checkipipnetversion"
  31. )
  32. // Dao dao.
  33. type Dao struct {
  34. // mysql
  35. c *conf.Config
  36. db *sql.DB
  37. client *http.Client
  38. client2 *httpx.Client
  39. // redis
  40. redis *redis.Pool
  41. expire int32
  42. // host
  43. anonym string
  44. checkip string
  45. }
  46. // New new a dao.
  47. func New(c *conf.Config) (d *Dao) {
  48. d = &Dao{
  49. c: c,
  50. db: sql.NewMySQL(c.DB.Zlimit),
  51. redis: redis.NewPool(c.Redis.Zlimit.Config),
  52. expire: int32(time.Duration(c.Redis.Zlimit.Expire) / time.Second),
  53. client: &http.Client{
  54. Timeout: time.Second * 30,
  55. },
  56. anonym: c.Host.Maxmind + _anonym,
  57. checkip: c.Host.Bvcip + _checkip,
  58. client2: httpx.NewClient(c.HTTPClient),
  59. }
  60. return
  61. }
  62. // Ping ping a dao.
  63. func (d *Dao) Ping(c context.Context) (err error) {
  64. conn := d.redis.Get(c)
  65. _, err = conn.Do("SET", "PING", "PONG")
  66. conn.Close()
  67. return
  68. }
  69. // Close close a dao.
  70. func (d *Dao) Close() (err error) {
  71. if d.redis != nil {
  72. if err1 := d.redis.Close(); err1 != nil {
  73. err = err1
  74. }
  75. }
  76. if d.db != nil {
  77. if err1 := d.db.Close(); err1 != nil {
  78. err = err1
  79. }
  80. }
  81. return
  82. }
  83. // DownloadAnonym download anonym file.
  84. func (d *Dao) DownloadAnonym() (err error) {
  85. // get file
  86. var (
  87. req *http.Request
  88. resp *http.Response
  89. )
  90. params := url.Values{}
  91. params.Set("edition_id", "GeoIP2-Anonymous-IP")
  92. params.Set("date", "")
  93. params.Set("license_key", d.c.AnonymKey)
  94. params.Set("suffix", "tar.gz")
  95. enc := params.Encode()
  96. if req, err = http.NewRequest(http.MethodGet, d.anonym+"?"+enc, nil); err != nil {
  97. log.Error("http.NewRequest(%v) error(%v)", d.anonym+"?"+enc, err)
  98. return
  99. }
  100. if resp, err = d.client.Do(req); err != nil {
  101. log.Error("d.client.Do error(%v)", d.anonym+"?"+enc, err)
  102. return
  103. }
  104. if resp.StatusCode >= http.StatusBadRequest {
  105. err = errors.New(fmt.Sprintf("incorrect http status:%d host:%s, url:%s", resp.StatusCode, d.anonym, enc))
  106. log.Error("%v", err)
  107. return
  108. }
  109. defer resp.Body.Close()
  110. // get md5
  111. buf := new(bytes.Buffer)
  112. if _, err = io.Copy(buf, resp.Body); err != nil {
  113. log.Error("io.Copy error(%v)", err)
  114. return
  115. }
  116. var md5Str string
  117. md5Bs := md5.Sum(buf.Bytes())
  118. if md5Str, err = d.downloadAnonymMd5(); err != nil {
  119. log.Error("downloadAnonymMd5 error(%v)", err)
  120. return
  121. }
  122. if md5Str != hex.EncodeToString(md5Bs[:]) {
  123. err = errors.New("md5 not matched")
  124. return
  125. }
  126. var gr *gzip.Reader
  127. if gr, err = gzip.NewReader(buf); err != nil {
  128. log.Error("gzip.NewReader error(%v)", err)
  129. return
  130. }
  131. defer gr.Close()
  132. tr := tar.NewReader(gr)
  133. var hdr *tar.Header
  134. for {
  135. if hdr, err = tr.Next(); err != nil {
  136. if err == io.EOF {
  137. err = nil
  138. break
  139. } else {
  140. log.Error("DownloadAnonym error(%v)", err)
  141. return
  142. }
  143. }
  144. if strings.Index(hdr.Name, d.c.AnonymFileName) > -1 {
  145. var f *os.File
  146. downfile := path.Join(d.c.FilePath, d.c.AnonymFileName)
  147. if f, err = os.OpenFile(downfile, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0666); err != nil {
  148. log.Error(" os.OpenFile(%v) error(%v)", downfile, err)
  149. return
  150. }
  151. defer f.Close()
  152. if _, err = io.Copy(f, tr); err != nil {
  153. log.Error("io.Copy error(%v)", err)
  154. return
  155. }
  156. break
  157. }
  158. }
  159. return
  160. }
  161. // downloadAnonymMd5 get anonym file md5.
  162. func (d *Dao) downloadAnonymMd5() (md5 string, err error) {
  163. var (
  164. req *http.Request
  165. resp *http.Response
  166. body []byte
  167. )
  168. params := url.Values{}
  169. params.Set("edition_id", "GeoIP2-Anonymous-IP")
  170. params.Set("date", "")
  171. params.Set("license_key", d.c.AnonymKey)
  172. params.Set("suffix", "tar.gz.md5")
  173. enc := params.Encode()
  174. if req, err = http.NewRequest(http.MethodGet, d.anonym+"?"+enc, nil); err != nil {
  175. log.Error("DownloadAnonym http.NewRequest(%v) error(%v)", d.anonym+"?"+enc, err)
  176. return
  177. }
  178. if resp, err = d.client.Do(req); err != nil {
  179. log.Error("DownloadAnonym d.client.Do error(%v)", d.anonym+"?"+enc, err)
  180. return
  181. }
  182. if resp.StatusCode >= http.StatusBadRequest {
  183. err = errors.New(fmt.Sprintf("incorrect http status:%d host:%s, url:%s", resp.StatusCode, d.anonym, enc))
  184. log.Error("%v", err)
  185. return
  186. }
  187. defer resp.Body.Close()
  188. if body, err = ioutil.ReadAll(resp.Body); err != nil {
  189. log.Error("DownloadAnonymMd5 ioutil.ReadAll() error(%v)", err)
  190. return
  191. }
  192. md5 = string(body)
  193. return
  194. }
  195. func (d *Dao) CheckVersion(c context.Context) (version *model.Version, err error) {
  196. var (
  197. req *http.Request
  198. ip = metadata.String(c, metadata.RemoteIP)
  199. )
  200. if req, err = d.client2.NewRequest("GET", d.checkip, ip, nil); err != nil {
  201. log.Error("%v", err)
  202. return
  203. }
  204. var res struct {
  205. Code int `json:"code"`
  206. Msg string `json:"msg"`
  207. Data *model.Version `json:"data"`
  208. }
  209. if err = d.client2.Do(c, req, &res); err != nil {
  210. return
  211. }
  212. if res.Code != ecode.OK.Code() {
  213. err = errors.New(fmt.Sprintf("checkVersion falid err_code(%v)", res.Code))
  214. return
  215. }
  216. version = res.Data
  217. return
  218. }
  219. func (d *Dao) DownIPLibrary(c context.Context, version, file string) (err error) {
  220. var (
  221. req *http.Request
  222. resp *http.Response
  223. )
  224. if req, err = http.NewRequest(http.MethodGet, version, nil); err != nil {
  225. log.Error("http.NewRequest(%v) error(%v)", version, err)
  226. return
  227. }
  228. if resp, err = d.client.Do(req); err != nil {
  229. log.Error("d.client.Do error(%v)", version, err)
  230. return
  231. }
  232. if resp.StatusCode >= http.StatusBadRequest {
  233. err = errors.New(fmt.Sprintf("incorrect http status:%d url:%s", resp.StatusCode, version))
  234. log.Error("%v", err)
  235. return
  236. }
  237. defer resp.Body.Close()
  238. var f *os.File
  239. if f, err = os.OpenFile(file, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0666); err != nil {
  240. log.Error(" os.OpenFile(%v) error(%v)", file, err)
  241. return
  242. }
  243. defer f.Close()
  244. if _, err = io.Copy(f, resp.Body); err != nil {
  245. log.Error("io.Copy error(%v)", err)
  246. }
  247. return
  248. }