Drop RFC 2696 paging now that the response is attribute-limited
Paging was introduced to work around what looked like a response-size problem, but the actual cause (previous commit) was @ldapjs/asn1's BER decoder choking on a specific oversized attribute value, not overall response size. With attributes now limited to mail/cn/displayName, the whole response is tiny, and paging's extra sequential round-trips on the same connection were themselves causing an ECONNRESET partway through. An unpaged single request+response now matches what a plain ldapsearch against this same AD does successfully. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012o9j9RezxbZVKQMrB7oRLY
This commit is contained in:
1 parent
1e8133ee39
commit
cb20d9eea5
1 file changed
+13
-16
+13
-16
@@ -61,25 +61,22 @@ function search(
|
|||||||
): Promise<{ dn: string; attributes: Record<string, string> }[]> {
|
): Promise<{ dn: string; attributes: Record<string, string> }[]> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const results: { dn: string; attributes: Record<string, string> }[] = [];
|
const results: { dn: string; attributes: Record<string, string> }[] = [];
|
||||||
// Paged (RFC 2696) rather than one unbounded response: a directory-wide
|
// `attributes` is restricted to just what callers actually read
|
||||||
// browse on a real AD domain can return ~1000 entries, and ldapjs's
|
|
||||||
// single-response handling for a batch that size was observed to drop
|
|
||||||
// the connection ("<id> closed") even though a plain `ldapsearch` with
|
|
||||||
// the identical filter completes cleanly — so the fix is on our client's
|
|
||||||
// response handling, not the query itself. ldapjs runs the multi-page
|
|
||||||
// RFC 2696 round-trips internally; callers still just see one continuous
|
|
||||||
// stream of `searchEntry` events followed by a single `end`.
|
|
||||||
//
|
|
||||||
// `attributes` is also restricted to just what callers actually read
|
|
||||||
// (mail/cn/displayName) instead of requesting every attribute AD has on
|
// (mail/cn/displayName) instead of requesting every attribute AD has on
|
||||||
// an object. The real failure turned out to be @ldapjs/asn1's BER
|
// an object. The original failure was @ldapjs/asn1's BER decoder
|
||||||
// decoder throwing "Encoding too long" — a parser desync, most likely
|
// throwing "Encoding too long" — a parser desync, most likely triggered
|
||||||
// triggered while decoding some oversized/exotic AD attribute we never
|
// while decoding some oversized/exotic AD attribute we never use anyway
|
||||||
// use anyway (e.g. nTSecurityDescriptor, msDS-ReplAttributeMetaData).
|
// (e.g. nTSecurityDescriptor, msDS-ReplAttributeMetaData). Not requesting
|
||||||
// Not requesting them sidesteps the bug entirely.
|
// them sidesteps that bug entirely.
|
||||||
|
//
|
||||||
|
// Deliberately NOT using RFC 2696 paging here: with the response now
|
||||||
|
// this much smaller, an unpaged single request+response is simpler and
|
||||||
|
// matches what a plain `ldapsearch` against this same AD does — paging
|
||||||
|
// instead caused ldapjs's multiple sequential requests on one connection
|
||||||
|
// to get an ECONNRESET partway through.
|
||||||
client.search(
|
client.search(
|
||||||
baseDn,
|
baseDn,
|
||||||
{ filter, scope: "sub", paged: { pageSize: 200 }, attributes: ["mail", "cn", "displayName"] },
|
{ filter, scope: "sub", attributes: ["mail", "cn", "displayName"] },
|
||||||
(err, res) => {
|
(err, res) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
reject(describeError(client, err));
|
reject(describeError(client, err));
|
||||||
|
|||||||
Reference in new issue
Block a user