tomas / needle

Nimble, streamable HTTP client for Node.js. With proxy, iconv, cookie, deflate & multipart support.
https://www.npmjs.com/package/needle
MIT License
1.63k stars 236 forks source link

Digest MD5 not working with Geovision IP Camera #423

Open samidalati opened 1 year ago

samidalati commented 1 year ago

I have been trying to get this HTTP request to work using Needle without luck. The HTTP request works using Postman and Axos-digest but not using Needle. However, Needle works with other IP cameras we have. I m using v3.2.0

Code:

var opts = {
  username: 'username',
  password: 'password',
  auth: 'digest'
}

needle.get('http://192.168.1.199:80/LAPI/V1.0/Media/Video/Streams/0/Snapshot', opts, function(err, resp, body) {
  console.log(resp.headers);

  if (resp.statusCode == 401)
    console.log('\nIt failed.')
  else
    console.log('\nIt worked!')
});

Here is the log:

******** resp:  <ref *2> IncomingMessage {
  _readableState: ReadableState {
    objectMode: false,
    highWaterMark: 16384,
    buffer: BufferList { head: null, tail: null, length: 0 },
    length: 0,
    pipes: [],
    flowing: false,
    ended: true,
    endEmitted: true,
    reading: false,
    constructed: true,
    sync: true,
    needReadable: false,
    emittedReadable: false,
    readableListening: false,
    resumeScheduled: false,
    errorEmitted: false,
    emitClose: true,
    autoDestroy: true,
    destroyed: true,
    errored: null,
    closed: true,
    closeEmitted: true,
    defaultEncoding: 'utf8',
    awaitDrainWriters: SafeSet(0) [Set] {},
    multiAwaitDrain: true,
    readingMore: true,
    dataEmitted: true,
    decoder: null,
    encoding: null,
    [Symbol(kPaused)]: true
  },
  _events: [Object: null prototype] {
    end: [ [Function: responseOnEnd], [Function: onend], [Function: onend] ],
    close: [
      [Function (anonymous)],
      [Function: onclose],
      [Function (anonymous)],
      [Function: onclose]
    ],
    finish: [ [Function: onfinish], [Function: onfinish] ],
    error: [ [Function: onerror], [Function: onerror] ]
  },
  _eventsCount: 4,
  _maxListeners: undefined,
  socket: <ref *1> Socket {
    connecting: false,
    _hadError: false,
    _parent: null,
    _host: null,
    _readableState: ReadableState {
      objectMode: false,
      highWaterMark: 16384,
      buffer: BufferList { head: null, tail: null, length: 0 },
      length: 0,
      pipes: [],
      flowing: true,
      ended: false,
      endEmitted: false,
      reading: true,
      constructed: true,
      sync: false,
      needReadable: true,
      emittedReadable: false,
      readableListening: false,
      resumeScheduled: false,
      errorEmitted: false,
      emitClose: false,
      autoDestroy: true,
      destroyed: false,
      errored: null,
      closed: false,
      closeEmitted: false,
      defaultEncoding: 'utf8',
      awaitDrainWriters: null,
      multiAwaitDrain: false,
      readingMore: false,
      dataEmitted: true,
      decoder: null,
      encoding: null,
      [Symbol(kPaused)]: false
    },
    _events: [Object: null prototype] {
      end: [Function: onReadableStreamEnd],
      free: [Function: onFree],
      close: [Array],
      timeout: [Function: onTimeout],
      agentRemove: [Function: onRemove],
      error: [Function: socketErrorListener],
      finish: [Function]
    },
    _eventsCount: 7,
    _maxListeners: undefined,
    _writableState: WritableState {
      objectMode: false,
      highWaterMark: 16384,
      finalCalled: true,
      needDrain: false,
      ending: true,
      ended: true,
      finished: false,
      destroyed: false,
      decodeStrings: false,
      defaultEncoding: 'utf8',
      length: 0,
      writing: false,
      corked: 0,
      sync: false,
      bufferProcessing: false,
      onwrite: [Function: bound onwrite],
      writecb: null,
      writelen: 0,
      afterWriteTickInfo: null,
      buffered: [],
      bufferedIndex: 0,
      allBuffers: true,
      allNoop: true,
      pendingcb: 1,
      constructed: true,
      prefinished: false,
      errorEmitted: false,
      emitClose: false,
      autoDestroy: true,
      errored: null,
      closed: false,
      closeEmitted: false,
      [Symbol(kOnFinished)]: []
    },
    allowHalfOpen: false,
    _sockname: null,
    _pendingData: null,
    _pendingEncoding: '',
    server: null,
    _server: null,
    parser: null,
    _httpMessage: ClientRequest {
      _events: [Object: null prototype],
      _eventsCount: 3,
      _maxListeners: undefined,
      outputData: [],
      outputSize: 0,
      writable: true,
      destroyed: false,
      _last: true,
      chunkedEncoding: false,
      shouldKeepAlive: false,
      maxRequestsOnConnectionReached: false,
      _defaultKeepAlive: true,
      useChunkedEncodingByDefault: false,
      sendDate: false,
      _removedConnection: false,
      _removedContLen: false,
      _removedTE: false,
      _contentLength: 0,
      _hasBody: true,
      _trailer: '',
      finished: true,
      _headerSent: true,
      _closed: false,
      socket: [Circular *1],
      _header: 'GET /LAPI/V1.0/Media/Video/Streams/0/Snapshot HTTP/1.1\r\n' +
        'accept: */*\r\n' +
        'user-agent: Needle/3.2.0 (Node.js v16.15.0; darwin arm64)\r\n' +
        'host: 192.168.1.199\r\n' +
        'authorization: Digest uri="/LAPI/V1.0/Media/Video/Streams/0/Snapshot", realm="0013e22cfbf8", nonce="9dd2edda3baca2e7a5b859fb440f71ca", username="brizi", response="e156f4df8c197a301f316b38e48bf631", qop="auth", opaque="07c984bd79faee74498abe2331d5e8db", nc="00000002", cnonce="c8657603"\r\n' +
        'Connection: close\r\n' +
        '\r\n',
      _keepAliveTimeout: 0,
      _onPendingData: [Function: nop],
      agent: [Agent],
      socketPath: undefined,
      method: 'GET',
      maxHeaderSize: undefined,
      insecureHTTPParser: undefined,
      path: '/LAPI/V1.0/Media/Video/Streams/0/Snapshot',
      _ended: true,
      res: [Circular *2],
      aborted: false,
      timeoutCb: null,
      upgradeOrConnect: false,
      parser: null,
      maxHeadersCount: null,
      reusedSocket: false,
      host: '192.168.1.199',
      protocol: 'http:',
      [Symbol(kCapture)]: false,
      [Symbol(kNeedDrain)]: false,
      [Symbol(corked)]: 0,
      [Symbol(kOutHeaders)]: [Object: null prototype]
    },
    [Symbol(async_id_symbol)]: 286,
    [Symbol(kHandle)]: TCP {
      reading: true,
      onconnection: null,
      [Symbol(owner_symbol)]: [Circular *1]
    },
    [Symbol(lastWriteQueueSize)]: 0,
    [Symbol(timeout)]: null,
    [Symbol(kBuffer)]: null,
    [Symbol(kBufferCb)]: null,
    [Symbol(kBufferGen)]: null,
    [Symbol(kCapture)]: false,
    [Symbol(kSetNoDelay)]: false,
    [Symbol(kSetKeepAlive)]: false,
    [Symbol(kSetKeepAliveInitialDelay)]: 0,
    [Symbol(kBytesRead)]: 0,
    [Symbol(kBytesWritten)]: 0,
    [Symbol(RequestTimeout)]: undefined
  },
  httpVersionMajor: 1,
  httpVersionMinor: 1,
  httpVersion: '1.1',
  complete: true,
  rawHeaders: [
    'Content-Length',
    '243',
    'Content-Type',
    'text/plain',
    'Connection',
    'close',
    'WWW-Authenticate',
    'Digest realm="0013e22cfbf8", nonce="9dd2edda3baca2e7a5b859fb440f71ca", stale="false", algorithm="MD5", qop="auth", opaque="07c984bd79faee74498abe2331d5e8db"',
    'X-Frame-Options',
    'SAMEORIGIN',
    'X-XSS-Protection',
    '1;mode=block'
  ],
  rawTrailers: [],
  aborted: false,
  upgrade: false,
  url: '',
  method: null,
  statusCode: 401,
  statusMessage: 'UnAuthorized',
  client: <ref *1> Socket {
    connecting: false,
    _hadError: false,
    _parent: null,
    _host: null,
    _readableState: ReadableState {
      objectMode: false,
      highWaterMark: 16384,
      buffer: BufferList { head: null, tail: null, length: 0 },
      length: 0,
      pipes: [],
      flowing: true,
      ended: false,
      endEmitted: false,
      reading: true,
      constructed: true,
      sync: false,
      needReadable: true,
      emittedReadable: false,
      readableListening: false,
      resumeScheduled: false,
      errorEmitted: false,
      emitClose: false,
      autoDestroy: true,
      destroyed: false,
      errored: null,
      closed: false,
      closeEmitted: false,
      defaultEncoding: 'utf8',
      awaitDrainWriters: null,
      multiAwaitDrain: false,
      readingMore: false,
      dataEmitted: true,
      decoder: null,
      encoding: null,
      [Symbol(kPaused)]: false
    },
    _events: [Object: null prototype] {
      end: [Function: onReadableStreamEnd],
      free: [Function: onFree],
      close: [Array],
      timeout: [Function: onTimeout],
      agentRemove: [Function: onRemove],
      error: [Function: socketErrorListener],
      finish: [Function]
    },
    _eventsCount: 7,
    _maxListeners: undefined,
    _writableState: WritableState {
      objectMode: false,
      highWaterMark: 16384,
      finalCalled: true,
      needDrain: false,
      ending: true,
      ended: true,
      finished: false,
      destroyed: false,
      decodeStrings: false,
      defaultEncoding: 'utf8',
      length: 0,
      writing: false,
      corked: 0,
      sync: false,
      bufferProcessing: false,
      onwrite: [Function: bound onwrite],
      writecb: null,
      writelen: 0,
      afterWriteTickInfo: null,
      buffered: [],
      bufferedIndex: 0,
      allBuffers: true,
      allNoop: true,
      pendingcb: 1,
      constructed: true,
      prefinished: false,
      errorEmitted: false,
      emitClose: false,
      autoDestroy: true,
      errored: null,
      closed: false,
      closeEmitted: false,
      [Symbol(kOnFinished)]: []
    },
    allowHalfOpen: false,
    _sockname: null,
    _pendingData: null,
    _pendingEncoding: '',
    server: null,
    _server: null,
    parser: null,
    _httpMessage: ClientRequest {
      _events: [Object: null prototype],
      _eventsCount: 3,
      _maxListeners: undefined,
      outputData: [],
      outputSize: 0,
      writable: true,
      destroyed: false,
      _last: true,
      chunkedEncoding: false,
      shouldKeepAlive: false,
      maxRequestsOnConnectionReached: false,
      _defaultKeepAlive: true,
      useChunkedEncodingByDefault: false,
      sendDate: false,
      _removedConnection: false,
      _removedContLen: false,
      _removedTE: false,
      _contentLength: 0,
      _hasBody: true,
      _trailer: '',
      finished: true,
      _headerSent: true,
      _closed: false,
      socket: [Circular *1],
      _header: 'GET /LAPI/V1.0/Media/Video/Streams/0/Snapshot HTTP/1.1\r\n' +
        'accept: */*\r\n' +
        'user-agent: Needle/3.2.0 (Node.js v16.15.0; darwin arm64)\r\n' +
        'host: 192.168.1.199\r\n' +
        'authorization: Digest uri="/LAPI/V1.0/Media/Video/Streams/0/Snapshot", realm="0013e22cfbf8", nonce="9dd2edda3baca2e7a5b859fb440f71ca", username="brizi", response="e156f4df8c197a301f316b38e48bf631", qop="auth", opaque="07c984bd79faee74498abe2331d5e8db", nc="00000002", cnonce="c8657603"\r\n' +
        'Connection: close\r\n' +
        '\r\n',
      _keepAliveTimeout: 0,
      _onPendingData: [Function: nop],
      agent: [Agent],
      socketPath: undefined,
      method: 'GET',
      maxHeaderSize: undefined,
      insecureHTTPParser: undefined,
      path: '/LAPI/V1.0/Media/Video/Streams/0/Snapshot',
      _ended: true,
      res: [Circular *2],
      aborted: false,
      timeoutCb: null,
      upgradeOrConnect: false,
      parser: null,
      maxHeadersCount: null,
      reusedSocket: false,
      host: '192.168.1.199',
      protocol: 'http:',
      [Symbol(kCapture)]: false,
      [Symbol(kNeedDrain)]: false,
      [Symbol(corked)]: 0,
      [Symbol(kOutHeaders)]: [Object: null prototype]
    },
    [Symbol(async_id_symbol)]: 286,
    [Symbol(kHandle)]: TCP {
      reading: true,
      onconnection: null,
      [Symbol(owner_symbol)]: [Circular *1]
    },
    [Symbol(lastWriteQueueSize)]: 0,
    [Symbol(timeout)]: null,
    [Symbol(kBuffer)]: null,
    [Symbol(kBufferCb)]: null,
    [Symbol(kBufferGen)]: null,
    [Symbol(kCapture)]: false,
    [Symbol(kSetNoDelay)]: false,
    [Symbol(kSetKeepAlive)]: false,
    [Symbol(kSetKeepAliveInitialDelay)]: 0,
    [Symbol(kBytesRead)]: 0,
    [Symbol(kBytesWritten)]: 0,
    [Symbol(RequestTimeout)]: undefined
  },
  _consuming: false,
  _dumped: false,
  req: <ref *3> ClientRequest {
    _events: [Object: null prototype] {
      abort: [Function],
      prefinish: [Function: requestOnPrefinish],
      error: [Function]
    },
    _eventsCount: 3,
    _maxListeners: undefined,
    outputData: [],
    outputSize: 0,
    writable: true,
    destroyed: false,
    _last: true,
    chunkedEncoding: false,
    shouldKeepAlive: false,
    maxRequestsOnConnectionReached: false,
    _defaultKeepAlive: true,
    useChunkedEncodingByDefault: false,
    sendDate: false,
    _removedConnection: false,
    _removedContLen: false,
    _removedTE: false,
    _contentLength: 0,
    _hasBody: true,
    _trailer: '',
    finished: true,
    _headerSent: true,
    _closed: false,
    socket: <ref *1> Socket {
      connecting: false,
      _hadError: false,
      _parent: null,
      _host: null,
      _readableState: [ReadableState],
      _events: [Object: null prototype],
      _eventsCount: 7,
      _maxListeners: undefined,
      _writableState: [WritableState],
      allowHalfOpen: false,
      _sockname: null,
      _pendingData: null,
      _pendingEncoding: '',
      server: null,
      _server: null,
      parser: null,
      _httpMessage: [Circular *3],
      [Symbol(async_id_symbol)]: 286,
      [Symbol(kHandle)]: [TCP],
      [Symbol(lastWriteQueueSize)]: 0,
      [Symbol(timeout)]: null,
      [Symbol(kBuffer)]: null,
      [Symbol(kBufferCb)]: null,
      [Symbol(kBufferGen)]: null,
      [Symbol(kCapture)]: false,
      [Symbol(kSetNoDelay)]: false,
      [Symbol(kSetKeepAlive)]: false,
      [Symbol(kSetKeepAliveInitialDelay)]: 0,
      [Symbol(kBytesRead)]: 0,
      [Symbol(kBytesWritten)]: 0,
      [Symbol(RequestTimeout)]: undefined
    },
    _header: 'GET /LAPI/V1.0/Media/Video/Streams/0/Snapshot HTTP/1.1\r\n' +
      'accept: */*\r\n' +
      'user-agent: Needle/3.2.0 (Node.js v16.15.0; darwin arm64)\r\n' +
      'host: 192.168.1.199\r\n' +
      'authorization: Digest uri="/LAPI/V1.0/Media/Video/Streams/0/Snapshot", realm="0013e22cfbf8", nonce="9dd2edda3baca2e7a5b859fb440f71ca", username="brizi", response="e156f4df8c197a301f316b38e48bf631", qop="auth", opaque="07c984bd79faee74498abe2331d5e8db", nc="00000002", cnonce="c8657603"\r\n' +
      'Connection: close\r\n' +
      '\r\n',
    _keepAliveTimeout: 0,
    _onPendingData: [Function: nop],
    agent: Agent {
      _events: [Object: null prototype],
      _eventsCount: 2,
      _maxListeners: undefined,
      defaultPort: 80,
      protocol: 'http:',
      options: [Object: null prototype],
      requests: [Object: null prototype] {},
      sockets: [Object: null prototype],
      freeSockets: [Object: null prototype] {},
      keepAliveMsecs: 1000,
      keepAlive: false,
      maxSockets: Infinity,
      maxFreeSockets: 256,
      scheduling: 'lifo',
      maxTotalSockets: Infinity,
      totalSocketCount: 1,
      [Symbol(kCapture)]: false
    },
    socketPath: undefined,
    method: 'GET',
    maxHeaderSize: undefined,
    insecureHTTPParser: undefined,
    path: '/LAPI/V1.0/Media/Video/Streams/0/Snapshot',
    _ended: true,
    res: [Circular *2],
    aborted: false,
    timeoutCb: null,
    upgradeOrConnect: false,
    parser: null,
    maxHeadersCount: null,
    reusedSocket: false,
    host: '192.168.1.199',
    protocol: 'http:',
    [Symbol(kCapture)]: false,
    [Symbol(kNeedDrain)]: false,
    [Symbol(corked)]: 0,
    [Symbol(kOutHeaders)]: [Object: null prototype] {
      accept: [Array],
      'user-agent': [Array],
      host: [Array],
      authorization: [Array]
    }
  },
  raw: <Buffer 7b 0d 0a 22 52 65 73 70 6f 6e 73 65 22 3a 20 7b 0d 0a 09 22 52 65 73 70 6f 6e 73 65 55 52 4c 22 3a 20 22 2f 4c 41 50 49 2f 56 31 2e 30 2f 4d 65 64 69 ... 193 more bytes>,
  body: '{\r\n' +
    '"Response": {\r\n' +
    '\t"ResponseURL": "/LAPI/V1.0/Media/Video/Streams/0/Snapshot",\r\n' +
    '\t"ResponseCode": 3,\r\n' +
    ' \t"SubResponseCode": 0,\r\n' +
    ' \t"ResponseString": "Not Authorized",\r\n' +
    '\t"StatusCode": 401,\r\n' +
    '\t"StatusString": "Unauthorized",\r\n' +
    '\t"Data": "null"\r\n' +
    '}\r\n' +
    '}\r\n',
  bytes: 243,
  [Symbol(kCapture)]: false,
  [Symbol(kHeaders)]: {
    'content-length': '243',
    'content-type': 'text/plain',
    connection: 'close',
    'www-authenticate': 'Digest realm="0013e22cfbf8", nonce="9dd2edda3baca2e7a5b859fb440f71ca", stale="false", algorithm="MD5", qop="auth", opaque="07c984bd79faee74498abe2331d5e8db"',
    'x-frame-options': 'SAMEORIGIN',
    'x-xss-protection': '1;mode=block'
  },
  [Symbol(kHeadersCount)]: 12,
  [Symbol(kTrailers)]: null,
  [Symbol(kTrailersCount)]: 0,
  [Symbol(RequestTimeout)]: undefined
}