SSL-сертификаты Apollo GraphQL Websocket - PullRequest
0 голосов
/ 18 июня 2019

Я пытаюсь установить соединение через websocket с сервером apollo graphql. Я использую библиотеку apollo-client-ws для достижения этой цели. К сожалению, я продолжаю получать ошибку 400, и в объекте ошибки в нескольких местах есть фраза «SELF_SIGNED_CERT_IN_CHAIN». После некоторых исследований я думаю, что это проблема с моим клиентом, который не доверяет SSL-сертификату сервера. Я понятия не имею, как это исправить. Я уже использую process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"; что было предложено исправить, но все, что он делает, это позволяет мне получить любой ответ; без него я ничего не получаю с сервера.

Это то, что я делаю

const gql = require("graphql-tag");
const { ApolloClient } = require("apollo-client");
const { ApolloClientWS } = require("apollo-client-ws");
const { InMemoryCache } = require("apollo-cache-inmemory");

process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";

const link = new ApolloClientWS({
    uri: "wss://domain/path",
    opts: {
        debug: 1,
        protocols: [],
        compress: false,
        encoding: "json",
        keepalive: 0,
        reconnectattempts: 10,
        reconnectdelay: 2 * 1000,
    }
})

const client = new ApolloClient({
    link: link,
    cache: new InMemoryCache()
})

client.query({ query: gql`
        /* Trust me the query is valid */
    `})
.then((response) => { 
    console.log("We got a response")
    console.log(response)
})
.catch((err) => { 
    console.log("We got an error")
    console.log(err.networkError.target) 
})

И это вывод

We got an error
WebSocket {
  _events:
   [Object: null prototype] { message: { [Function: onMessage] _listener: [Function] } },
  _eventsCount: 1,
  _maxListeners: undefined,
  readyState: 3,
  protocol: '',
  _binaryType: 'nodebuffer',
  _closeFrameReceived: false,
  _closeFrameSent: false,
  _closeMessage: '',
  _closeTimer: null,
  _closeCode: 1006,
  _extensions: {},
  _receiver: null,
  _sender: null,
  _socket: null,
  _bufferedAmount: 0,
  _isServer: false,
  _redirects: 0,
  url: 'wss://domain/path',
  _req:
   ClientRequest {
     _events:
      [Object: null prototype] {
        error: [Function],
        response: [Function],
        upgrade: [Function],
        prefinish: [Function: requestOnPrefinish] },
     _eventsCount: 4,
     _maxListeners: undefined,
     output: [],
     outputEncodings: [],
     outputCallbacks: [],
     outputSize: 0,
     writable: true,
     _last: true,
     chunkedEncoding: false,
     shouldKeepAlive: true,
     useChunkedEncodingByDefault: false,
     sendDate: false,
     _removedConnection: false,
     _removedContLen: false,
     _removedTE: false,
     _contentLength: 0,
     _hasBody: true,
     _trailer: '',
     finished: true,
     _headerSent: true,
     socket:
      TLSSocket {
        _tlsOptions: [Object],
        _secureEstablished: true,
        _securePending: false,
        _newSessionPending: false,
        _controlReleased: true,
        _SNICallback: null,
        servername: 'domain',
        alpnProtocol: false,
        authorized: false,
        authorizationError: 'SELF_SIGNED_CERT_IN_CHAIN',
        encrypted: true,
        _events: [Object],
        _eventsCount: 7,
        connecting: false,
        _hadError: false,
        _handle: null,
        _parent: null,
        _host: 'domain',
        _readableState: [ReadableState],
        readable: false,
        _maxListeners: undefined,
        _writableState: [WritableState],
        writable: false,
        allowHalfOpen: false,
        _sockname: null,
        _pendingData: null,
        _pendingEncoding: '',
        server: undefined,
        _server: null,
        ssl: null,
        _requestCert: true,
        _rejectUnauthorized: false,
        parser: [HTTPParser],
        _httpMessage: [Circular],
        [Symbol(res)]: [TLSWrap],
        [Symbol(asyncId)]: 367,
        [Symbol(lastWriteQueueSize)]: 0,
        [Symbol(timeout)]: null,
        [Symbol(kBytesRead)]: 172,
        [Symbol(kBytesWritten)]: 246,
        [Symbol(connect-options)]: [Object] },
     connection:
      TLSSocket {
        _tlsOptions: [Object],
        _secureEstablished: true,
        _securePending: false,
        _newSessionPending: false,
        _controlReleased: true,
        _SNICallback: null,
        servername: 'domain',
        alpnProtocol: false,
        authorized: false,
        authorizationError: 'SELF_SIGNED_CERT_IN_CHAIN',
        encrypted: true,
        _events: [Object],
        _eventsCount: 7,
        connecting: false,
        _hadError: false,
        _handle: null,
        _parent: null,
        _host: 'domain',
        _readableState: [ReadableState],
        readable: false,
        _maxListeners: undefined,
        _writableState: [WritableState],
        writable: false,
        allowHalfOpen: false,
        _sockname: null,
        _pendingData: null,
        _pendingEncoding: '',
        server: undefined,
        _server: null,
        ssl: null,
        _requestCert: true,
        _rejectUnauthorized: false,
        parser: [HTTPParser],
        _httpMessage: [Circular],
        [Symbol(res)]: [TLSWrap],
        [Symbol(asyncId)]: 367,
        [Symbol(lastWriteQueueSize)]: 0,
        [Symbol(timeout)]: null,
        [Symbol(kBytesRead)]: 172,
        [Symbol(kBytesWritten)]: 246,
        [Symbol(connect-options)]: [Object] },
     _header:
      'GET /api/v1 HTTP/1.1\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: R4WfFMGHI2FxqAvaWmnrdA==\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Extensions: permessage-deflate; client_max_window_bits\r\nHost: domain\r\n\r\n',
     _onPendingData: [Function: noopPendingOutput],
     agent: undefined,
     socketPath: undefined,
     timeout: undefined,
     method: 'GET',
     path: '/path',
     _ended: false,
     res:
      IncomingMessage {
        _readableState: [ReadableState],
        readable: true,
        _events: [Object],
        _eventsCount: 1,
        _maxListeners: undefined,
        socket: [TLSSocket],
        connection: [TLSSocket],
        httpVersionMajor: 1,
        httpVersionMinor: 1,
        httpVersion: '1.1',
        complete: false,
        headers: [Object],
        rawHeaders: [Array],
        trailers: {},
        rawTrailers: [],
        aborted: false,
        upgrade: false,
        url: '',
        method: null,
        statusCode: 400,
        statusMessage: 'Bad Request',
        client: [TLSSocket],
        _consuming: true,
        _dumped: true,
        req: [Circular] },
     aborted: 1560885460441,
     timeoutCb: null,
     upgradeOrConnect: false,
     parser:
      HTTPParser {
        '0': [Function: parserOnHeaders],
        '1': [Function: parserOnHeadersComplete],
        '2': [Function: parserOnBody],
        '3': [Function: parserOnMessageComplete],
        '4': null,
        _headers: [],
        _url: '',
        socket: [TLSSocket],
        incoming: [IncomingMessage],
        outgoing: [Circular],
        maxHeaderPairs: 2000,
        _consumed: false,
        onIncoming: [Function: parserOnIncomingClient],
        [Symbol(isReused)]: true },
     maxHeadersCount: null,
     [Symbol(isCorked)]: false,
     [Symbol(outHeadersKey)]:
      [Object: null prototype] {
        'sec-websocket-version': [Array],
        'sec-websocket-key': [Array],
        connection: [Array],
        upgrade: [Array],
        'sec-websocket-extensions': [Array],
        host: [Array] } } }

Обратите внимание, что я использую console.log(err.networkError.target) вместо console.log(err), потому что без дополнительной специфичности он не печатает с достаточной глубиной, чтобы увидеть соответствующую информацию (или то, что я считаю соответствующей информацией).

...