diff options
| -rw-r--r-- | gopherproxy.go | 71 | ||||
| -rw-r--r-- | template.go | 2 | 
2 files changed, 45 insertions, 28 deletions
diff --git a/gopherproxy.go b/gopherproxy.go index 65c8f89..751cebf 100644 --- a/gopherproxy.go +++ b/gopherproxy.go  | |||
| @@ -50,25 +50,25 @@ type AssetList struct { | |||
| 50 | PropFontW2 string | 50 | PropFontW2 string | 
| 51 | } | 51 | } | 
| 52 | 52 | ||
| 53 | func resolveURI(uri string, baseUrl *url.URL) (resolvedUri string) { | 53 | func resolveURI(uri string, baseURL *url.URL) (resolvedURI string) { | 
| 54 | if strings.HasPrefix(uri, "//") { | 54 | if strings.HasPrefix(uri, "//") { | 
| 55 | resolvedUri = "/gemini/" + strings.TrimPrefix(uri, "//") | 55 | resolvedURI = "/gemini/" + strings.TrimPrefix(uri, "//") | 
| 56 | } else if strings.HasPrefix(uri, "gemini://") { | 56 | } else if strings.HasPrefix(uri, "gemini://") { | 
| 57 | resolvedUri = "/gemini/" + strings.TrimPrefix(uri, "gemini://") | 57 | resolvedURI = "/gemini/" + strings.TrimPrefix(uri, "gemini://") | 
| 58 | } else if strings.HasPrefix(uri, "gopher://") { | 58 | } else if strings.HasPrefix(uri, "gopher://") { | 
| 59 | resolvedUri = "/gopher/" + strings.TrimPrefix(uri, "gopher://") | 59 | resolvedURI = "/gopher/" + strings.TrimPrefix(uri, "gopher://") | 
| 60 | } else { | 60 | } else { | 
| 61 | url, err := url.Parse(uri) | 61 | url, err := url.Parse(uri) | 
| 62 | if err != nil { | 62 | if err != nil { | 
| 63 | return "" | 63 | return "" | 
| 64 | } | 64 | } | 
| 65 | adjustedUrl := baseUrl.ResolveReference(url) | 65 | adjustedURI := baseURL.ResolveReference(url) | 
| 66 | if adjustedUrl.Scheme == "gemini" { | 66 | if adjustedURI.Scheme == "gemini" { | 
| 67 | resolvedUri = "/gemini/" + adjustedUrl.Host + adjustedUrl.Path | 67 | resolvedURI = "/gemini/" + adjustedURI.Host + adjustedURI.Path | 
| 68 | } else if adjustedUrl.Scheme == "gopher" { | 68 | } else if adjustedURI.Scheme == "gopher" { | 
| 69 | resolvedUri = "/gopher/" + adjustedUrl.Host + adjustedUrl.Path | 69 | resolvedURI = "/gopher/" + adjustedURI.Host + adjustedURI.Path | 
| 70 | } else { | 70 | } else { | 
| 71 | resolvedUri = adjustedUrl.String() | 71 | resolvedURI = adjustedURI.String() | 
| 72 | } | 72 | } | 
| 73 | } | 73 | } | 
| 74 | 74 | ||
| @@ -123,7 +123,11 @@ func renderGopherDirectory(w http.ResponseWriter, tpl *template.Template, assetL | |||
| 123 | } | 123 | } | 
| 124 | 124 | ||
| 125 | if title == "" { | 125 | if title == "" { | 
| 126 | title = hostport | 126 | if uri != "" { | 
| 127 | title = fmt.Sprintf("%s/%s", hostport, uri) | ||
| 128 | } else { | ||
| 129 | title = hostport | ||
| 130 | } | ||
| 127 | } | 131 | } | 
| 128 | 132 | ||
| 129 | return tpl.Execute(w, struct { | 133 | return tpl.Execute(w, struct { | 
| @@ -138,7 +142,7 @@ func renderGopherDirectory(w http.ResponseWriter, tpl *template.Template, assetL | |||
| 138 | } | 142 | } | 
| 139 | 143 | ||
| 140 | func parseGeminiDocument(body *bytes.Buffer, uri string, hostport string) (items []Item) { | 144 | func parseGeminiDocument(body *bytes.Buffer, uri string, hostport string) (items []Item) { | 
| 141 | baseUrl, err := url.Parse(fmt.Sprintf( | 145 | baseURL, err := url.Parse(fmt.Sprintf( | 
| 142 | "gemini://%s/%s", | 146 | "gemini://%s/%s", | 
| 143 | hostport, | 147 | hostport, | 
| 144 | uri, | 148 | uri, | 
| @@ -160,7 +164,7 @@ func parseGeminiDocument(body *bytes.Buffer, uri string, hostport string) (items | |||
| 160 | linkMatch := GeminiLinkPattern.FindStringSubmatch(line) | 164 | linkMatch := GeminiLinkPattern.FindStringSubmatch(line) | 
| 161 | if len(linkMatch) != 0 && linkMatch[0] != "" { | 165 | if len(linkMatch) != 0 && linkMatch[0] != "" { | 
| 162 | item.Type = ITEM_TYPE_GEMINI_LINK | 166 | item.Type = ITEM_TYPE_GEMINI_LINK | 
| 163 | item.Link = template.URL(resolveURI(linkMatch[1], baseUrl)) | 167 | item.Link = template.URL(resolveURI(linkMatch[1], baseURL)) | 
| 164 | item.Text = linkMatch[2] | 168 | item.Text = linkMatch[2] | 
| 165 | if item.Text == "" { | 169 | if item.Text == "" { | 
| 166 | item.Text = linkMatch[1] | 170 | item.Text = linkMatch[1] | 
| @@ -201,6 +205,8 @@ func GopherHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
| 201 | return | 205 | return | 
| 202 | } | 206 | } | 
| 203 | 207 | ||
| 208 | title := hostport | ||
| 209 | |||
| 204 | var qs string | 210 | var qs string | 
| 205 | 211 | ||
| 206 | if req.URL.RawQuery != "" { | 212 | if req.URL.RawQuery != "" { | 
| @@ -217,10 +223,14 @@ func GopherHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
| 217 | Lines []Item | 223 | Lines []Item | 
| 218 | Error bool | 224 | Error bool | 
| 219 | Protocol string | 225 | Protocol string | 
| 220 | }{"", hostport, assetList, fmt.Sprintf("Error: %s", err), nil, true, "gopher"}) | 226 | }{title, hostport, assetList, fmt.Sprintf("Error: %s", err), nil, true, "gopher"}) | 
| 221 | return | 227 | return | 
| 222 | } | 228 | } | 
| 223 | 229 | ||
| 230 | if uri != "" { | ||
| 231 | title = fmt.Sprintf("%s/%s", hostport, uri) | ||
| 232 | } | ||
| 233 | |||
| 224 | res, err := gopher.Get( | 234 | res, err := gopher.Get( | 
| 225 | fmt.Sprintf( | 235 | fmt.Sprintf( | 
| 226 | "gopher://%s/%s%s", | 236 | "gopher://%s/%s%s", | 
| @@ -239,15 +249,14 @@ func GopherHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
| 239 | Lines []Item | 249 | Lines []Item | 
| 240 | Error bool | 250 | Error bool | 
| 241 | Protocol string | 251 | Protocol string | 
| 242 | }{uri, fmt.Sprintf("%s/%s", hostport, uri), assetList, fmt.Sprintf("Error: %s", err), nil, true, "gopher"}) | 252 | }{title, fmt.Sprintf("%s/%s", hostport, uri), assetList, fmt.Sprintf("Error: %s", err), nil, true, "gopher"}) | 
| 243 | return | 253 | return | 
| 244 | } | 254 | } | 
| 245 | 255 | ||
| 246 | if res.Body != nil { | 256 | if res.Body != nil { | 
| 247 | if len(parts) < 2 { | 257 | if len(parts) < 2 { | 
| 248 | io.Copy(w, res.Body) | 258 | io.Copy(w, res.Body) | 
| 249 | } else if strings.HasPrefix(parts[1], "0") && !strings.HasSuffix(uri, ".xml") && !strings.HasSuffix(uri, ".asc") { //strings.HasSuffix(uri, ".txt") || strings.HasSuffix(uri, ".md") { | 259 | } else if strings.HasPrefix(parts[1], "0") && !strings.HasSuffix(uri, ".xml") && !strings.HasSuffix(uri, ".asc") { | 
| 250 | // handle .txt files | ||
| 251 | buf := new(bytes.Buffer) | 260 | buf := new(bytes.Buffer) | 
| 252 | buf.ReadFrom(res.Body) | 261 | buf.ReadFrom(res.Body) | 
| 253 | tpl.Execute(w, struct { | 262 | tpl.Execute(w, struct { | 
| @@ -258,7 +267,7 @@ func GopherHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
| 258 | Lines []Item | 267 | Lines []Item | 
| 259 | Error bool | 268 | Error bool | 
| 260 | Protocol string | 269 | Protocol string | 
| 261 | }{uri, fmt.Sprintf("%s/%s", hostport, uri), assetList, buf.String(), nil, false, "gopher"}) | 270 | }{title, fmt.Sprintf("%s/%s", hostport, uri), assetList, buf.String(), nil, false, "gopher"}) | 
| 262 | } else if strings.HasPrefix(parts[1], "T") { | 271 | } else if strings.HasPrefix(parts[1], "T") { | 
| 263 | _, _, err = vips.NewTransform(). | 272 | _, _, err = vips.NewTransform(). | 
| 264 | Load(res.Body). | 273 | Load(res.Body). | 
| @@ -280,8 +289,7 @@ func GopherHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
| 280 | Lines []Item | 289 | Lines []Item | 
| 281 | Error bool | 290 | Error bool | 
| 282 | Protocol string | 291 | Protocol string | 
| 283 | }{uri, fmt.Sprintf("%s/%s", hostport, uri), assetList, fmt.Sprintf("Error: %s", err), nil, true, "gopher"}) | 292 | }{title, fmt.Sprintf("%s/%s", hostport, uri), assetList, fmt.Sprintf("Error: %s", err), nil, true, "gopher"}) | 
| 284 | return | ||
| 285 | } | 293 | } | 
| 286 | } | 294 | } | 
| 287 | } | 295 | } | 
| @@ -304,6 +312,8 @@ func GeminiHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
| 304 | return | 312 | return | 
| 305 | } | 313 | } | 
| 306 | 314 | ||
| 315 | title := hostport | ||
| 316 | |||
| 307 | var qs string | 317 | var qs string | 
| 308 | 318 | ||
| 309 | if req.URL.RawQuery != "" { | 319 | if req.URL.RawQuery != "" { | 
| @@ -320,10 +330,14 @@ func GeminiHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
| 320 | Lines []Item | 330 | Lines []Item | 
| 321 | Error bool | 331 | Error bool | 
| 322 | Protocol string | 332 | Protocol string | 
| 323 | }{"", hostport, assetList, fmt.Sprintf("Error: %s", err), nil, true, "gemini"}) | 333 | }{title, hostport, assetList, fmt.Sprintf("Error: %s", err), nil, true, "gemini"}) | 
| 324 | return | 334 | return | 
| 325 | } | 335 | } | 
| 326 | 336 | ||
| 337 | if uri != "" { | ||
| 338 | title = fmt.Sprintf("%s/%s", hostport, uri) | ||
| 339 | } | ||
| 340 | |||
| 327 | res, err := GeminiGet( | 341 | res, err := GeminiGet( | 
| 328 | fmt.Sprintf( | 342 | fmt.Sprintf( | 
| 329 | "gemini://%s/%s%s", | 343 | "gemini://%s/%s%s", | 
| @@ -342,12 +356,12 @@ func GeminiHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
| 342 | Lines []Item | 356 | Lines []Item | 
| 343 | Error bool | 357 | Error bool | 
| 344 | Protocol string | 358 | Protocol string | 
| 345 | }{uri, fmt.Sprintf("%s/%s", hostport, uri), assetList, fmt.Sprintf("Error: %s", err), nil, true, "gemini"}) | 359 | }{title, fmt.Sprintf("%s/%s", hostport, uri), assetList, fmt.Sprintf("Error: %s", err), nil, true, "gemini"}) | 
| 346 | return | 360 | return | 
| 347 | } | 361 | } | 
| 348 | 362 | ||
| 349 | if int(res.Header.Status/10) == 3 { | 363 | if int(res.Header.Status/10) == 3 { | 
| 350 | baseUrl, err := url.Parse(fmt.Sprintf( | 364 | baseURL, err := url.Parse(fmt.Sprintf( | 
| 351 | "gemini://%s/%s", | 365 | "gemini://%s/%s", | 
| 352 | hostport, | 366 | hostport, | 
| 353 | uri, | 367 | uri, | 
| @@ -361,11 +375,11 @@ func GeminiHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
| 361 | Lines []Item | 375 | Lines []Item | 
| 362 | Error bool | 376 | Error bool | 
| 363 | Protocol string | 377 | Protocol string | 
| 364 | }{uri, fmt.Sprintf("%s/%s", hostport, uri), assetList, fmt.Sprintf("Error: %s", err), nil, true, "gemini"}) | 378 | }{title, fmt.Sprintf("%s/%s", hostport, uri), assetList, fmt.Sprintf("Error: %s", err), nil, true, "gemini"}) | 
| 365 | return | 379 | return | 
| 366 | } | 380 | } | 
| 367 | 381 | ||
| 368 | http.Redirect(w, req, resolveURI(res.Header.Meta, baseUrl), http.StatusFound) | 382 | http.Redirect(w, req, resolveURI(res.Header.Meta, baseURL), http.StatusFound) | 
| 369 | return | 383 | return | 
| 370 | } | 384 | } | 
| 371 | 385 | ||
| @@ -378,7 +392,7 @@ func GeminiHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
| 378 | Lines []Item | 392 | Lines []Item | 
| 379 | Error bool | 393 | Error bool | 
| 380 | Protocol string | 394 | Protocol string | 
| 381 | }{uri, fmt.Sprintf("%s/%s", hostport, uri), assetList, fmt.Sprintf("Error %d: %s", res.Header.Status, res.Header.Meta), nil, true, "gemini"}) | 395 | }{title, fmt.Sprintf("%s/%s", hostport, uri), assetList, fmt.Sprintf("Error %d: %s", res.Header.Status, res.Header.Meta), nil, true, "gemini"}) | 
| 382 | return | 396 | return | 
| 383 | } | 397 | } | 
| 384 | 398 | ||
| @@ -417,7 +431,7 @@ func GeminiHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
| 417 | Lines []Item | 431 | Lines []Item | 
| 418 | Error bool | 432 | Error bool | 
| 419 | Protocol string | 433 | Protocol string | 
| 420 | }{uri, fmt.Sprintf("%s/%s", hostport, uri), assetList, rawText, items, false, "gemini"}) | 434 | }{title, fmt.Sprintf("%s/%s", hostport, uri), assetList, rawText, items, false, "gemini"}) | 
| 421 | } else { | 435 | } else { | 
| 422 | io.Copy(w, res.Body) | 436 | io.Copy(w, res.Body) | 
| 423 | } | 437 | } | 
| @@ -594,6 +608,9 @@ func ListenAndServe(bind, robotsfile string, robotsdebug bool, vipsconcurrency i | |||
| 594 | "hasPrefix": func(s string, prefix string) bool { | 608 | "hasPrefix": func(s string, prefix string) bool { | 
| 595 | return strings.HasPrefix(s, prefix) | 609 | return strings.HasPrefix(s, prefix) | 
| 596 | }, | 610 | }, | 
| 611 | "title": func(s string) string { | ||
| 612 | return strings.Title(s) | ||
| 613 | }, | ||
| 597 | } | 614 | } | 
| 598 | 615 | ||
| 599 | tpl, err = template.New("gophermenu").Funcs(funcMap).Parse(tpltext) | 616 | tpl, err = template.New("gophermenu").Funcs(funcMap).Parse(tpltext) | 
diff --git a/template.go b/template.go index 6a9c6fe..3bd8950 100644 --- a/template.go +++ b/template.go  | |||
| @@ -5,7 +5,7 @@ var tpltext = `<!doctype html> | |||
| 5 | <head> | 5 | <head> | 
| 6 | <meta charset="utf-8"> | 6 | <meta charset="utf-8"> | 
| 7 | <meta name="viewport" content="width=device-width, initial-scale=1" /> | 7 | <meta name="viewport" content="width=device-width, initial-scale=1" /> | 
| 8 | <title>{{ .Title }}</title> | 8 | <title>{{ .Title }} - {{ .Protocol | title }} proxy</title> | 
| 9 | <link rel="stylesheet" href="{{ .Assets.Style }}" /> | 9 | <link rel="stylesheet" href="{{ .Assets.Style }}" /> | 
| 10 | <style> | 10 | <style> | 
| 11 | @font-face { | 11 | @font-face { | 
