From ddf2aefa09e81f0efd1dfcd3c10615ab55c6920d Mon Sep 17 00:00:00 2001 From: Feuerfuchs Date: Sat, 16 Nov 2019 01:39:33 +0100 Subject: Fixed some issues with Gemini --- gopherproxy.go | 114 ++++++++++++++++++++++++++++++++++++--------------------- libgemini.go | 2 +- template.go | 3 ++ 3 files changed, 76 insertions(+), 43 deletions(-) diff --git a/gopherproxy.go b/gopherproxy.go index 9a60507..ab8e906 100644 --- a/gopherproxy.go +++ b/gopherproxy.go @@ -46,6 +46,31 @@ type AssetList struct { PropFontW2 string } +func resolveURI(uri string, baseUrl *url.URL) (resolvedUri string) { + if strings.HasPrefix(uri, "//") { + resolvedUri = "/gemini/" + strings.TrimPrefix(uri, "//") + } else if strings.HasPrefix(uri, "gemini://") { + resolvedUri = "/gemini/" + strings.TrimPrefix(uri, "gemini://") + } else if strings.HasPrefix(uri, "gopher://") { + resolvedUri = "/gopher/" + strings.TrimPrefix(uri, "gopher://") + } else { + url, err := url.Parse(uri) + if err != nil { + return "" + } + adjustedUrl := baseUrl.ResolveReference(url) + if adjustedUrl.Scheme == "gemini" { + resolvedUri = "/gemini/" + adjustedUrl.Host + adjustedUrl.Path + } else if adjustedUrl.Scheme == "gopher" { + resolvedUri = "/gopher/" + adjustedUrl.Host + adjustedUrl.Path + } else { + resolvedUri = adjustedUrl.String() + } + } + + return +} + func renderGopherDirectory(w http.ResponseWriter, tpl *template.Template, assetList AssetList, uri string, hostport string, d gopher.Directory) error { var title string @@ -109,9 +134,6 @@ func renderGopherDirectory(w http.ResponseWriter, tpl *template.Template, assetL } func parseGeminiDocument(response *GeminiResponse, uri string, hostport string) (items []Item) { - scanner := bufio.NewScanner(response.Body) - scanner.Split(bufio.ScanLines) - baseUrl, err := url.Parse(fmt.Sprintf( "gemini://%s/%s", hostport, @@ -121,6 +143,9 @@ func parseGeminiDocument(response *GeminiResponse, uri string, hostport string) return []Item{} } + scanner := bufio.NewScanner(response.Body) + scanner.Split(bufio.ScanLines) + for scanner.Scan() { line := strings.Trim(scanner.Text(), "\r\n") @@ -131,34 +156,10 @@ func parseGeminiDocument(response *GeminiResponse, uri string, hostport string) linkMatch := GeminiLinkPattern.FindStringSubmatch(line) if len(linkMatch) != 0 && linkMatch[0] != "" { - link := linkMatch[1] - - if strings.HasPrefix(link, "//") { - link = "/gemini/" + strings.TrimPrefix(link, "//") - } else if strings.HasPrefix(link, "gemini://") { - link = "/gemini/" + strings.TrimPrefix(link, "gemini://") - } else if strings.HasPrefix(link, "gopher://") { - link = "/gopher/" + strings.TrimPrefix(link, "gopher://") - } else { - linkUrl, err := url.Parse(link) - if err != nil { - continue - } - adjustedUrl := baseUrl.ResolveReference(linkUrl) - if adjustedUrl.Scheme == "gemini" { - link = "/gemini/" + adjustedUrl.Host + adjustedUrl.Path - } else if adjustedUrl.Scheme == "gopher" { - link = "/gopher/" + adjustedUrl.Host + adjustedUrl.Path - } else { - link = adjustedUrl.String() - } - } - item.Type = ITEM_TYPE_GEMINI_LINK - item.Link = template.URL(link) - if linkMatch[2] != "" { - item.Text = linkMatch[2] - } else { + item.Link = template.URL(resolveURI(linkMatch[1], baseUrl)) + item.Text = linkMatch[2] + if item.Text == "" { item.Text = linkMatch[1] } } @@ -342,6 +343,29 @@ func GeminiHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass return } + if int(res.Header.Status/10) == 3 { + baseUrl, err := url.Parse(fmt.Sprintf( + "gemini://%s/%s", + hostport, + uri, + )) + if err != nil { + tpl.Execute(w, struct { + Title string + URI string + Assets AssetList + RawText string + Lines []Item + Error bool + Protocol string + }{uri, fmt.Sprintf("%s/%s", hostport, uri), assetList, fmt.Sprintf("Error: %s", err), nil, true, "gemini"}) + return + } + + http.Redirect(w, req, resolveURI(res.Header.Meta, baseUrl), http.StatusFound) + return + } + if int(res.Header.Status/10) != 2 { tpl.Execute(w, struct { Title string @@ -355,18 +379,24 @@ func GeminiHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass return } - if strings.HasPrefix(res.Header.Meta, MIME_GEMINI) { - items := parseGeminiDocument(res, uri, hostport) - tpl.Execute(w, struct { - Title string - URI string - Assets AssetList - RawText string - Lines []Item - Error bool - Protocol string - }{uri, fmt.Sprintf("%s/%s", hostport, uri), assetList, "", items, false, "gemini"}) - } else if strings.HasPrefix(res.Header.Meta, "text/") { + if strings.HasPrefix(res.Header.Meta, "text/") { + // TODO: Handle encoding + // https://stackoverflow.com/questions/32518432/how-to-convert-from-an-encoding-to-utf-8-in-go + + if strings.HasPrefix(res.Header.Meta, MIME_GEMINI) { + items := parseGeminiDocument(res, uri, hostport) + tpl.Execute(w, struct { + Title string + URI string + Assets AssetList + RawText string + Lines []Item + Error bool + Protocol string + }{uri, fmt.Sprintf("%s/%s", hostport, uri), assetList, "", items, false, "gemini"}) + return + } + buf := new(bytes.Buffer) buf.ReadFrom(res.Body) tpl.Execute(w, struct { diff --git a/libgemini.go b/libgemini.go index 05321ef..56e1463 100644 --- a/libgemini.go +++ b/libgemini.go @@ -49,7 +49,7 @@ var ( HeaderPattern = regexp.MustCompile("^(\\d\\d)[ \\t]+(.*)$") MimeTypePattern = regexp.MustCompile("^[-\\w.]+/[-\\w.]+") MimeCharsetPattern = regexp.MustCompile("charset=([^ ;]+)") - GeminiLinkPattern = regexp.MustCompile("^=>[ \\t]*([^ ]+)(?:[ \\t]+(.*))?$") + GeminiLinkPattern = regexp.MustCompile("^=>[ \\t]*([^ \\t]+)(?:[ \\t]+(.*))?$") ) type GeminiHeader struct { diff --git a/template.go b/template.go index b7d1b1f..6a9c6fe 100644 --- a/template.go +++ b/template.go @@ -58,6 +58,9 @@ var tpltext = ` {{- if ne (len $uriParts) 0 -}} / {{- end -}} + {{- if and (eq $page.Protocol "gopher") (eq (len $uriParts) 1) -}} + {{- $uriLast = $uriLast | trimLeftChar -}} + {{- end -}} {{ $uriLast }}
-- cgit v1.2.3-70-g09d2