diff options
author | Feuerfuchs <git@feuerfuchs.dev> | 2019-11-16 01:39:33 +0100 |
---|---|---|
committer | Feuerfuchs <git@feuerfuchs.dev> | 2019-11-16 01:39:33 +0100 |
commit | ddf2aefa09e81f0efd1dfcd3c10615ab55c6920d (patch) | |
tree | b0403855e643c4b5bd9d00f56c10ccd9af7c5361 | |
parent | Initial Gemini support (diff) | |
download | gopherproxy-ddf2aefa09e81f0efd1dfcd3c10615ab55c6920d.tar.gz gopherproxy-ddf2aefa09e81f0efd1dfcd3c10615ab55c6920d.tar.bz2 gopherproxy-ddf2aefa09e81f0efd1dfcd3c10615ab55c6920d.zip |
Fixed some issues with Gemini
-rw-r--r-- | gopherproxy.go | 114 | ||||
-rw-r--r-- | libgemini.go | 2 | ||||
-rw-r--r-- | 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 { | |||
46 | PropFontW2 string | 46 | PropFontW2 string |
47 | } | 47 | } |
48 | 48 | ||
49 | func resolveURI(uri string, baseUrl *url.URL) (resolvedUri string) { | ||
50 | if strings.HasPrefix(uri, "//") { | ||
51 | resolvedUri = "/gemini/" + strings.TrimPrefix(uri, "//") | ||
52 | } else if strings.HasPrefix(uri, "gemini://") { | ||
53 | resolvedUri = "/gemini/" + strings.TrimPrefix(uri, "gemini://") | ||
54 | } else if strings.HasPrefix(uri, "gopher://") { | ||
55 | resolvedUri = "/gopher/" + strings.TrimPrefix(uri, "gopher://") | ||
56 | } else { | ||
57 | url, err := url.Parse(uri) | ||
58 | if err != nil { | ||
59 | return "" | ||
60 | } | ||
61 | adjustedUrl := baseUrl.ResolveReference(url) | ||
62 | if adjustedUrl.Scheme == "gemini" { | ||
63 | resolvedUri = "/gemini/" + adjustedUrl.Host + adjustedUrl.Path | ||
64 | } else if adjustedUrl.Scheme == "gopher" { | ||
65 | resolvedUri = "/gopher/" + adjustedUrl.Host + adjustedUrl.Path | ||
66 | } else { | ||
67 | resolvedUri = adjustedUrl.String() | ||
68 | } | ||
69 | } | ||
70 | |||
71 | return | ||
72 | } | ||
73 | |||
49 | func renderGopherDirectory(w http.ResponseWriter, tpl *template.Template, assetList AssetList, uri string, hostport string, d gopher.Directory) error { | 74 | func renderGopherDirectory(w http.ResponseWriter, tpl *template.Template, assetList AssetList, uri string, hostport string, d gopher.Directory) error { |
50 | var title string | 75 | var title string |
51 | 76 | ||
@@ -109,9 +134,6 @@ func renderGopherDirectory(w http.ResponseWriter, tpl *template.Template, assetL | |||
109 | } | 134 | } |
110 | 135 | ||
111 | func parseGeminiDocument(response *GeminiResponse, uri string, hostport string) (items []Item) { | 136 | func parseGeminiDocument(response *GeminiResponse, uri string, hostport string) (items []Item) { |
112 | scanner := bufio.NewScanner(response.Body) | ||
113 | scanner.Split(bufio.ScanLines) | ||
114 | |||
115 | baseUrl, err := url.Parse(fmt.Sprintf( | 137 | baseUrl, err := url.Parse(fmt.Sprintf( |
116 | "gemini://%s/%s", | 138 | "gemini://%s/%s", |
117 | hostport, | 139 | hostport, |
@@ -121,6 +143,9 @@ func parseGeminiDocument(response *GeminiResponse, uri string, hostport string) | |||
121 | return []Item{} | 143 | return []Item{} |
122 | } | 144 | } |
123 | 145 | ||
146 | scanner := bufio.NewScanner(response.Body) | ||
147 | scanner.Split(bufio.ScanLines) | ||
148 | |||
124 | for scanner.Scan() { | 149 | for scanner.Scan() { |
125 | line := strings.Trim(scanner.Text(), "\r\n") | 150 | line := strings.Trim(scanner.Text(), "\r\n") |
126 | 151 | ||
@@ -131,34 +156,10 @@ func parseGeminiDocument(response *GeminiResponse, uri string, hostport string) | |||
131 | 156 | ||
132 | linkMatch := GeminiLinkPattern.FindStringSubmatch(line) | 157 | linkMatch := GeminiLinkPattern.FindStringSubmatch(line) |
133 | if len(linkMatch) != 0 && linkMatch[0] != "" { | 158 | if len(linkMatch) != 0 && linkMatch[0] != "" { |
134 | link := linkMatch[1] | ||
135 | |||
136 | if strings.HasPrefix(link, "//") { | ||
137 | link = "/gemini/" + strings.TrimPrefix(link, "//") | ||
138 | } else if strings.HasPrefix(link, "gemini://") { | ||
139 | link = "/gemini/" + strings.TrimPrefix(link, "gemini://") | ||
140 | } else if strings.HasPrefix(link, "gopher://") { | ||
141 | link = "/gopher/" + strings.TrimPrefix(link, "gopher://") | ||
142 | } else { | ||
143 | linkUrl, err := url.Parse(link) | ||
144 | if err != nil { | ||
145 | continue | ||
146 | } | ||
147 | adjustedUrl := baseUrl.ResolveReference(linkUrl) | ||
148 | if adjustedUrl.Scheme == "gemini" { | ||
149 | link = "/gemini/" + adjustedUrl.Host + adjustedUrl.Path | ||
150 | } else if adjustedUrl.Scheme == "gopher" { | ||
151 | link = "/gopher/" + adjustedUrl.Host + adjustedUrl.Path | ||
152 | } else { | ||
153 | link = adjustedUrl.String() | ||
154 | } | ||
155 | } | ||
156 | |||
157 | item.Type = ITEM_TYPE_GEMINI_LINK | 159 | item.Type = ITEM_TYPE_GEMINI_LINK |
158 | item.Link = template.URL(link) | 160 | item.Link = template.URL(resolveURI(linkMatch[1], baseUrl)) |
159 | if linkMatch[2] != "" { | 161 | item.Text = linkMatch[2] |
160 | item.Text = linkMatch[2] | 162 | if item.Text == "" { |
161 | } else { | ||
162 | item.Text = linkMatch[1] | 163 | item.Text = linkMatch[1] |
163 | } | 164 | } |
164 | } | 165 | } |
@@ -342,6 +343,29 @@ func GeminiHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
342 | return | 343 | return |
343 | } | 344 | } |
344 | 345 | ||
346 | if int(res.Header.Status/10) == 3 { | ||
347 | baseUrl, err := url.Parse(fmt.Sprintf( | ||
348 | "gemini://%s/%s", | ||
349 | hostport, | ||
350 | uri, | ||
351 | )) | ||
352 | if err != nil { | ||
353 | tpl.Execute(w, struct { | ||
354 | Title string | ||
355 | URI string | ||
356 | Assets AssetList | ||
357 | RawText string | ||
358 | Lines []Item | ||
359 | Error bool | ||
360 | Protocol string | ||
361 | }{uri, fmt.Sprintf("%s/%s", hostport, uri), assetList, fmt.Sprintf("Error: %s", err), nil, true, "gemini"}) | ||
362 | return | ||
363 | } | ||
364 | |||
365 | http.Redirect(w, req, resolveURI(res.Header.Meta, baseUrl), http.StatusFound) | ||
366 | return | ||
367 | } | ||
368 | |||
345 | if int(res.Header.Status/10) != 2 { | 369 | if int(res.Header.Status/10) != 2 { |
346 | tpl.Execute(w, struct { | 370 | tpl.Execute(w, struct { |
347 | Title string | 371 | Title string |
@@ -355,18 +379,24 @@ func GeminiHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
355 | return | 379 | return |
356 | } | 380 | } |
357 | 381 | ||
358 | if strings.HasPrefix(res.Header.Meta, MIME_GEMINI) { | 382 | if strings.HasPrefix(res.Header.Meta, "text/") { |
359 | items := parseGeminiDocument(res, uri, hostport) | 383 | // TODO: Handle encoding |
360 | tpl.Execute(w, struct { | 384 | // https://stackoverflow.com/questions/32518432/how-to-convert-from-an-encoding-to-utf-8-in-go |
361 | Title string | 385 | |
362 | URI string | 386 | if strings.HasPrefix(res.Header.Meta, MIME_GEMINI) { |
363 | Assets AssetList | 387 | items := parseGeminiDocument(res, uri, hostport) |
364 | RawText string | 388 | tpl.Execute(w, struct { |
365 | Lines []Item | 389 | Title string |
366 | Error bool | 390 | URI string |
367 | Protocol string | 391 | Assets AssetList |
368 | }{uri, fmt.Sprintf("%s/%s", hostport, uri), assetList, "", items, false, "gemini"}) | 392 | RawText string |
369 | } else if strings.HasPrefix(res.Header.Meta, "text/") { | 393 | Lines []Item |
394 | Error bool | ||
395 | Protocol string | ||
396 | }{uri, fmt.Sprintf("%s/%s", hostport, uri), assetList, "", items, false, "gemini"}) | ||
397 | return | ||
398 | } | ||
399 | |||
370 | buf := new(bytes.Buffer) | 400 | buf := new(bytes.Buffer) |
371 | buf.ReadFrom(res.Body) | 401 | buf.ReadFrom(res.Body) |
372 | tpl.Execute(w, struct { | 402 | 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 ( | |||
49 | HeaderPattern = regexp.MustCompile("^(\\d\\d)[ \\t]+(.*)$") | 49 | HeaderPattern = regexp.MustCompile("^(\\d\\d)[ \\t]+(.*)$") |
50 | MimeTypePattern = regexp.MustCompile("^[-\\w.]+/[-\\w.]+") | 50 | MimeTypePattern = regexp.MustCompile("^[-\\w.]+/[-\\w.]+") |
51 | MimeCharsetPattern = regexp.MustCompile("charset=([^ ;]+)") | 51 | MimeCharsetPattern = regexp.MustCompile("charset=([^ ;]+)") |
52 | GeminiLinkPattern = regexp.MustCompile("^=>[ \\t]*([^ ]+)(?:[ \\t]+(.*))?$") | 52 | GeminiLinkPattern = regexp.MustCompile("^=>[ \\t]*([^ \\t]+)(?:[ \\t]+(.*))?$") |
53 | ) | 53 | ) |
54 | 54 | ||
55 | type GeminiHeader struct { | 55 | 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 = `<!doctype html> | |||
58 | {{- if ne (len $uriParts) 0 -}} | 58 | {{- if ne (len $uriParts) 0 -}} |
59 | <span class="location__slash">/</span> | 59 | <span class="location__slash">/</span> |
60 | {{- end -}} | 60 | {{- end -}} |
61 | {{- if and (eq $page.Protocol "gopher") (eq (len $uriParts) 1) -}} | ||
62 | {{- $uriLast = $uriLast | trimLeftChar -}} | ||
63 | {{- end -}} | ||
61 | <span class="location__uripart">{{ $uriLast }}</span> | 64 | <span class="location__uripart">{{ $uriLast }}</span> |
62 | </div> | 65 | </div> |
63 | <div class="actions"> | 66 | <div class="actions"> |