diff options
| -rw-r--r-- | gopherproxy/gopherproxy.go | 203 | 
1 files changed, 103 insertions, 100 deletions
| diff --git a/gopherproxy/gopherproxy.go b/gopherproxy/gopherproxy.go index 6556845..4a7d972 100644 --- a/gopherproxy/gopherproxy.go +++ b/gopherproxy/gopherproxy.go | |||
| @@ -49,6 +49,16 @@ type AssetList struct { | |||
| 49 | PropFontW2 string | 49 | PropFontW2 string | 
| 50 | } | 50 | } | 
| 51 | 51 | ||
| 52 | type TemplateVariables struct { | ||
| 53 | Title string | ||
| 54 | URI string | ||
| 55 | Assets AssetList | ||
| 56 | RawText string | ||
| 57 | Lines []Item | ||
| 58 | Error bool | ||
| 59 | Protocol string | ||
| 60 | } | ||
| 61 | |||
| 52 | func resolveURI(uri string, baseURL *url.URL) (resolvedURI string) { | 62 | func resolveURI(uri string, baseURL *url.URL) (resolvedURI string) { | 
| 53 | if strings.HasPrefix(uri, "//") { | 63 | if strings.HasPrefix(uri, "//") { | 
| 54 | resolvedURI = "/gemini/" + strings.TrimPrefix(uri, "//") | 64 | resolvedURI = "/gemini/" + strings.TrimPrefix(uri, "//") | 
| @@ -144,15 +154,13 @@ func renderGopherDirectory(w http.ResponseWriter, tpl *template.Template, assetL | |||
| 144 | } | 154 | } | 
| 145 | } | 155 | } | 
| 146 | 156 | ||
| 147 | return tpl.Execute(w, struct { | 157 | return tpl.Execute(w, TemplateVariables{ | 
| 148 | Title string | 158 | Title: title, | 
| 149 | URI string | 159 | URI: fmt.Sprintf("%s/%s", hostport, uri), | 
| 150 | Assets AssetList | 160 | Assets: assetList, | 
| 151 | Lines []Item | 161 | Lines: out, | 
| 152 | RawText string | 162 | Protocol: "gopher", | 
| 153 | Error bool | 163 | }) | 
| 154 | Protocol string | ||
| 155 | }{title, fmt.Sprintf("%s/%s", hostport, uri), assetList, out, "", false, "gopher"}) | ||
| 156 | } | 164 | } | 
| 157 | 165 | ||
| 158 | func parseGeminiDocument(body *bytes.Buffer, uri string, hostport string) (items []Item) { | 166 | func parseGeminiDocument(body *bytes.Buffer, uri string, hostport string) (items []Item) { | 
| @@ -193,15 +201,12 @@ func parseGeminiDocument(body *bytes.Buffer, uri string, hostport string) (items | |||
| 193 | 201 | ||
| 194 | func DefaultHandler(tpl *template.Template, startpagetext string, assetList AssetList) http.HandlerFunc { | 202 | func DefaultHandler(tpl *template.Template, startpagetext string, assetList AssetList) http.HandlerFunc { | 
| 195 | return func(w http.ResponseWriter, req *http.Request) { | 203 | return func(w http.ResponseWriter, req *http.Request) { | 
| 196 | if err := tpl.Execute(w, struct { | 204 | if err := tpl.Execute(w, TemplateVariables{ | 
| 197 | Title string | 205 | Title: "Gopher/Gemini proxy", | 
| 198 | URI string | 206 | Assets: assetList, | 
| 199 | Assets AssetList | 207 | RawText: startpagetext, | 
| 200 | RawText string | 208 | Protocol: "startpage", | 
| 201 | Lines []Item | 209 | }); err != nil { | 
| 202 | Error bool | ||
| 203 | Protocol string | ||
| 204 | }{"Gopher/Gemini proxy", "", assetList, startpagetext, nil, false, "startpage"}); err != nil { | ||
| 205 | log.Println("Template error: " + err.Error()) | 210 | log.Println("Template error: " + err.Error()) | 
| 206 | } | 211 | } | 
| 207 | } | 212 | } | 
| @@ -239,15 +244,14 @@ func GopherHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
| 239 | 244 | ||
| 240 | uri, err := url.QueryUnescape(strings.Join(parts[1:], "/")) | 245 | uri, err := url.QueryUnescape(strings.Join(parts[1:], "/")) | 
| 241 | if err != nil { | 246 | if err != nil { | 
| 242 | if e := tpl.Execute(w, struct { | 247 | if e := tpl.Execute(w, TemplateVariables{ | 
| 243 | Title string | 248 | Title: title, | 
| 244 | URI string | 249 | URI: hostport, | 
| 245 | Assets AssetList | 250 | Assets: assetList, | 
| 246 | RawText string | 251 | RawText: fmt.Sprintf("Error: %s", err), | 
| 247 | Lines []Item | 252 | Error: true, | 
| 248 | Error bool | 253 | Protocol: "gopher", | 
| 249 | Protocol string | 254 | }); e != nil { | 
| 250 | }{title, hostport, assetList, fmt.Sprintf("Error: %s", err), nil, true, "gopher"}); e != nil { | ||
| 251 | log.Println("Template error: " + e.Error()) | 255 | log.Println("Template error: " + e.Error()) | 
| 252 | log.Println(err.Error()) | 256 | log.Println(err.Error()) | 
| 253 | } | 257 | } | 
| @@ -268,15 +272,14 @@ func GopherHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
| 268 | ) | 272 | ) | 
| 269 | 273 | ||
| 270 | if err != nil { | 274 | if err != nil { | 
| 271 | if e := tpl.Execute(w, struct { | 275 | if e := tpl.Execute(w, TemplateVariables{ | 
| 272 | Title string | 276 | Title: title, | 
| 273 | URI string | 277 | URI: fmt.Sprintf("%s/%s", hostport, uri), | 
| 274 | Assets AssetList | 278 | Assets: assetList, | 
| 275 | RawText string | 279 | RawText: fmt.Sprintf("Error: %s", err), | 
| 276 | Lines []Item | 280 | Error: true, | 
| 277 | Error bool | 281 | Protocol: "gopher", | 
| 278 | Protocol string | 282 | }); e != nil { | 
| 279 | }{title, fmt.Sprintf("%s/%s", hostport, uri), assetList, fmt.Sprintf("Error: %s", err), nil, true, "gopher"}); e != nil { | ||
| 280 | log.Println("Template error: " + e.Error()) | 283 | log.Println("Template error: " + e.Error()) | 
| 281 | } | 284 | } | 
| 282 | return | 285 | return | 
| @@ -288,15 +291,14 @@ func GopherHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
| 288 | } else if strings.HasPrefix(parts[1], "0") && !strings.HasSuffix(uri, ".xml") && !strings.HasSuffix(uri, ".asc") { | 291 | } else if strings.HasPrefix(parts[1], "0") && !strings.HasSuffix(uri, ".xml") && !strings.HasSuffix(uri, ".asc") { | 
| 289 | buf := new(bytes.Buffer) | 292 | buf := new(bytes.Buffer) | 
| 290 | buf.ReadFrom(res.Body) | 293 | buf.ReadFrom(res.Body) | 
| 291 | if err := tpl.Execute(w, struct { | 294 | |
| 292 | Title string | 295 | if err := tpl.Execute(w, TemplateVariables{ | 
| 293 | URI string | 296 | Title: title, | 
| 294 | Assets AssetList | 297 | URI: fmt.Sprintf("%s/%s", hostport, uri), | 
| 295 | RawText string | 298 | Assets: assetList, | 
| 296 | Lines []Item | 299 | RawText: buf.String(), | 
| 297 | Error bool | 300 | Protocol: "gopher", | 
| 298 | Protocol string | 301 | }); err != nil { | 
| 299 | }{title, fmt.Sprintf("%s/%s", hostport, uri), assetList, buf.String(), nil, false, "gopher"}); err != nil { | ||
| 300 | log.Println("Template error: " + err.Error()) | 302 | log.Println("Template error: " + err.Error()) | 
| 301 | } | 303 | } | 
| 302 | } else if strings.HasPrefix(parts[1], "T") { | 304 | } else if strings.HasPrefix(parts[1], "T") { | 
| @@ -312,15 +314,14 @@ func GopherHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
| 312 | } | 314 | } | 
| 313 | } else { | 315 | } else { | 
| 314 | if err := renderGopherDirectory(w, tpl, assetList, uri, hostport, res.Dir); err != nil { | 316 | if err := renderGopherDirectory(w, tpl, assetList, uri, hostport, res.Dir); err != nil { | 
| 315 | if e := tpl.Execute(w, struct { | 317 | if e := tpl.Execute(w, TemplateVariables{ | 
| 316 | Title string | 318 | Title: title, | 
| 317 | URI string | 319 | URI: fmt.Sprintf("%s/%s", hostport, uri), | 
| 318 | Assets AssetList | 320 | Assets: assetList, | 
| 319 | RawText string | 321 | RawText: fmt.Sprintf("Error: %s", err), | 
| 320 | Lines []Item | 322 | Error: true, | 
| 321 | Error bool | 323 | Protocol: "gopher", | 
| 322 | Protocol string | 324 | }); e != nil { | 
| 323 | }{title, fmt.Sprintf("%s/%s", hostport, uri), assetList, fmt.Sprintf("Error: %s", err), nil, true, "gopher"}); e != nil { | ||
| 324 | log.Println("Template error: " + e.Error()) | 325 | log.Println("Template error: " + e.Error()) | 
| 325 | log.Println(e.Error()) | 326 | log.Println(e.Error()) | 
| 326 | } | 327 | } | 
| @@ -356,15 +357,14 @@ func GeminiHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
| 356 | 357 | ||
| 357 | uri, err := url.QueryUnescape(strings.Join(parts[1:], "/")) | 358 | uri, err := url.QueryUnescape(strings.Join(parts[1:], "/")) | 
| 358 | if err != nil { | 359 | if err != nil { | 
| 359 | if e := tpl.Execute(w, struct { | 360 | if e := tpl.Execute(w, TemplateVariables{ | 
| 360 | Title string | 361 | Title: title, | 
| 361 | URI string | 362 | URI: hostport, | 
| 362 | Assets AssetList | 363 | Assets: assetList, | 
| 363 | RawText string | 364 | RawText: fmt.Sprintf("Error: %s", err), | 
| 364 | Lines []Item | 365 | Error: true, | 
| 365 | Error bool | 366 | Protocol: "gemini", | 
| 366 | Protocol string | 367 | }); e != nil { | 
| 367 | }{title, hostport, assetList, fmt.Sprintf("Error: %s", err), nil, true, "gemini"}); e != nil { | ||
| 368 | log.Println("Template error: " + e.Error()) | 368 | log.Println("Template error: " + e.Error()) | 
| 369 | log.Println(err.Error()) | 369 | log.Println(err.Error()) | 
| 370 | } | 370 | } | 
| @@ -385,15 +385,14 @@ func GeminiHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
| 385 | ) | 385 | ) | 
| 386 | 386 | ||
| 387 | if err != nil { | 387 | if err != nil { | 
| 388 | if e := tpl.Execute(w, struct { | 388 | if e := tpl.Execute(w, TemplateVariables{ | 
| 389 | Title string | 389 | Title: title, | 
| 390 | URI string | 390 | URI: fmt.Sprintf("%s/%s", hostport, uri), | 
| 391 | Assets AssetList | 391 | Assets: assetList, | 
| 392 | RawText string | 392 | RawText: fmt.Sprintf("Error: %s", err), | 
| 393 | Lines []Item | 393 | Error: true, | 
| 394 | Error bool | 394 | Protocol: "gemini", | 
| 395 | Protocol string | 395 | }); e != nil { | 
| 396 | }{title, fmt.Sprintf("%s/%s", hostport, uri), assetList, fmt.Sprintf("Error: %s", err), nil, true, "gemini"}); e != nil { | ||
| 397 | log.Println("Template error: " + e.Error()) | 396 | log.Println("Template error: " + e.Error()) | 
| 398 | log.Println(err.Error()) | 397 | log.Println(err.Error()) | 
| 399 | } | 398 | } | 
| @@ -407,15 +406,14 @@ func GeminiHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
| 407 | uri, | 406 | uri, | 
| 408 | )) | 407 | )) | 
| 409 | if err != nil { | 408 | if err != nil { | 
| 410 | if e := tpl.Execute(w, struct { | 409 | if e := tpl.Execute(w, TemplateVariables{ | 
| 411 | Title string | 410 | Title: title, | 
| 412 | URI string | 411 | URI: fmt.Sprintf("%s/%s", hostport, uri), | 
| 413 | Assets AssetList | 412 | Assets: assetList, | 
| 414 | RawText string | 413 | RawText: fmt.Sprintf("Error: %s", err), | 
| 415 | Lines []Item | 414 | Error: true, | 
| 416 | Error bool | 415 | Protocol: "gemini", | 
| 417 | Protocol string | 416 | }); e != nil { | 
| 418 | }{title, fmt.Sprintf("%s/%s", hostport, uri), assetList, fmt.Sprintf("Error: %s", err), nil, true, "gemini"}); e != nil { | ||
| 419 | log.Println("Template error: " + e.Error()) | 417 | log.Println("Template error: " + e.Error()) | 
| 420 | log.Println(err.Error()) | 418 | log.Println(err.Error()) | 
| 421 | } | 419 | } | 
| @@ -427,15 +425,14 @@ func GeminiHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
| 427 | } | 425 | } | 
| 428 | 426 | ||
| 429 | if int(res.Header.Status/10) != 2 { | 427 | if int(res.Header.Status/10) != 2 { | 
| 430 | if err := tpl.Execute(w, struct { | 428 | if err := tpl.Execute(w, TemplateVariables{ | 
| 431 | Title string | 429 | Title: title, | 
| 432 | URI string | 430 | URI: fmt.Sprintf("%s/%s", hostport, uri), | 
| 433 | Assets AssetList | 431 | Assets: assetList, | 
| 434 | RawText string | 432 | RawText: fmt.Sprintf("Error %d: %s", res.Header.Status, res.Header.Meta), | 
| 435 | Lines []Item | 433 | Error: true, | 
| 436 | Error bool | 434 | Protocol: "gemini", | 
| 437 | Protocol string | 435 | }); err != nil { | 
| 438 | }{title, fmt.Sprintf("%s/%s", hostport, uri), assetList, fmt.Sprintf("Error %d: %s", res.Header.Status, res.Header.Meta), nil, true, "gemini"}); err != nil { | ||
| 439 | log.Println("Template error: " + err.Error()) | 436 | log.Println("Template error: " + err.Error()) | 
| 440 | } | 437 | } | 
| 441 | return | 438 | return | 
| @@ -468,15 +465,14 @@ func GeminiHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
| 468 | rawText = buf.String() | 465 | rawText = buf.String() | 
| 469 | } | 466 | } | 
| 470 | 467 | ||
| 471 | if err := tpl.Execute(w, struct { | 468 | if err := tpl.Execute(w, TemplateVariables{ | 
| 472 | Title string | 469 | Title: title, | 
| 473 | URI string | 470 | URI: fmt.Sprintf("%s/%s", hostport, uri), | 
| 474 | Assets AssetList | 471 | Assets: assetList, | 
| 475 | RawText string | 472 | Lines: items, | 
| 476 | Lines []Item | 473 | RawText: rawText, | 
| 477 | Error bool | 474 | Protocol: "gemini", | 
| 478 | Protocol string | 475 | }); err != nil { | 
| 479 | }{title, fmt.Sprintf("%s/%s", hostport, uri), assetList, rawText, items, false, "gemini"}); err != nil { | ||
| 480 | log.Println("Template error: " + err.Error()) | 476 | log.Println("Template error: " + err.Error()) | 
| 481 | } | 477 | } | 
| 482 | } else { | 478 | } else { | 
| @@ -678,7 +674,14 @@ func ListenAndServe(bind, startpagefile string, robotsfile string, robotsdebug b | |||
| 678 | ConcurrencyLevel: vipsconcurrency, | 674 | ConcurrencyLevel: vipsconcurrency, | 
| 679 | }) | 675 | }) | 
| 680 | 676 | ||
| 681 | assets := AssetList{styleAsset, jsAsset, fontwAsset, fontw2Asset, propfontwAsset, propfontw2Asset} | 677 | assets := AssetList{ | 
| 678 | Style: styleAsset, | ||
| 679 | JS: jsAsset, | ||
| 680 | FontW: fontwAsset, | ||
| 681 | FontW2: fontw2Asset, | ||
| 682 | PropFontW: propfontwAsset, | ||
| 683 | PropFontW2: propfontw2Asset, | ||
| 684 | } | ||
| 682 | 685 | ||
| 683 | http.Handle("/", gziphandler.GzipHandler(DefaultHandler(tpl, startpagetext, assets))) | 686 | http.Handle("/", gziphandler.GzipHandler(DefaultHandler(tpl, startpagetext, assets))) | 
| 684 | http.Handle("/gopher/", gziphandler.GzipHandler(GopherHandler(tpl, robotsdata, assets, robotsdebug))) | 687 | http.Handle("/gopher/", gziphandler.GzipHandler(GopherHandler(tpl, robotsdata, assets, robotsdebug))) | 
