diff options
Diffstat (limited to 'gemini/response.go')
-rw-r--r-- | gemini/response.go | 35 |
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() |