Я пытаюсь установить соединение через 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)
, потому что без дополнительной специфичности он не печатает с достаточной глубиной, чтобы увидеть соответствующую информацию (или то, что я считаю соответствующей информацией).