Add missing error handling

Error handling is currently missing is a couple of places. Most of
them are i/o related.

This change adds checks, an therefore sometimes also has to change
function signatures by adding an error return value. In the case of
the response writer the status and meta handling is changed and this
also breaks the API.

In some places where we don't have any reasonable I've added
assignment to a blank identifier to make it clear that we're ignoring
an error.

text: read the Err() that can be set by the scanner.

client: check if conn.SetDeadline() returns an error.

client: check if req.Write() returns an error.

fs: panic if mime type registration fails.

server: stop performing i/o in Header/Status functions

By deferring the actual header write to the first Write() or Flush()
call we don't have to do any error handling in Header() or Status().

As Server.respond() now defers a ResponseWriter.Flush() instead of
directly flushing the underlying bufio.Writer this has the added
benefit of ensuring that we always write a header
to the client, even if the responder is a complete NOOP.

tofu: return an error if we fail to write to the known hosts writer.
This commit is contained in:
Hugo Wetterberg
2021-01-07 23:08:50 +01:00
committed by Adnan Maolood
parent efef44c2f9
commit f2921a396f
6 changed files with 107 additions and 47 deletions

18
fs.go
View File

@@ -1,6 +1,7 @@
package gemini
import (
"fmt"
"io"
"mime"
"os"
@@ -9,8 +10,13 @@ import (
func init() {
// Add Gemini mime types
mime.AddExtensionType(".gmi", "text/gemini")
mime.AddExtensionType(".gemini", "text/gemini")
if err := mime.AddExtensionType(".gmi", "text/gemini"); err != nil {
panic(fmt.Errorf("failed to register .gmi extension mimetype: %w", err))
}
if err := mime.AddExtensionType(".gemini", "text/gemini"); err != nil {
panic(fmt.Errorf("failed to register .gemini extension mimetype: %w", err))
}
}
// FileServer takes a filesystem and returns a Responder which uses that filesystem.
@@ -27,7 +33,7 @@ func (fsh fsHandler) Respond(w *ResponseWriter, r *Request) {
p := path.Clean(r.URL.Path)
f, err := fsh.Open(p)
if err != nil {
w.WriteStatus(StatusNotFound)
w.Status(StatusNotFound)
return
}
// Detect mimetype
@@ -35,7 +41,7 @@ func (fsh fsHandler) Respond(w *ResponseWriter, r *Request) {
mimetype := mime.TypeByExtension(ext)
w.SetMediaType(mimetype)
// Copy file to response writer
io.Copy(w, f)
_, _ = io.Copy(w, f)
}
// TODO: replace with io/fs.FS when available
@@ -66,7 +72,7 @@ func (d Dir) Open(name string) (File, error) {
func ServeFile(w *ResponseWriter, fs FS, name string) {
f, err := fs.Open(name)
if err != nil {
w.WriteStatus(StatusNotFound)
w.Status(StatusNotFound)
return
}
// Detect mimetype
@@ -74,7 +80,7 @@ func ServeFile(w *ResponseWriter, fs FS, name string) {
mimetype := mime.TypeByExtension(ext)
w.SetMediaType(mimetype)
// Copy file to response writer
io.Copy(w, f)
_, _ = io.Copy(w, f)
}
func openFile(p string) (File, error) {