Я реализовал LoggingInterceptor
, который должен иметь доступ к окончательному Ответу GraphQL с его свойствами данных и ошибок + исходное тело запроса и аутентифицированный пользователь, который был добавлен к запросу до AuthGuard
. (РЕДАКТИРОВАТЬ: Частично разрешается с помощью @ jay-mcdoniel: user
и body
доступны через GqlExecutionContext.create(context).getContext()
)
Действительно, Перехватчик предоставляет только один полностью разрешенный GraphQL-объект.
@Injectable()
export class LoggingInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
return next.handle().pipe(tap(
(allData) => console.log(allData),
(error)=> console.log(error)));
}
}
Это мой класс перехватчиков.Это просто вызов RxJS-оператора tap
для регистрации текущих значений наблюдаемой.
Если я запускаю следующий GraphQL-запрос ...
mutation {
login(data: { username: "admin", password: "123456" }) {
id
username
token
}
}
... мой серверправильно отвечает следующим телом ответа:
{
"data": {
"login": {
"id": "6f40be3b-cda9-4e6d-97ce-ced3787e9974",
"username": "admin",
"token": "someToken"
}
}
}
Но содержимое allData
, которое регистрируется в консоли моим перехватчиком, выглядит следующим образом:
{
id: '6f40be3b-cda9-4e6d-97ce-ced3787e9974',
isAdmin: true,
username: 'admin',
firstname: null,
lastname: null,
email: null,
created: 2019-07-05T15:11:31.606Z,
token: 'someToken'
}
Вместо этого я хотел бычтобы увидеть информацию о реальном теле ответа.
Я дополнительно попытался получить доступ к HttpResponse по context.switchToHttp().getResponse()
.Но он содержит только параметры метода мутации-входа в систему:
{
data: [Object: null prototype] { username: 'admin', password: '123456' }
}
РЕДАКТИРОВАТЬ :
console.log(GqlExecutionContext.create(context).getContext());
отпечатков (все еще нет GraphQL-ResponseBody):
{
headers: {
/*...*/
},
user: /*...*/,
body: {
operationName: null,
variables: {},
query: 'mutation {\n login(data: {username: "admin", password: ' +
'"123456"}) {\n token\n id\n username\n isAdmin\n }\n' +
'}\n'
},
res: ServerResponse {
_events: [Object: null prototype] { finish: [Function: bound resOnFinish] },
_eventsCount: 1,
_maxListeners: undefined,
outputData: [],
outputSize: 0,
writable: true,
_last: false,
chunkedEncoding: false,
shouldKeepAlive: true,
useChunkedEncodingByDefault: true,
sendDate: true,
_removedConnection: false,
_removedContLen: false,
_removedTE: false,
_contentLength: null,
_hasBody: true,
_trailer: '',
finished: false,
_headerSent: false,
socket: Socket {
connecting: false,
_hadError: false,
_parent: null,
_host: null,
_readableState: [ReadableState],
readable: true,
_events: [Object],
_eventsCount: 8,
_maxListeners: undefined,
_writableState: [WritableState],
writable: true,
allowHalfOpen: true,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: [Server],
_server: [Server],
timeout: 120000,
parser: [HTTPParser],
on: [Function: socketOnWrap],
_paused: false,
_httpMessage: [Circular],
[Symbol(asyncId)]: 566,
[Symbol(kHandle)]: [TCP],
[Symbol(lastWriteQueueSize)]: 0,
[Symbol(timeout)]: Timeout {
/*...*/
},
[Symbol(kBytesRead)]: 0,
[Symbol(kBytesWritten)]: 0
},
connection: Socket {
connecting: false,
_hadError: false,
_parent: null,
_host: null,
_readableState: [ReadableState],
readable: true,
_events: [Object],
_eventsCount: 8,
_maxListeners: undefined,
_writableState: [WritableState],
writable: true,
allowHalfOpen: true,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: [Server],
_server: [Server],
timeout: 120000,
parser: [HTTPParser],
on: [Function: socketOnWrap],
_paused: false,
_httpMessage: [Circular],
[Symbol(asyncId)]: 566,
[Symbol(kHandle)]: [TCP],
[Symbol(lastWriteQueueSize)]: 0,
[Symbol(timeout)]: Timeout {
_idleTimeout: 120000,
_idlePrev: [TimersList],
_idleNext: [TimersList],
_idleStart: 3273,
_onTimeout: [Function: bound ],
_timerArgs: undefined,
_repeat: null,
_destroyed: false,
[Symbol(refed)]: false,
[Symbol(asyncId)]: 567,
[Symbol(triggerId)]: 566
},
[Symbol(kBytesRead)]: 0,
[Symbol(kBytesWritten)]: 0
},
_header: null,
_onPendingData: [Function: bound updateOutgoingData],
_sent100: false,
_expect_continue: false,
req: IncomingMessage {
/*...*/
},
locals: [Object: null prototype] {},
[Symbol(isCorked)]: false,
[Symbol(outHeadersKey)]: [Object: null prototype] {
'x-powered-by': [Array],
'access-control-allow-origin': [Array]
}
},
_extensionStack: GraphQLExtensionStack { extensions: [ [CacheControlExtension] ] }
}