1
0
Fork 0
mirror of https://git.sr.ht/~adnano/go-gemini synced 2024-05-07 09:46:15 +02:00

Make Status a type

Using a type is better than using an integer.
This commit is contained in:
Adnan Maolood 2021-02-20 16:15:26 -05:00
parent 99a8f09c22
commit 8938038797
6 changed files with 47 additions and 44 deletions

View File

@ -102,7 +102,7 @@ func do(req *gemini.Request, via []*gemini.Request) (*gemini.Response, error) {
return resp, err return resp, err
} }
switch gemini.StatusClass(resp.Status) { switch resp.Status.Class() {
case gemini.StatusInput: case gemini.StatusInput:
input, ok := getInput(resp.Meta, resp.Status == gemini.StatusSensitiveInput) input, ok := getInput(resp.Meta, resp.Status == gemini.StatusSensitiveInput)
if !ok { if !ok {
@ -155,7 +155,7 @@ func main() {
defer resp.Body.Close() defer resp.Body.Close()
// Handle response // Handle response
if gemini.StatusClass(resp.Status) == gemini.StatusSuccess { if resp.Status.Class() == gemini.StatusSuccess {
body, err := io.ReadAll(resp.Body) body, err := io.ReadAll(resp.Body)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)

View File

@ -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 // RedirectHandler returns a request handler that redirects each request it
// receives to the given url using the given status code. // 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. // StatusRedirect or StatusPermanentRedirect.
func RedirectHandler(code int, url string) Handler { func RedirectHandler(status Status, url string) Handler {
return &redirectHandler{code, url} return &redirectHandler{status, url}
} }
type redirectHandler struct { type redirectHandler struct {
code int status Status
url string url string
} }
func (h *redirectHandler) ServeGemini(ctx context.Context, w ResponseWriter, r *Request) { 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. // NotFound replies to the request with a Gemini 51 not found error.

View File

@ -18,7 +18,7 @@ const defaultMediaType = "text/gemini; charset=utf-8"
// as the Body field is read. // as the Body field is read.
type Response struct { type Response struct {
// Status contains the response status code. // Status contains the response status code.
Status int Status Status
// Meta contains more information related to the response status. // Meta contains more information related to the response status.
// For successful responses, Meta should contain the media type of the response. // 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 { if err != nil {
return nil, ErrInvalidResponse return nil, ErrInvalidResponse
} }
resp.Status = status resp.Status = Status(status)
// Read one space // Read one space
if b, err := br.ReadByte(); err != nil { if b, err := br.ReadByte(); err != nil {
@ -77,7 +77,7 @@ func ReadResponse(rc io.ReadCloser) (*Response, error) {
if len(meta) > 1024 { if len(meta) > 1024 {
return nil, ErrInvalidResponse return nil, ErrInvalidResponse
} }
if StatusClass(status) == StatusSuccess && meta == "" { if resp.Status.Class() == StatusSuccess && meta == "" {
// Use default media type // Use default media type
meta = defaultMediaType meta = defaultMediaType
} }
@ -90,7 +90,7 @@ func ReadResponse(rc io.ReadCloser) (*Response, error) {
return nil, ErrInvalidResponse return nil, ErrInvalidResponse
} }
if StatusClass(status) == StatusSuccess { if resp.Status.Class() == StatusSuccess {
resp.Body = newReadCloserBody(br, rc) resp.Body = newReadCloserBody(br, rc)
} else { } else {
resp.Body = nopReadCloser{} resp.Body = nopReadCloser{}
@ -186,7 +186,7 @@ type ResponseWriter interface {
// The provided code must be a valid Gemini status code. // The provided code must be a valid Gemini status code.
// The provided meta must not be longer than 1024 bytes. // The provided meta must not be longer than 1024 bytes.
// Only one header may be written. // 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 // 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) return w.b.Write(b)
} }
func (w *responseWriter) WriteHeader(status int, meta string) { func (w *responseWriter) WriteHeader(status Status, meta string) {
if w.wroteHeader { if w.wroteHeader {
return return
} }
if StatusClass(status) == StatusSuccess { if status.Class() == StatusSuccess {
w.bodyAllowed = true w.bodyAllowed = true
} }
w.b.WriteString(strconv.Itoa(status)) w.b.WriteString(strconv.Itoa(int(status)))
w.b.WriteByte(' ') w.b.WriteByte(' ')
w.b.WriteString(meta) w.b.WriteString(meta)
w.b.Write(crlf) w.b.Write(crlf)

View File

@ -9,7 +9,7 @@ import (
func TestReadWriteResponse(t *testing.T) { func TestReadWriteResponse(t *testing.T) {
tests := []struct { tests := []struct {
Raw string Raw string
Status int Status Status
Meta string Meta string
Body string Body string
Err error Err error

View File

@ -1,37 +1,40 @@
package gemini package gemini
// Status represents a Gemini status code.
type Status int
// Gemini status codes. // Gemini status codes.
const ( const (
StatusInput = 10 StatusInput Status = 10
StatusSensitiveInput = 11 StatusSensitiveInput Status = 11
StatusSuccess = 20 StatusSuccess Status = 20
StatusRedirect = 30 StatusRedirect Status = 30
StatusPermanentRedirect = 31 StatusPermanentRedirect Status = 31
StatusTemporaryFailure = 40 StatusTemporaryFailure Status = 40
StatusServerUnavailable = 41 StatusServerUnavailable Status = 41
StatusCGIError = 42 StatusCGIError Status = 42
StatusProxyError = 43 StatusProxyError Status = 43
StatusSlowDown = 44 StatusSlowDown Status = 44
StatusPermanentFailure = 50 StatusPermanentFailure Status = 50
StatusNotFound = 51 StatusNotFound Status = 51
StatusGone = 52 StatusGone Status = 52
StatusProxyRequestRefused = 53 StatusProxyRequestRefused Status = 53
StatusBadRequest = 59 StatusBadRequest Status = 59
StatusCertificateRequired = 60 StatusCertificateRequired Status = 60
StatusCertificateNotAuthorized = 61 StatusCertificateNotAuthorized Status = 61
StatusCertificateNotValid = 62 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. // 1x becomes 10, 2x becomes 20, and so on.
func StatusClass(code int) int { func (s Status) Class() Status {
return (code / 10) * 10 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. // It returns the empty string if the status code is unknown.
func StatusText(code int) string { func (s Status) String() string {
switch code { switch s {
case StatusInput: case StatusInput:
return "Input" return "Input"
case StatusSensitiveInput: case StatusSensitiveInput:

View File

@ -66,7 +66,7 @@ func (t *timeoutHandler) ServeGemini(ctx context.Context, w ResponseWriter, r *R
type timeoutWriter struct { type timeoutWriter struct {
mu sync.Mutex mu sync.Mutex
b bytes.Buffer b bytes.Buffer
status int status Status
meta string meta string
mediatype string mediatype string
wroteHeader bool wroteHeader bool
@ -91,7 +91,7 @@ func (w *timeoutWriter) Write(b []byte) (int, error) {
return w.b.Write(b) return w.b.Write(b)
} }
func (w *timeoutWriter) WriteHeader(status int, meta string) { func (w *timeoutWriter) WriteHeader(status Status, meta string) {
w.mu.Lock() w.mu.Lock()
defer w.mu.Unlock() defer w.mu.Unlock()
if w.timedOut { if w.timedOut {
@ -100,7 +100,7 @@ func (w *timeoutWriter) WriteHeader(status int, meta string) {
w.writeHeaderLocked(status, meta) w.writeHeaderLocked(status, meta)
} }
func (w *timeoutWriter) writeHeaderLocked(status int, meta string) { func (w *timeoutWriter) writeHeaderLocked(status Status, meta string) {
if w.wroteHeader { if w.wroteHeader {
return return
} }