summaryrefslogtreecommitdiff
path: root/main.go
diff options
context:
space:
mode:
Diffstat (limited to 'main.go')
-rw-r--r--main.go93
1 files changed, 93 insertions, 0 deletions
diff --git a/main.go b/main.go
new file mode 100644
index 0000000..903abc4
--- /dev/null
+++ b/main.go
@@ -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)
+}