mirror of
https://github.com/soypat/lneto.git
synced 2026-08-20 06:29:03 +00:00
add Go's ServeMux Request.PathValue access semantics to Exchange, Mux and MuxSlice
This commit is contained in:
@@ -22,6 +22,9 @@ func (f *Form) Reset(buf []byte, capKV int) {
|
||||
// ParseBytes copies the argument bytes to the Form's underlying buffer and parses them.
|
||||
func (f *Form) ParseBytes(b []byte) error {
|
||||
f.Reset(nil, 0)
|
||||
if len(b) == 0 {
|
||||
return nil // An empty body is an empty form, not a failure to read one.
|
||||
}
|
||||
err := f.kv.ReadFromBytes(b)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -54,7 +57,7 @@ func (f *Form) Decode() error {
|
||||
return err
|
||||
} else if len(v) == 0 {
|
||||
if nk != len(k) {
|
||||
f.kv.setAt(i, k, v)
|
||||
f.kv.setAt(i, k[:nk], v) // k[:nk]: the decoded key is shorter.
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -66,6 +66,29 @@ func TestFormDecode(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Decoding a valueless key that shrinks must rewrite the key without inventing
|
||||
// a value: the pair has no '=' before Decode and must have none after.
|
||||
func TestFormDecodeValuelessKeyShrinks(t *testing.T) {
|
||||
var f Form
|
||||
const body = "a=1&o%6Bay"
|
||||
if err := f.ParseBytes([]byte(body)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := f.Decode(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
const want = "a=1|okay"
|
||||
if got := render(&f); got != want {
|
||||
t.Errorf("want %q, got %q", want, got)
|
||||
}
|
||||
if _, value := f.Pair(1); value != nil {
|
||||
t.Errorf("want valueless pair to stay valueless, got value %q", value)
|
||||
}
|
||||
if !f.Has("okay") {
|
||||
t.Error("want decoded valueless key present")
|
||||
}
|
||||
}
|
||||
|
||||
// A malformed escape must be reported, never silently passed through.
|
||||
func TestFormDecodeMalformed(t *testing.T) {
|
||||
for _, body := range []string{"q=%zz", "%zz=v", "q=%4"} {
|
||||
|
||||
@@ -241,49 +241,11 @@ func (h *Header) SetInt(key string, value int64, base int) {
|
||||
// Calling Set mangles the buffer.
|
||||
func (h *Header) Set(key, value string) (enoughSpace bool) {
|
||||
return h.hbuf.kv.Set(key, value)
|
||||
|
||||
// useKv := h.takeReusableSlot(key)
|
||||
// if useKv == nil {
|
||||
// h.hbuf.kv.appendPair(key, value)
|
||||
// } else {
|
||||
// useKv.value = h.hbuf.kv.reuseOrAppend(useKv.value, value)
|
||||
// }
|
||||
}
|
||||
|
||||
// takeReusableSlot returns the valid key-value entry for key with the largest
|
||||
// value buffer (best candidate for in-place reuse) and invalidates any other
|
||||
// entries sharing the key. Returns nil if the key is not present.
|
||||
func (h *Header) takeReusableSlot(key string) *argsKV {
|
||||
// hb := &h.hbuf
|
||||
var useKv *argsKV
|
||||
// for i := 0; i < len(hb.headers); i++ {
|
||||
// // Search for key-value with largest buffer for value to store value reusing buffer.
|
||||
// gotkv := &hb.headers[i]
|
||||
// if gotkv.isValidHeader() && b2s(hb.musttoken(gotkv.key)) == key {
|
||||
// if useKv == nil {
|
||||
// useKv = gotkv
|
||||
// } else if gotkv.value.len > useKv.value.len {
|
||||
// useKv.invalidate()
|
||||
// useKv = gotkv
|
||||
// } else {
|
||||
// gotkv.invalidate()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
return useKv
|
||||
}
|
||||
|
||||
// Get gets the first exact-match value of a key found in the headers. Use [Header.ForEach] to find multiple values corresponding to same key.
|
||||
func (h *Header) Get(key string) []byte {
|
||||
return h.hbuf.kv.Get(key)
|
||||
// debuglog("http:get:start")
|
||||
// kv := h.peekHeader(key)
|
||||
// if kv.isValidHeader() {
|
||||
// debuglog("http:get:found")
|
||||
// return h.hbuf.musttoken(kv.value)
|
||||
// }
|
||||
// debuglog("http:get:notfound")
|
||||
// return nil
|
||||
}
|
||||
|
||||
// GetFold gets the first value whose key matches key under ASCII case-insensitive
|
||||
|
||||
@@ -225,9 +225,11 @@ func (mb *KVBuffer) At(i int) (key, value []byte) {
|
||||
}
|
||||
func (mb *KVBuffer) setAt(i int, k, v []byte) {
|
||||
mb.flags |= flagMangledBuffer
|
||||
// Route through slice, not bytes2tok: a nil v is a pair with no '=' and must
|
||||
// stay absent rather than trip the alias check on a nil pointer.
|
||||
mb.kvs[i] = argsKV{
|
||||
key: bytes2tok(mb.buf, k),
|
||||
value: bytes2tok(mb.buf, v),
|
||||
key: mb.slice(k),
|
||||
value: mb.slice(v),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,10 +12,10 @@ var (
|
||||
errNoProto = errors.New("missing protocol, HTTP/0.9 unsupported")
|
||||
// ErrNeedMoreData signals a parser was handed an incomplete buffer: append
|
||||
// more data to it and call again.
|
||||
ErrNeedMoreData = errors.New("need more data: cannot find trailing lf/delimiter")
|
||||
errNoBoundary = errors.New("httpraw: multipart boundary not set")
|
||||
errUnparsed = errors.New("need to finish parsing")
|
||||
errInvalidName = errors.New("invalid header name")
|
||||
ErrNeedMoreData = errors.New("need more data: cannot find trailing lf/delimiter")
|
||||
errNoBoundary = errors.New("httpraw: multipart boundary not set")
|
||||
errUnparsed = errors.New("need to finish parsing")
|
||||
errInvalidName = errors.New("invalid header name")
|
||||
// ErrBufferExhausted signals a buffer with no room left for the data being
|
||||
// written and no permission to grow, see [KVBuffer.EnableBufferGrowth].
|
||||
// Enlarging the buffer handed to Reset is the only fix; a server answers it
|
||||
|
||||
Reference in New Issue
Block a user