diff options
author | Feuerfuchs <git@feuerfuchs.dev> | 2019-11-17 10:14:58 +0100 |
---|---|---|
committer | Feuerfuchs <git@feuerfuchs.dev> | 2019-11-17 10:14:58 +0100 |
commit | e85a6b1c934d1070e40d11ad94b3ad4d79bdc9b2 (patch) | |
tree | 66613d0dac2581b117d17879af9c24b31d6f0af7 /gopherproxy.go | |
parent | Remove obsolete vars from libgemini (diff) | |
download | gopherproxy-e85a6b1c934d1070e40d11ad94b3ad4d79bdc9b2.tar.gz gopherproxy-e85a6b1c934d1070e40d11ad94b3ad4d79bdc9b2.tar.bz2 gopherproxy-e85a6b1c934d1070e40d11ad94b3ad4d79bdc9b2.zip |
Report template errors, add support for start page
Diffstat (limited to 'gopherproxy.go')
-rw-r--r-- | gopherproxy.go | 97 |
1 files changed, 69 insertions, 28 deletions
diff --git a/gopherproxy.go b/gopherproxy.go index 751cebf..2a6358c 100644 --- a/gopherproxy.go +++ b/gopherproxy.go | |||
@@ -177,9 +177,19 @@ func parseGeminiDocument(body *bytes.Buffer, uri string, hostport string) (items | |||
177 | return | 177 | return |
178 | } | 178 | } |
179 | 179 | ||
180 | func DefaultHandler(tpl *template.Template, uri string) http.HandlerFunc { | 180 | func DefaultHandler(tpl *template.Template, startpagetext string, assetList AssetList) http.HandlerFunc { |
181 | return func(w http.ResponseWriter, req *http.Request) { | 181 | return func(w http.ResponseWriter, req *http.Request) { |
182 | http.Redirect(w, req, "/"+uri, http.StatusFound) | 182 | if err := tpl.Execute(w, struct { |
183 | Title string | ||
184 | URI string | ||
185 | Assets AssetList | ||
186 | RawText string | ||
187 | Lines []Item | ||
188 | Error bool | ||
189 | Protocol string | ||
190 | }{"Gopher/Gemini proxy", "", assetList, startpagetext, nil, false, "startpage"}); err != nil { | ||
191 | log.Println("Template error: " + err.Error()) | ||
192 | } | ||
183 | } | 193 | } |
184 | } | 194 | } |
185 | 195 | ||
@@ -188,7 +198,7 @@ func DefaultHandler(tpl *template.Template, uri string) http.HandlerFunc { | |||
188 | // to the request path and renders the content using the provided template. | 198 | // to the request path and renders the content using the provided template. |
189 | // The optional robots parameters points to a robotstxt.RobotsData struct | 199 | // The optional robots parameters points to a robotstxt.RobotsData struct |
190 | // to test user agents against a configurable robotst.txt file. | 200 | // to test user agents against a configurable robotst.txt file. |
191 | func GopherHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, assetList AssetList, robotsdebug bool, uri string) http.HandlerFunc { | 201 | func GopherHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, assetList AssetList, robotsdebug bool) http.HandlerFunc { |
192 | return func(w http.ResponseWriter, req *http.Request) { | 202 | return func(w http.ResponseWriter, req *http.Request) { |
193 | agent := req.UserAgent() | 203 | agent := req.UserAgent() |
194 | path := strings.TrimPrefix(req.URL.Path, "/gopher/") | 204 | path := strings.TrimPrefix(req.URL.Path, "/gopher/") |
@@ -201,7 +211,7 @@ func GopherHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
201 | hostport := parts[0] | 211 | hostport := parts[0] |
202 | 212 | ||
203 | if len(hostport) == 0 { | 213 | if len(hostport) == 0 { |
204 | http.Redirect(w, req, "/"+uri, http.StatusFound) | 214 | http.Redirect(w, req, "/", http.StatusFound) |
205 | return | 215 | return |
206 | } | 216 | } |
207 | 217 | ||
@@ -215,7 +225,7 @@ func GopherHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
215 | 225 | ||
216 | uri, err := url.QueryUnescape(strings.Join(parts[1:], "/")) | 226 | uri, err := url.QueryUnescape(strings.Join(parts[1:], "/")) |
217 | if err != nil { | 227 | if err != nil { |
218 | tpl.Execute(w, struct { | 228 | if e := tpl.Execute(w, struct { |
219 | Title string | 229 | Title string |
220 | URI string | 230 | URI string |
221 | Assets AssetList | 231 | Assets AssetList |
@@ -223,7 +233,10 @@ func GopherHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
223 | Lines []Item | 233 | Lines []Item |
224 | Error bool | 234 | Error bool |
225 | Protocol string | 235 | Protocol string |
226 | }{title, hostport, assetList, fmt.Sprintf("Error: %s", err), nil, true, "gopher"}) | 236 | }{title, hostport, assetList, fmt.Sprintf("Error: %s", err), nil, true, "gopher"}); e != nil { |
237 | log.Println("Template error: " + e.Error()) | ||
238 | log.Println(err.Error()) | ||
239 | } | ||
227 | return | 240 | return |
228 | } | 241 | } |
229 | 242 | ||
@@ -241,7 +254,7 @@ func GopherHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
241 | ) | 254 | ) |
242 | 255 | ||
243 | if err != nil { | 256 | if err != nil { |
244 | tpl.Execute(w, struct { | 257 | if e := tpl.Execute(w, struct { |
245 | Title string | 258 | Title string |
246 | URI string | 259 | URI string |
247 | Assets AssetList | 260 | Assets AssetList |
@@ -249,7 +262,9 @@ func GopherHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
249 | Lines []Item | 262 | Lines []Item |
250 | Error bool | 263 | Error bool |
251 | Protocol string | 264 | Protocol string |
252 | }{title, fmt.Sprintf("%s/%s", hostport, uri), assetList, fmt.Sprintf("Error: %s", err), nil, true, "gopher"}) | 265 | }{title, fmt.Sprintf("%s/%s", hostport, uri), assetList, fmt.Sprintf("Error: %s", err), nil, true, "gopher"}); e != nil { |
266 | log.Println("Template error: " + e.Error()) | ||
267 | } | ||
253 | return | 268 | return |
254 | } | 269 | } |
255 | 270 | ||
@@ -259,7 +274,7 @@ func GopherHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
259 | } else if strings.HasPrefix(parts[1], "0") && !strings.HasSuffix(uri, ".xml") && !strings.HasSuffix(uri, ".asc") { | 274 | } else if strings.HasPrefix(parts[1], "0") && !strings.HasSuffix(uri, ".xml") && !strings.HasSuffix(uri, ".asc") { |
260 | buf := new(bytes.Buffer) | 275 | buf := new(bytes.Buffer) |
261 | buf.ReadFrom(res.Body) | 276 | buf.ReadFrom(res.Body) |
262 | tpl.Execute(w, struct { | 277 | if err := tpl.Execute(w, struct { |
263 | Title string | 278 | Title string |
264 | URI string | 279 | URI string |
265 | Assets AssetList | 280 | Assets AssetList |
@@ -267,7 +282,9 @@ func GopherHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
267 | Lines []Item | 282 | Lines []Item |
268 | Error bool | 283 | Error bool |
269 | Protocol string | 284 | Protocol string |
270 | }{title, fmt.Sprintf("%s/%s", hostport, uri), assetList, buf.String(), nil, false, "gopher"}) | 285 | }{title, fmt.Sprintf("%s/%s", hostport, uri), assetList, buf.String(), nil, false, "gopher"}); err != nil { |
286 | log.Println("Template error: " + err.Error()) | ||
287 | } | ||
271 | } else if strings.HasPrefix(parts[1], "T") { | 288 | } else if strings.HasPrefix(parts[1], "T") { |
272 | _, _, err = vips.NewTransform(). | 289 | _, _, err = vips.NewTransform(). |
273 | Load(res.Body). | 290 | Load(res.Body). |
@@ -281,7 +298,7 @@ func GopherHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
281 | } | 298 | } |
282 | } else { | 299 | } else { |
283 | if err := renderGopherDirectory(w, tpl, assetList, uri, hostport, res.Dir); err != nil { | 300 | if err := renderGopherDirectory(w, tpl, assetList, uri, hostport, res.Dir); err != nil { |
284 | tpl.Execute(w, struct { | 301 | if e := tpl.Execute(w, struct { |
285 | Title string | 302 | Title string |
286 | URI string | 303 | URI string |
287 | Assets AssetList | 304 | Assets AssetList |
@@ -289,13 +306,16 @@ func GopherHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
289 | Lines []Item | 306 | Lines []Item |
290 | Error bool | 307 | Error bool |
291 | Protocol string | 308 | Protocol string |
292 | }{title, fmt.Sprintf("%s/%s", hostport, uri), assetList, fmt.Sprintf("Error: %s", err), nil, true, "gopher"}) | 309 | }{title, fmt.Sprintf("%s/%s", hostport, uri), assetList, fmt.Sprintf("Error: %s", err), nil, true, "gopher"}); e != nil { |
310 | log.Println("Template error: " + e.Error()) | ||
311 | log.Println(e.Error()) | ||
312 | } | ||
293 | } | 313 | } |
294 | } | 314 | } |
295 | } | 315 | } |
296 | } | 316 | } |
297 | 317 | ||
298 | func GeminiHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, assetList AssetList, robotsdebug bool, uri string) http.HandlerFunc { | 318 | func GeminiHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, assetList AssetList, robotsdebug bool) http.HandlerFunc { |
299 | return func(w http.ResponseWriter, req *http.Request) { | 319 | return func(w http.ResponseWriter, req *http.Request) { |
300 | agent := req.UserAgent() | 320 | agent := req.UserAgent() |
301 | path := strings.TrimPrefix(req.URL.Path, "/gemini/") | 321 | path := strings.TrimPrefix(req.URL.Path, "/gemini/") |
@@ -308,7 +328,7 @@ func GeminiHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
308 | hostport := parts[0] | 328 | hostport := parts[0] |
309 | 329 | ||
310 | if len(hostport) == 0 { | 330 | if len(hostport) == 0 { |
311 | http.Redirect(w, req, "/"+uri, http.StatusFound) | 331 | http.Redirect(w, req, "/", http.StatusFound) |
312 | return | 332 | return |
313 | } | 333 | } |
314 | 334 | ||
@@ -322,7 +342,7 @@ func GeminiHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
322 | 342 | ||
323 | uri, err := url.QueryUnescape(strings.Join(parts[1:], "/")) | 343 | uri, err := url.QueryUnescape(strings.Join(parts[1:], "/")) |
324 | if err != nil { | 344 | if err != nil { |
325 | tpl.Execute(w, struct { | 345 | if e := tpl.Execute(w, struct { |
326 | Title string | 346 | Title string |
327 | URI string | 347 | URI string |
328 | Assets AssetList | 348 | Assets AssetList |
@@ -330,7 +350,10 @@ func GeminiHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
330 | Lines []Item | 350 | Lines []Item |
331 | Error bool | 351 | Error bool |
332 | Protocol string | 352 | Protocol string |
333 | }{title, hostport, assetList, fmt.Sprintf("Error: %s", err), nil, true, "gemini"}) | 353 | }{title, hostport, assetList, fmt.Sprintf("Error: %s", err), nil, true, "gemini"}); e != nil { |
354 | log.Println("Template error: " + e.Error()) | ||
355 | log.Println(err.Error()) | ||
356 | } | ||
334 | return | 357 | return |
335 | } | 358 | } |
336 | 359 | ||
@@ -348,7 +371,7 @@ func GeminiHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
348 | ) | 371 | ) |
349 | 372 | ||
350 | if err != nil { | 373 | if err != nil { |
351 | tpl.Execute(w, struct { | 374 | if e := tpl.Execute(w, struct { |
352 | Title string | 375 | Title string |
353 | URI string | 376 | URI string |
354 | Assets AssetList | 377 | Assets AssetList |
@@ -356,7 +379,10 @@ func GeminiHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
356 | Lines []Item | 379 | Lines []Item |
357 | Error bool | 380 | Error bool |
358 | Protocol string | 381 | Protocol string |
359 | }{title, fmt.Sprintf("%s/%s", hostport, uri), assetList, fmt.Sprintf("Error: %s", err), nil, true, "gemini"}) | 382 | }{title, fmt.Sprintf("%s/%s", hostport, uri), assetList, fmt.Sprintf("Error: %s", err), nil, true, "gemini"}); e != nil { |
383 | log.Println("Template error: " + e.Error()) | ||
384 | log.Println(err.Error()) | ||
385 | } | ||
360 | return | 386 | return |
361 | } | 387 | } |
362 | 388 | ||
@@ -367,7 +393,7 @@ func GeminiHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
367 | uri, | 393 | uri, |
368 | )) | 394 | )) |
369 | if err != nil { | 395 | if err != nil { |
370 | tpl.Execute(w, struct { | 396 | if e := tpl.Execute(w, struct { |
371 | Title string | 397 | Title string |
372 | URI string | 398 | URI string |
373 | Assets AssetList | 399 | Assets AssetList |
@@ -375,7 +401,10 @@ func GeminiHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
375 | Lines []Item | 401 | Lines []Item |
376 | Error bool | 402 | Error bool |
377 | Protocol string | 403 | Protocol string |
378 | }{title, fmt.Sprintf("%s/%s", hostport, uri), assetList, fmt.Sprintf("Error: %s", err), nil, true, "gemini"}) | 404 | }{title, fmt.Sprintf("%s/%s", hostport, uri), assetList, fmt.Sprintf("Error: %s", err), nil, true, "gemini"}); e != nil { |
405 | log.Println("Template error: " + e.Error()) | ||
406 | log.Println(err.Error()) | ||
407 | } | ||
379 | return | 408 | return |
380 | } | 409 | } |
381 | 410 | ||
@@ -384,7 +413,7 @@ func GeminiHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
384 | } | 413 | } |
385 | 414 | ||
386 | if int(res.Header.Status/10) != 2 { | 415 | if int(res.Header.Status/10) != 2 { |
387 | tpl.Execute(w, struct { | 416 | if err := tpl.Execute(w, struct { |
388 | Title string | 417 | Title string |
389 | URI string | 418 | URI string |
390 | Assets AssetList | 419 | Assets AssetList |
@@ -392,7 +421,9 @@ func GeminiHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
392 | Lines []Item | 421 | Lines []Item |
393 | Error bool | 422 | Error bool |
394 | Protocol string | 423 | Protocol string |
395 | }{title, fmt.Sprintf("%s/%s", hostport, uri), assetList, fmt.Sprintf("Error %d: %s", res.Header.Status, res.Header.Meta), nil, true, "gemini"}) | 424 | }{title, fmt.Sprintf("%s/%s", hostport, uri), assetList, fmt.Sprintf("Error %d: %s", res.Header.Status, res.Header.Meta), nil, true, "gemini"}); err != nil { |
425 | log.Println("Template error: " + err.Error()) | ||
426 | } | ||
396 | return | 427 | return |
397 | } | 428 | } |
398 | 429 | ||
@@ -423,7 +454,7 @@ func GeminiHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
423 | rawText = buf.String() | 454 | rawText = buf.String() |
424 | } | 455 | } |
425 | 456 | ||
426 | tpl.Execute(w, struct { | 457 | if err := tpl.Execute(w, struct { |
427 | Title string | 458 | Title string |
428 | URI string | 459 | URI string |
429 | Assets AssetList | 460 | Assets AssetList |
@@ -431,7 +462,9 @@ func GeminiHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
431 | Lines []Item | 462 | Lines []Item |
432 | Error bool | 463 | Error bool |
433 | Protocol string | 464 | Protocol string |
434 | }{title, fmt.Sprintf("%s/%s", hostport, uri), assetList, rawText, items, false, "gemini"}) | 465 | }{title, fmt.Sprintf("%s/%s", hostport, uri), assetList, rawText, items, false, "gemini"}); err != nil { |
466 | log.Println("Template error: " + err.Error()) | ||
467 | } | ||
435 | } else { | 468 | } else { |
436 | io.Copy(w, res.Body) | 469 | io.Copy(w, res.Body) |
437 | } | 470 | } |
@@ -506,7 +539,7 @@ func FontHandler(woff2 bool, fontdata []byte) http.HandlerFunc { | |||
506 | // specified by the request. The robots argument is a pointer to | 539 | // specified by the request. The robots argument is a pointer to |
507 | // a robotstxt.RobotsData struct for testing user agents against | 540 | // a robotstxt.RobotsData struct for testing user agents against |
508 | // a configurable robots.txt file. | 541 | // a configurable robots.txt file. |
509 | func ListenAndServe(bind, robotsfile string, robotsdebug bool, vipsconcurrency int, uri string) error { | 542 | func ListenAndServe(bind, robotsfile string, robotsdebug bool, vipsconcurrency int) error { |
510 | var ( | 543 | var ( |
511 | tpl *template.Template | 544 | tpl *template.Template |
512 | robotsdata *robotstxt.RobotsData | 545 | robotsdata *robotstxt.RobotsData |
@@ -567,6 +600,12 @@ func ListenAndServe(bind, robotsfile string, robotsdebug bool, vipsconcurrency i | |||
567 | favicondata = []byte{} | 600 | favicondata = []byte{} |
568 | } | 601 | } |
569 | 602 | ||
603 | startpagedata, err := ioutil.ReadFile("startpage.txt") | ||
604 | if err != nil { | ||
605 | startpagedata = []byte{} | ||
606 | } | ||
607 | startpagetext := string(startpagedata) | ||
608 | |||
570 | tpldata, err := ioutil.ReadFile(".template") | 609 | tpldata, err := ioutil.ReadFile(".template") |
571 | if err == nil { | 610 | if err == nil { |
572 | tpltext = string(tpldata) | 611 | tpltext = string(tpldata) |
@@ -622,9 +661,11 @@ func ListenAndServe(bind, robotsfile string, robotsdebug bool, vipsconcurrency i | |||
622 | ConcurrencyLevel: vipsconcurrency, | 661 | ConcurrencyLevel: vipsconcurrency, |
623 | }) | 662 | }) |
624 | 663 | ||
625 | http.Handle("/", gziphandler.GzipHandler(DefaultHandler(tpl, uri))) | 664 | assets := AssetList{styleAsset, jsAsset, fontwAsset, fontw2Asset, propfontwAsset, propfontw2Asset} |
626 | http.Handle("/gopher/", gziphandler.GzipHandler(GopherHandler(tpl, robotsdata, AssetList{styleAsset, jsAsset, fontwAsset, fontw2Asset, propfontwAsset, propfontw2Asset}, robotsdebug, uri))) | 665 | |
627 | http.Handle("/gemini/", gziphandler.GzipHandler(GeminiHandler(tpl, robotsdata, AssetList{styleAsset, jsAsset, fontwAsset, fontw2Asset, propfontwAsset, propfontw2Asset}, robotsdebug, uri))) | 666 | http.Handle("/", gziphandler.GzipHandler(DefaultHandler(tpl, startpagetext, assets))) |
667 | http.Handle("/gopher/", gziphandler.GzipHandler(GopherHandler(tpl, robotsdata, assets, robotsdebug))) | ||
668 | http.Handle("/gemini/", gziphandler.GzipHandler(GeminiHandler(tpl, robotsdata, assets, robotsdebug))) | ||
628 | http.Handle("/robots.txt", gziphandler.GzipHandler(RobotsTxtHandler(robotstxtdata))) | 669 | http.Handle("/robots.txt", gziphandler.GzipHandler(RobotsTxtHandler(robotstxtdata))) |
629 | http.Handle("/favicon.ico", gziphandler.GzipHandler(FaviconHandler(favicondata))) | 670 | http.Handle("/favicon.ico", gziphandler.GzipHandler(FaviconHandler(favicondata))) |
630 | http.Handle(styleAsset, gziphandler.GzipHandler(StyleHandler(styledata))) | 671 | http.Handle(styleAsset, gziphandler.GzipHandler(StyleHandler(styledata))) |