aboutsummaryrefslogtreecommitdiffstats
path: root/gopherproxy.go
diff options
context:
space:
mode:
authorFeuerfuchs <git@feuerfuchs.dev>2019-11-17 10:14:58 +0100
committerFeuerfuchs <git@feuerfuchs.dev>2019-11-17 10:14:58 +0100
commite85a6b1c934d1070e40d11ad94b3ad4d79bdc9b2 (patch)
tree66613d0dac2581b117d17879af9c24b31d6f0af7 /gopherproxy.go
parentRemove obsolete vars from libgemini (diff)
downloadgopherproxy-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.go97
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
180func DefaultHandler(tpl *template.Template, uri string) http.HandlerFunc { 180func 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.
191func GopherHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, assetList AssetList, robotsdebug bool, uri string) http.HandlerFunc { 201func 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
298func GeminiHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, assetList AssetList, robotsdebug bool, uri string) http.HandlerFunc { 318func 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.
509func ListenAndServe(bind, robotsfile string, robotsdebug bool, vipsconcurrency int, uri string) error { 542func 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)))