Skip to content

Commit 94868b6

Browse files
committed
Inital project finished
1 parent 71cf685 commit 94868b6

File tree

11 files changed

+622
-15
lines changed

11 files changed

+622
-15
lines changed

.github/settings.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
repository:
2-
name: github-go
2+
name: http-downloader
33
description: This is a template project
44
homepage: https://github.com/linuxsuren
55
private: false

.github/workflows/backup.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@ jobs:
1515
uses: jenkins-zh/[email protected]
1616
env:
1717
GIT_DEPLOY_KEY: ${{ secrets.GIT_DEPLOY_KEY }}
18-
TARGET_GIT: "[email protected]:linuxsuren/github-go.git"
18+
TARGET_GIT: "[email protected]:linuxsuren/http-downloader.git"

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
.idea/
22
bin/
3+
4+
*/**/*.xml

.goreleaser.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
# Official documentation at http://goreleaser.com
2-
project_name: github-go
2+
project_name: http-downloader
33
builds:
44
- env:
55
- CGO_ENABLED=0
6-
binary: github-go
6+
binary: http-downloader
77
goarch:
88
- amd64
99
- arm64
@@ -46,28 +46,28 @@ changelog:
4646
- '^test:'
4747
brews:
4848
-
49-
name: github-go
49+
name: http-downloader
5050
tap:
5151
owner: linuxsuren
5252
name: homebrew-linuxsuren
5353
folder: Formula
54-
homepage: "https://github.com/linuxsuren/github-go"
54+
homepage: "https://github.com/linuxsuren/http-downloader"
5555
description: cgit is a tiny tool for Chinese developers.
5656
dependencies:
5757
- name: vim
5858
type: optional
5959
- name: bash-completion
6060
type: optional
6161
test: |
62-
version_output = shell_output("#{bin}/github-go version")
62+
version_output = shell_output("#{bin}/http-downloader version")
6363
assert_match version.to_s, version_output
6464
install: |
6565
bin.install name
6666
6767
prefix.install_metafiles
6868
nfpms:
6969
- file_name_template: "{{ .Binary }}-{{.Os}}-{{.Arch}}"
70-
homepage: https://github.com/linuxsuren/github-go
70+
homepage: https://github.com/linuxsuren/http-downloader
7171
description: cgit is a tiny tool for Chinese developers.
7272
maintainer: rick <[email protected]>
7373
license: MIT

README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
[![](https://goreportcard.com/badge/linuxsuren/github-go)](https://goreportcard.com/report/linuxsuren/github-go)
2-
[![](http://img.shields.io/badge/godoc-reference-5272B4.svg?style=flat-square)](https://godoc.org/github.com/linuxsuren/github-go)
3-
[![Contributors](https://img.shields.io/github/contributors/linuxsuren/github-go.svg)](https://github.com/linuxsuren/github-go/graphs/contributors)
4-
[![GitHub release](https://img.shields.io/github/release/linuxsuren/github-go.svg?label=release)](https://github.com/linuxsuren/github-go/releases/latest)
5-
![GitHub All Releases](https://img.shields.io/github/downloads/linuxsuren/github-go/total)
1+
[![](https://goreportcard.com/badge/linuxsuren/http-downloader)](https://goreportcard.com/report/linuxsuren/github-go)
2+
[![](http://img.shields.io/badge/godoc-reference-5272B4.svg?style=flat-square)](https://godoc.org/github.com/linuxsuren/http-downloader)
3+
[![Contributors](https://img.shields.io/github/contributors/linuxsuren/http-downloader.svg)](https://github.com/linuxsuren/github-go/graphs/contributors)
4+
[![GitHub release](https://img.shields.io/github/release/linuxsuren/http-downloader.svg?label=release)](https://github.com/linuxsuren/github-go/releases/latest)
5+
![GitHub All Releases](https://img.shields.io/github/downloads/linuxsuren/http-downloader/total)
66

77
# Get started
88

99
You can use this template repository via the following command:
1010

11-
`gh repo create --public -p linuxsuren/github-go -y <project-name>`
11+
`gh repo create --public -p linuxsuren/http-downloader -y <project-name>`
1212

1313
# Clean
1414

go.mod

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,11 @@ module github.com/linuxsuren/github-go
22

33
go 1.15
44

5-
require github.com/spf13/cobra v1.1.1
5+
require (
6+
github.com/golang/mock v1.4.4
7+
github.com/gosuri/uiprogress v0.0.1
8+
github.com/jenkins-zh/jenkins-cli v0.0.32
9+
github.com/onsi/ginkgo v1.14.2
10+
github.com/onsi/gomega v1.10.3
11+
github.com/spf13/cobra v1.1.1
12+
)

go.sum

Lines changed: 142 additions & 0 deletions
Large diffs are not rendered by default.

pkg/http.go

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
package pkg
2+
3+
import (
4+
"crypto/tls"
5+
"encoding/base64"
6+
"fmt"
7+
"io"
8+
"io/ioutil"
9+
"net/http"
10+
"net/url"
11+
"os"
12+
"path"
13+
"strconv"
14+
15+
"github.com/gosuri/uiprogress"
16+
)
17+
18+
const (
19+
// ContentType is for the http header of content type
20+
ContentType = "Content-Type"
21+
// ApplicationForm is for the form submit
22+
ApplicationForm = "application/x-www-form-urlencoded"
23+
)
24+
25+
// HTTPDownloader is the downloader for http request
26+
type HTTPDownloader struct {
27+
TargetFilePath string
28+
URL string
29+
ShowProgress bool
30+
InsecureSkipVerify bool
31+
32+
UserName string
33+
Password string
34+
35+
Proxy string
36+
ProxyAuth string
37+
38+
Debug bool
39+
RoundTripper http.RoundTripper
40+
}
41+
42+
// SetProxy set the proxy for a http
43+
func SetProxy(proxy, proxyAuth string, tr *http.Transport) (err error) {
44+
if proxy == "" {
45+
return
46+
}
47+
48+
var proxyURL *url.URL
49+
if proxyURL, err = url.Parse(proxy); err != nil {
50+
return
51+
}
52+
53+
tr.Proxy = http.ProxyURL(proxyURL)
54+
55+
if proxyAuth != "" {
56+
basicAuth := "Basic " + base64.StdEncoding.EncodeToString([]byte(proxyAuth))
57+
tr.ProxyConnectHeader = http.Header{}
58+
tr.ProxyConnectHeader.Add("Proxy-Authorization", basicAuth)
59+
}
60+
return
61+
}
62+
63+
func (h *HTTPDownloader) fetchProxyFromEnv(scheme string) {
64+
allProxy := os.Getenv("all_proxy")
65+
httpProxy := os.Getenv("http_proxy")
66+
httpsProxy := os.Getenv("https_proxy")
67+
68+
if allProxy != "" {
69+
h.Proxy = allProxy
70+
} else {
71+
switch scheme {
72+
case "http":
73+
if httpProxy != "" {
74+
h.Proxy = httpProxy
75+
}
76+
case "https":
77+
if httpsProxy != "" {
78+
h.Proxy = httpsProxy
79+
}
80+
}
81+
}
82+
}
83+
84+
// DownloadFile download a file with the progress
85+
func (h *HTTPDownloader) DownloadFile() error {
86+
filepath, downloadURL, showProgress := h.TargetFilePath, h.URL, h.ShowProgress
87+
// Get the data
88+
req, err := http.NewRequest(http.MethodGet, downloadURL, nil)
89+
if err != nil {
90+
return err
91+
}
92+
93+
if h.UserName != "" && h.Password != "" {
94+
req.SetBasicAuth(h.UserName, h.Password)
95+
}
96+
var tr http.RoundTripper
97+
if h.RoundTripper != nil {
98+
tr = h.RoundTripper
99+
} else {
100+
trp := &http.Transport{
101+
TLSClientConfig: &tls.Config{InsecureSkipVerify: h.InsecureSkipVerify},
102+
}
103+
h.fetchProxyFromEnv(req.URL.Scheme)
104+
if err = SetProxy(h.Proxy, h.ProxyAuth, trp); err != nil {
105+
return err
106+
}
107+
108+
if h.Proxy != "" {
109+
basicAuth := "Basic " + base64.StdEncoding.EncodeToString([]byte(h.ProxyAuth))
110+
req.Header.Add("Proxy-Authorization", basicAuth)
111+
}
112+
tr = trp
113+
}
114+
client := &http.Client{Transport: tr}
115+
var resp *http.Response
116+
117+
if resp, err = client.Do(req); err != nil {
118+
return err
119+
}
120+
121+
if resp.StatusCode != 200 {
122+
if h.Debug {
123+
if data, err := ioutil.ReadAll(resp.Body); err == nil {
124+
ioutil.WriteFile("debug-download.html", data, 0664)
125+
}
126+
}
127+
return fmt.Errorf("invalidate status code: %d", resp.StatusCode)
128+
}
129+
130+
writer := &ProgressIndicator{
131+
Title: "Downloading",
132+
}
133+
if showProgress {
134+
if total, ok := resp.Header["Content-Length"]; ok && len(total) > 0 {
135+
fileLength, err := strconv.ParseInt(total[0], 10, 64)
136+
if err == nil {
137+
writer.Total = float64(fileLength)
138+
}
139+
}
140+
}
141+
142+
if err := os.MkdirAll(path.Dir(filepath), os.FileMode(0755)); err != nil {
143+
return err
144+
}
145+
146+
// Create the file
147+
out, err := os.Create(filepath)
148+
if err != nil {
149+
return err
150+
}
151+
defer out.Close()
152+
153+
writer.Writer = out
154+
155+
if showProgress {
156+
writer.Init()
157+
}
158+
159+
// Write the body to file
160+
_, err = io.Copy(writer, resp.Body)
161+
return err
162+
}
163+
164+
// ProgressIndicator hold the progress of io operation
165+
type ProgressIndicator struct {
166+
Writer io.Writer
167+
Reader io.Reader
168+
Title string
169+
170+
// bytes.Buffer
171+
Total float64
172+
count float64
173+
bar *uiprogress.Bar
174+
}
175+
176+
// Init set the default value for progress indicator
177+
func (i *ProgressIndicator) Init() {
178+
uiprogress.Start() // start rendering
179+
i.bar = uiprogress.AddBar(100) // Add a new bar
180+
181+
// optionally, append and prepend completion and elapsed time
182+
i.bar.AppendCompleted()
183+
// i.bar.PrependElapsed()
184+
185+
if i.Title != "" {
186+
i.bar.PrependFunc(func(_ *uiprogress.Bar) string {
187+
return fmt.Sprintf("%s: ", i.Title)
188+
})
189+
}
190+
}
191+
192+
// Write writes the progress
193+
func (i *ProgressIndicator) Write(p []byte) (n int, err error) {
194+
n, err = i.Writer.Write(p)
195+
i.setBar(n)
196+
return
197+
}
198+
199+
// Read reads the progress
200+
func (i *ProgressIndicator) Read(p []byte) (n int, err error) {
201+
n, err = i.Reader.Read(p)
202+
i.setBar(n)
203+
return
204+
}
205+
206+
func (i *ProgressIndicator) setBar(n int) {
207+
i.count += float64(n)
208+
209+
if i.bar != nil {
210+
i.bar.Set((int)(i.count * 100 / i.Total))
211+
}
212+
}

0 commit comments

Comments
 (0)