💾 Archived View for source.community › ckaznocha › gemini › raw › main › request.go captured on 2023-07-10 at 13:38:05.
⬅️ Previous capture (2021-12-17)
-=-=-=-=-=-=-
package gemini import ( "bufio" "crypto/x509/pkix" "fmt" "net/textproto" "reflect" "sync" "unsafe" ) const maxRequestLength = 1024 // Request is a Gemini request. type Request struct { Subject *pkix.Name URI *URI RemoteAddr string } var requestPool = sync.Pool{ New: func() interface{} { b := make([]byte, 0, maxRequestLength) return &b }, } // ReadRequest reads and parses a Gemini request from buffer. It returns an // error if the request could not be read or was malformed. func ReadRequest(b *bufio.Reader) (*Request, error) { u, ok := requestPool.Get().(*[]byte) if !ok { return nil, fmt.Errorf("%w: %s", ErrRequestRead, "request pool returned non-byte slice") } defer requestPool.Put(u) sh := (*reflect.SliceHeader)(unsafe.Pointer(u)) //nolint:gosec // This is safe. sh.Len = 0 cr := false for { b, err := b.ReadByte() if err != nil { return nil, fmt.Errorf("%w: %s", ErrRequestRead, err) } if b == '\r' { cr = true continue } if cr && b == '\n' { break } cr = false *u = append(*u, b) if len(*u) > maxRequestLength { return nil, ErrMaxRequestLengthExceeded } } *u = textproto.TrimBytes(*u) uri, err := ParseRequestURI(*(*string)(unsafe.Pointer(u))) //nolint:gosec // This is safe. if err != nil { return nil, err } return &Request{URI: uri}, nil }