1
0
Fork 0
mirror of https://git.sr.ht/~adnano/go-gemini synced 2024-04-26 15:55:23 +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
}
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)

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
// 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.

View File

@ -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)

View File

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

View File

@ -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:

View File

@ -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
}