package spartan import ( "bufio" "errors" "io" "net/url" "strconv" "strings" "tildegit.org/tjp/gus" ) var ( // InvalidRequestLine indicates a malformed first-line of a spartan request. InvalidRequestLine = errors.New("invalid request line") // InvalidRequestLineEnding says that a spartan request's first line wasn't terminated with CRLF. InvalidRequestLineEnding = errors.New("invalid request line ending") ) // ParseRequest parses a single spartan request and the indicated content-length from a reader. // // If ther reader artument is a *bufio.Reader, it will only read a single line from it. func ParseRequest(rdr io.Reader) (*gus.Request, int, error) { bufrdr, ok := rdr.(*bufio.Reader) if !ok { bufrdr = bufio.NewReader(rdr) } line, err := bufrdr.ReadString('\n') if err != io.EOF && err != nil { return nil, 0, err } host, rest, ok := strings.Cut(line, " ") if !ok { return nil, 0, InvalidRequestLine } path, rest, ok := strings.Cut(line, " ") if !ok { return nil, 0, InvalidRequestLine } if len(rest) < 2 || line[len(line)-2:] != "\r\n" { return nil, 0, InvalidRequestLineEnding } contentlen, err := strconv.Atoi(line[:len(line)-2]) if err != nil { return nil, 0, err } return &gus.Request{ URL: &url.URL{ Scheme: "spartan", Host: host, Path: path, RawPath: path, }, }, contentlen, nil }