diff options
author | haturatu <taro@eyes4you.org> | 2024-12-04 17:10:51 +0900 |
---|---|---|
committer | haturatu <taro@eyes4you.org> | 2024-12-04 17:10:51 +0900 |
commit | c6deec6e6452b591ecb729bfd5b4ec0a1822c640 (patch) | |
tree | a2ebf18997d18a13cc779693a0ceae1f99e2a00b |
first commit
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | README.md | 42 | ||||
-rw-r--r-- | go.mod | 5 | ||||
-rw-r--r-- | go.sum | 2 | ||||
-rw-r--r-- | main.go | 93 |
5 files changed, 143 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9ecece9 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +ght diff --git a/README.md b/README.md new file mode 100644 index 0000000..c712269 --- /dev/null +++ b/README.md @@ -0,0 +1,42 @@ +# ght +go-http-get + +## Build +Please check if the Go path is running. +```bash +which go +``` + +And then compile. +```bash +go build -o ght main.go +``` +Move the executable binary to `/usr/local/bin` to work with CLI. +```bash +sudo mv ght /usr/local/bin +sudo chown root:root /usr/local/bin/ght +which ght +``` + +## Usage +URL in `$1`. +```bash +$ ght +Usage: ght "https://google.com/" +``` + +### for example +If you have a file called `urls` with URLs listed. +```bash:urls +https://www.google.com/ +https://soulminingrig.com/ +https://soulminingrig.com/ab/ +``` +Single proccessing +```bash +cat urls | while read -r url ; do ght $url ; done +``` +Parallel processing with `xargs` +```bash +cat urls | xargs -P 4 -I {} ght {} +``` @@ -0,0 +1,5 @@ +module ght + +go 1.23.3 + +require golang.org/x/net v0.31.0 @@ -0,0 +1,2 @@ +golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= +golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= @@ -0,0 +1,93 @@ +package main + +import ( + "crypto/tls" + "fmt" + "net/http" + "os" + "time" + + "golang.org/x/net/html" +) + +func findTitleTag(n *html.Node) string { + if n.Type == html.ElementNode && n.Data == "title" { + if n.FirstChild != nil { + return n.FirstChild.Data + } + } + for c := n.FirstChild; c != nil; c = c.NextSibling { + if result := findTitleTag(c); result != "" { + return result + } + } + return "" +} + +func fetchAndParse(client *http.Client, url string, useRange bool) (string, error) { + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return "", fmt.Errorf("failed to create request: %w", err) + } + if useRange { + req.Header.Set("Range", "bytes=0-4096") + } + + resp, err := client.Do(req) + if err != nil { + return "", fmt.Errorf("failed to fetch URL: %w", err) + } + defer resp.Body.Close() + + doc, err := html.Parse(resp.Body) + if err != nil { + return "", fmt.Errorf("failed to parse HTML: %w", err) + } + + return findTitleTag(doc), nil +} + +func fetchTitle(url string) (string, error) { + client := &http.Client{ + Timeout: 5 * time.Second, + Transport: &http.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + }, + } + + // range limit : get request + title, err := fetchAndParse(client, url, true) + if err != nil { + return "", err + } + if title != "" { + return title, nil + } + + // no range limit : get reqest + title, err = fetchAndParse(client, url, false) + if err != nil { + return "", err + } + if title == "" { + return "", fmt.Errorf("no title found: %s", url) + } + + return title, nil +} + +func main() { + if len(os.Args) < 2 { + fmt.Fprintln(os.Stderr, "Usage: ght \"https://google.com/\"") + os.Exit(1) + } + + url := os.Args[1] + title, err := fetchTitle(url) + if err != nil { + fmt.Fprintf(os.Stderr, "Error: %v\n", err) + os.Exit(2) + } + + fmt.Printf("%s\n", title) +} |