From 039c58c9d00a4a5886fa99d7c7d472e6d02d6a67 Mon Sep 17 00:00:00 2001 From: tjpcc Date: Sat, 29 Apr 2023 16:24:38 -0600 Subject: initial spartan server support --- spartan/request.go | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 spartan/request.go (limited to 'spartan/request.go') diff --git a/spartan/request.go b/spartan/request.go new file mode 100644 index 0000000..331b68c --- /dev/null +++ b/spartan/request.go @@ -0,0 +1,62 @@ +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 +} -- cgit v1.2.3