@@ -4,42 +4,93 @@ import (
4
4
"archive/zip"
5
5
"bufio"
6
6
"bytes"
7
+ "fmt"
7
8
"io"
8
9
"net/http"
10
+ "net/url"
9
11
"os"
10
12
"strconv"
11
13
"strings"
14
+ "time"
12
15
)
13
16
14
17
var rankings map [string ]int = make (map [string ]int )
18
+ var rankDate string
19
+
20
+ func getLastModified (resp * http.Response ) time.Time {
21
+ lastModified , lmErr := http .ParseTime (resp .Header .Get ("Last-Modified" ))
22
+ if lmErr == nil {
23
+ return lastModified
24
+ }
25
+ dateFromHeader , dateErr := time .Parse ("2006-01-02 15:04:05" , resp .Header .Get ("Date" ))
26
+ if dateErr == nil {
27
+ return dateFromHeader
28
+ }
29
+
30
+ return time .Now ()
31
+ }
15
32
16
33
func initRankings () error {
17
34
18
- url := os .Getenv ("URL" )
19
- if url == "" {
20
- url = "https://tranco-list.eu/top-1m.csv.zip"
21
- //"https://s3.amazonaws.com/alexa-static/top-1m.csv.zip"
35
+ urlStr := os .Getenv ("URL" )
36
+ if urlStr == "" {
37
+ urlStr = "file:top-1m.csv.zip"
22
38
}
23
39
24
- logger .Info ("Downloading rankings" , "url" , url )
25
- resp , err := http . Get ( url )
26
- if err != nil {
27
- logger .Error ("Failed to download rankings " , "error" , err , "url" , url )
28
- return err
40
+ logger .Info ("Loading rankings" , "url" , urlStr )
41
+ url , urlErr := url . Parse ( urlStr )
42
+ if urlErr != nil {
43
+ logger .Error ("Invalid URL " , "error" , urlErr , "url" , urlStr )
44
+ return urlErr
29
45
}
30
- defer resp . Body . Close ( )
46
+ logger . Debug ( "Parsed rankings URL" , "url" , urlStr , "parsed" , url )
31
47
32
- body , err := io .ReadAll (resp .Body )
48
+ var body []byte
49
+ var readErr error
50
+ if url .Scheme == "file" {
51
+ var filePath string
52
+ if url .Path == "" {
53
+ filePath = url .Opaque
54
+ } else {
55
+ filePath = url .Path
56
+ }
57
+ stats , statErr := os .Stat (filePath )
58
+ if statErr != nil {
59
+ logger .Error ("Failed to stat rankings file" , "error" , statErr , "url" , urlStr , "path" , filePath )
60
+ return statErr
61
+ }
62
+ rankDate = stats .ModTime ().Format ("2006-01-02 15:04:05" )
63
+ body , readErr = os .ReadFile (filePath )
64
+ } else if url .Scheme == "http" || url .Scheme == "https" {
65
+ resp , err := http .Get (urlStr )
66
+ if err != nil {
67
+ logger .Error ("Failed to download rankings" , "error" , err , "url" , urlStr )
68
+ return err
69
+ }
70
+ defer resp .Body .Close ()
71
+
72
+ rankDate = getLastModified (resp ).Format ("2006-01-02 15:04:05" )
73
+ body , readErr = io .ReadAll (resp .Body )
74
+
75
+ logger .Info ("Downloaded rankings" , "url" , urlStr , "size" , len (body ), "contentLength" , resp .ContentLength )
76
+ } else {
77
+ logger .Error ("Unsupported URL scheme" , "scheme" , url .Scheme , "url" , urlStr )
78
+ return fmt .Errorf ("unsupported URL scheme %s" , url .Scheme )
79
+ }
80
+ if readErr != nil {
81
+ logger .Error ("Failed to read rankings" , "error" , readErr , "url" , urlStr )
82
+ return readErr
83
+ }
33
84
34
- zipData , err := zip .NewReader (bytes .NewReader (body ), resp . ContentLength )
85
+ zipData , err := zip .NewReader (bytes .NewReader (body ), int64 ( len ( body )) )
35
86
if err != nil {
36
- logger .Error ("Failed to read zip file" , "error" , err , "url" , url )
87
+ logger .Error ("Failed to read zip file" , "error" , err , "url" , urlStr )
37
88
return err
38
89
}
39
90
40
91
zipFile , zipFileErr := zipData .File [0 ].Open ()
41
92
if zipFileErr != nil {
42
- logger .Error ("Failed to open file from zip" , "error" , zipFileErr , "url" , url )
93
+ logger .Error ("Failed to open file from zip" , "error" , zipFileErr , "url" , urlStr )
43
94
return zipFileErr
44
95
}
45
96
@@ -50,21 +101,21 @@ func initRankings() error {
50
101
line := scanner .Text ()
51
102
parts := strings .Split (line , "," )
52
103
if len (parts ) != 2 {
53
- logger .Error ("Invalid ranking line" , "line" , line , "lineNumber" , lineNo , "url" , url )
104
+ logger .Error ("Invalid ranking line" , "line" , line , "lineNumber" , lineNo , "url" , urlStr )
54
105
continue
55
106
}
56
107
rank , err := strconv .Atoi (parts [0 ])
57
108
if err != nil {
58
- logger .Error ("Invalid ranking rank" , "line" , line , "lineNumber" , lineNo , "url" , url )
109
+ logger .Error ("Invalid ranking rank" , "line" , line , "lineNumber" , lineNo , "url" , urlStr )
59
110
continue
60
111
}
61
112
rankings [parts [1 ]] = rank
62
113
}
63
114
if err := scanner .Err (); err != nil {
64
- logger .Error ("Failed to scan zip file" , "error" , err , "url" , url )
115
+ logger .Error ("Failed to scan zip file" , "error" , err , "url" , urlStr )
65
116
return err
66
117
}
67
- logger .Info ("Loaded rankings" , "url" , url , "count" , len (rankings ))
118
+ logger .Info ("Loaded rankings" , "url" , urlStr , "count" , len (rankings ))
68
119
69
120
return nil
70
121
}
0 commit comments