Skip to content

Commit 991068c

Browse files
committed
UPDATE: support for reading db from a file
1 parent 40eb017 commit 991068c

File tree

5 files changed

+79
-20
lines changed

5 files changed

+79
-20
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,6 @@ _site/
1010
.sass-cache/
1111
tmp/
1212
*.tmp
13+
top-1m.csv.zip
1314
vendor/
1415
.wrangler/

Dockerfile

+4-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
FROM golang:1.22-alpine as builder
33
RUN apk update && \
44
apk upgrade && \
5-
apk --no-cache add git upx ca-certificates
5+
apk --no-cache add git upx wget ca-certificates
66
RUN mkdir /build
7+
RUN wget https://tranco-list.eu/top-1m.csv.zip
8+
79
ADD . /build/
810
WORKDIR /build
911
ARG COMMIT
@@ -17,9 +19,9 @@ RUN \
1719
-o siterank \
1820
*.go \
1921
&& upx siterank
20-
2122
FROM scratch
2223
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
24+
COPY --from=builder /build/top-1m.csv.zip /app/
2325
COPY --from=builder /build/siterank /app/
2426
ENV PORT 4000
2527
ENTRYPOINT ["/app/siterank"]

rankings.go

+69-18
Original file line numberDiff line numberDiff line change
@@ -4,42 +4,93 @@ import (
44
"archive/zip"
55
"bufio"
66
"bytes"
7+
"fmt"
78
"io"
89
"net/http"
10+
"net/url"
911
"os"
1012
"strconv"
1113
"strings"
14+
"time"
1215
)
1316

1417
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+
}
1532

1633
func initRankings() error {
1734

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"
2238
}
2339

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
2945
}
30-
defer resp.Body.Close()
46+
logger.Debug("Parsed rankings URL", "url", urlStr, "parsed", url)
3147

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+
}
3384

34-
zipData, err := zip.NewReader(bytes.NewReader(body), resp.ContentLength)
85+
zipData, err := zip.NewReader(bytes.NewReader(body), int64(len(body)))
3586
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)
3788
return err
3889
}
3990

4091
zipFile, zipFileErr := zipData.File[0].Open()
4192
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)
4394
return zipFileErr
4495
}
4596

@@ -50,21 +101,21 @@ func initRankings() error {
50101
line := scanner.Text()
51102
parts := strings.Split(line, ",")
52103
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)
54105
continue
55106
}
56107
rank, err := strconv.Atoi(parts[0])
57108
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)
59110
continue
60111
}
61112
rankings[parts[1]] = rank
62113
}
63114
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)
65116
return err
66117
}
67-
logger.Info("Loaded rankings", "url", url, "count", len(rankings))
118+
logger.Info("Loaded rankings", "url", urlStr, "count", len(rankings))
68119

69120
return nil
70121
}

static/index.html

+3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ <h1>
1515
<p>
1616
API to retrieve the rank of a website in a given ranking list.
1717
</p>
18+
<p>
19+
Try it via the form at <a href="https://resolve.rs/domains/rank.html">resolve.rs</a>!
20+
</p>
1821
<p>
1922
<a href="https://github.com/redirect2me/siterank">How this works</a>, including API details and source code!
2023
</p>

statusHandler.go

+2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ type Status struct {
1616
Commit string `json:"commit"`
1717
LastMod string `json:"lastmod"`
1818
Tech string `json:"tech"`
19+
RankDate string `json:"rankings"`
1920
}
2021

2122
func statusHandler(w http.ResponseWriter, r *http.Request) {
@@ -27,6 +28,7 @@ func statusHandler(w http.ResponseWriter, r *http.Request) {
2728
status.Commit = COMMIT
2829
status.LastMod = LASTMOD
2930
status.Tech = runtime.Version()
31+
status.RankDate = rankDate
3032

3133
handleJson(w, r, status)
3234
}

0 commit comments

Comments
 (0)