aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdnan Maolood <[email protected]>2021-02-20 16:15:26 -0500
committerAdnan Maolood <[email protected]>2021-02-20 16:16:32 -0500
commit893803879742057befabc4f6b5d4d412ac6612b6 (patch)
tree6d873d5645af6cbc4332f618e5950568bc1df486
parentTimeoutHandler: Use provided context (diff)
downloadgo-gemini-893803879742057befabc4f6b5d4d412ac6612b6.tar.xz
go-gemini-893803879742057befabc4f6b5d4d412ac6612b6.zip
Make Status a type
Using a type is better than using an integer.
-rw-r--r--examples/client.go4
-rw-r--r--handler.go12
-rw-r--r--response.go16
-rw-r--r--response_test.go2
-rw-r--r--status.go51
-rw-r--r--timeout.go6
6 files changed, 47 insertions, 44 deletions
diff --git a/examples/client.go b/examples/client.go
index 21f09c5..c806a8f 100644
--- a/examples/client.go
+++ b/examples/client.go
@@ -102,7 +102,7 @@ func do(req *gemini.Request, via []*gemini.Request) (*gemini.Response, error) {
return resp, err
}
- switch gemini.StatusClass(resp.Status) {
+ switch resp.Status.Class() {
case gemini.StatusInput:
input, ok := getInput(resp.Meta, resp.Status == gemini.StatusSensitiveInput)
if !ok {
@@ -155,7 +155,7 @@ func main() {
defer resp.Body.Close()
// Handle response
- if gemini.StatusClass(resp.Status) == gemini.StatusSuccess {
+ if resp.Status.Class() == gemini.StatusSuccess {
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
diff --git a/handler.go b/handler.go
index a85ba3c..5698e88 100644
--- a/handler.go
+++ b/handler.go
@@ -38,19 +38,19 @@ func (f HandlerFunc) ServeGemini(ctx context.Context, w ResponseWriter, r *Reque
// RedirectHandler returns a request handler that redirects each request it
// receives to the given url using the given status code.
//
-// The provided code should be in the 3x range and is usually
+// The provided status code should be in the 3x range and is usually
// StatusRedirect or StatusPermanentRedirect.
-func RedirectHandler(code int, url string) Handler {
- return &redirectHandler{code, url}
+func RedirectHandler(status Status, url string) Handler {
+ return &redirectHandler{status, url}
}
type redirectHandler struct {
- code int
- url string
+ status Status
+ url string
}
func (h *redirectHandler) ServeGemini(ctx context.Context, w ResponseWriter, r *Request) {
- w.WriteHeader(h.code, h.url)
+ w.WriteHeader(h.status, h.url)
}
// NotFound replies to the request with a Gemini 51 not found error.
diff --git a/response.go b/response.go
index 17e2155..d62b8cf 100644
--- a/response.go
+++ b/response.go
@@ -18,7 +18,7 @@ const defaultMediaType = "text/gemini; charset=utf-8"
// as the Body field is read.
type Response struct {
// Status contains the response status code.
- Status int
+ Status Status
// Meta contains more information related to the response status.
// For successful responses, Meta should contain the media type of the response.
@@ -57,7 +57,7 @@ func ReadResponse(rc io.ReadCloser) (*Response, error) {
if err != nil {
return nil, ErrInvalidResponse
}
- resp.Status = status
+ resp.Status = Status(status)
// Read one space
if b, err := br.ReadByte(); err != nil {
@@ -77,7 +77,7 @@ func ReadResponse(rc io.ReadCloser) (*Response, error) {
if len(meta) > 1024 {
return nil, ErrInvalidResponse
}
- if StatusClass(status) == StatusSuccess && meta == "" {
+ if resp.Status.Class() == StatusSuccess && meta == "" {
// Use default media type
meta = defaultMediaType
}
@@ -90,7 +90,7 @@ func ReadResponse(rc io.ReadCloser) (*Response, error) {
return nil, ErrInvalidResponse
}
- if StatusClass(status) == StatusSuccess {
+ if resp.Status.Class() == StatusSuccess {
resp.Body = newReadCloserBody(br, rc)
} else {
resp.Body = nopReadCloser{}
@@ -186,7 +186,7 @@ type ResponseWriter interface {
// The provided code must be a valid Gemini status code.
// The provided meta must not be longer than 1024 bytes.
// Only one header may be written.
- WriteHeader(status int, meta string)
+ WriteHeader(status Status, meta string)
}
// The Flusher interface is implemented by ResponseWriters that allow a
@@ -237,16 +237,16 @@ func (w *responseWriter) Write(b []byte) (int, error) {
return w.b.Write(b)
}
-func (w *responseWriter) WriteHeader(status int, meta string) {
+func (w *responseWriter) WriteHeader(status Status, meta string) {
if w.wroteHeader {
return
}
- if StatusClass(status) == StatusSuccess {
+ if status.Class() == StatusSuccess {
w.bodyAllowed = true
}
- w.b.WriteString(strconv.Itoa(status))
+ w.b.WriteString(strconv.Itoa(int(status)))
w.b.WriteByte(' ')
w.b.WriteString(meta)
w.b.Write(crlf)
diff --git a/response_test.go b/response_test.go
index 889e1ab..a6226ee 100644
--- a/response_test.go
+++ b/response_test.go
@@ -9,7 +9,7 @@ import (
func TestReadWriteResponse(t *testing.T) {
tests := []struct {
Raw string
- Status int
+ Status Status
Meta string
Body string
Err error
diff --git a/status.go b/status.go
index 45eaed4..6e4f1bb 100644
--- a/status.go
+++ b/status.go
@@ -1,37 +1,40 @@
package gemini
+// Status represents a Gemini status code.
+type Status int
+
// Gemini status codes.
const (
- StatusInput = 10
- StatusSensitiveInput = 11
- StatusSuccess = 20
- StatusRedirect = 30
- StatusPermanentRedirect = 31
- StatusTemporaryFailure = 40
- StatusServerUnavailable = 41
- StatusCGIError = 42
- StatusProxyError = 43
- StatusSlowDown = 44
- StatusPermanentFailure = 50
- StatusNotFound = 51
- StatusGone = 52
- StatusProxyRequestRefused = 53
- StatusBadRequest = 59
- StatusCertificateRequired = 60
- StatusCertificateNotAuthorized = 61
- StatusCertificateNotValid = 62
+ StatusInput Status = 10
+ StatusSensitiveInput Status = 11
+ StatusSuccess Status = 20
+ StatusRedirect Status = 30
+ StatusPermanentRedirect Status = 31
+ StatusTemporaryFailure Status = 40
+ StatusServerUnavailable Status = 41
+ StatusCGIError Status = 42
+ StatusProxyError Status = 43
+ StatusSlowDown Status = 44
+ StatusPermanentFailure Status = 50
+ StatusNotFound Status = 51
+ StatusGone Status = 52
+ StatusProxyRequestRefused Status = 53
+ StatusBadRequest Status = 59
+ StatusCertificateRequired Status = 60
+ StatusCertificateNotAuthorized Status = 61
+ StatusCertificateNotValid Status = 62
)
-// StatusClass returns the status class for the provided status code.
+// Class returns the status class for the status code.
// 1x becomes 10, 2x becomes 20, and so on.
-func StatusClass(code int) int {
- return (code / 10) * 10
+func (s Status) Class() Status {
+ return (s / 10) * 10
}
-// StatusText returns a text for the provided status code.
+// String returns a text for the status code.
// It returns the empty string if the status code is unknown.
-func StatusText(code int) string {
- switch code {
+func (s Status) String() string {
+ switch s {
case StatusInput:
return "Input"
case StatusSensitiveInput:
diff --git a/timeout.go b/timeout.go
index 9d3dab6..b23a895 100644
--- a/timeout.go
+++ b/timeout.go
@@ -66,7 +66,7 @@ func (t *timeoutHandler) ServeGemini(ctx context.Context, w ResponseWriter, r *R
type timeoutWriter struct {
mu sync.Mutex
b bytes.Buffer
- status int
+ status Status
meta string
mediatype string
wroteHeader bool
@@ -91,7 +91,7 @@ func (w *timeoutWriter) Write(b []byte) (int, error) {
return w.b.Write(b)
}
-func (w *timeoutWriter) WriteHeader(status int, meta string) {
+func (w *timeoutWriter) WriteHeader(status Status, meta string) {
w.mu.Lock()
defer w.mu.Unlock()
if w.timedOut {
@@ -100,7 +100,7 @@ func (w *timeoutWriter) WriteHeader(status int, meta string) {
w.writeHeaderLocked(status, meta)
}
-func (w *timeoutWriter) writeHeaderLocked(status int, meta string) {
+func (w *timeoutWriter) writeHeaderLocked(status Status, meta string) {
if w.wroteHeader {
return
}