summaryrefslogtreecommitdiff
path: root/gemini/response.go
diff options
context:
space:
mode:
Diffstat (limited to 'gemini/response.go')
-rw-r--r--gemini/response.go35
1 files changed, 35 insertions, 0 deletions
diff --git a/gemini/response.go b/gemini/response.go
index 90340a5..478913b 100644
--- a/gemini/response.go
+++ b/gemini/response.go
@@ -1,7 +1,9 @@
package gemini
import (
+ "bufio"
"bytes"
+ "errors"
"io"
"strconv"
)
@@ -262,6 +264,39 @@ func CertInvalid(msg string) *Response {
}
}
+// InvalidResponseLineEnding indicates that a gemini response header didn't end with "\r\n".
+var InvalidResponseLineEnding = errors.New("Invalid response line ending.")
+
+// InvalidResponseHeaderLine indicates a malformed gemini response header line.
+var InvalidResponseHeaderLine = errors.New("Invalid response header line.")
+
+// ParseResponse parses a complete gemini response from a reader.
+//
+// The reader must contain only one gemini response.
+func ParseResponse(rdr io.Reader) (*Response, error) {
+ bufrdr := bufio.NewReader(rdr)
+
+ hdrLine, err := bufrdr.ReadBytes('\n')
+ if err != nil {
+ return nil, InvalidResponseLineEnding
+ }
+ if hdrLine[len(hdrLine)-2] != '\r' {
+ return nil, InvalidResponseLineEnding
+ }
+ hdrLine = hdrLine[:len(hdrLine)-2]
+
+ status, err := strconv.Atoi(string(hdrLine[:2]))
+ if err != nil {
+ return nil, InvalidResponseHeaderLine
+ }
+
+ return &Response{
+ Status: Status(status),
+ Meta: string(hdrLine[2:]),
+ Body: bufrdr,
+ }, nil
+}
+
// Read implements io.Reader for Response.
func (r *Response) Read(b []byte) (int, error) {
r.ensureReader()