aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFeuerfuchs <git@feuerfuchs.dev>2019-11-16 01:39:33 +0100
committerFeuerfuchs <git@feuerfuchs.dev>2019-11-16 01:39:33 +0100
commitddf2aefa09e81f0efd1dfcd3c10615ab55c6920d (patch)
treeb0403855e643c4b5bd9d00f56c10ccd9af7c5361
parentInitial Gemini support (diff)
downloadgopherproxy-ddf2aefa09e81f0efd1dfcd3c10615ab55c6920d.tar.gz
gopherproxy-ddf2aefa09e81f0efd1dfcd3c10615ab55c6920d.tar.bz2
gopherproxy-ddf2aefa09e81f0efd1dfcd3c10615ab55c6920d.zip
Fixed some issues with Gemini
-rw-r--r--gopherproxy.go114
-rw-r--r--libgemini.go2
-rw-r--r--template.go3
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
49func 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
49func renderGopherDirectory(w http.ResponseWriter, tpl *template.Template, assetList AssetList, uri string, hostport string, d gopher.Directory) error { 74func 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
111func parseGeminiDocument(response *GeminiResponse, uri string, hostport string) (items []Item) { 136func 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
55type GeminiHeader struct { 55type 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">