Skip to content

Commit

Permalink
refactor: centralise token header and url query keys
Browse files Browse the repository at this point in the history
  • Loading branch information
enisdenjo committed Nov 12, 2021
1 parent 98780c0 commit 7d7b694
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 16 deletions.
27 changes: 27 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ graphql-sse
- [StreamDataForID](README.md#streamdataforid)
- [StreamEvent](README.md#streamevent)

### Variables

- [TOKEN\_HEADER\_KEY](README.md#token_header_key)
- [TOKEN\_QUERY\_KEY](README.md#token_query_key)

### Functions

- [createClient](README.md#createclient)
Expand Down Expand Up @@ -95,6 +100,28 @@ ___

___

### TOKEN\_HEADER\_KEY

**TOKEN\_HEADER\_KEY**: ``"x-graphql-event-stream-token"``

Header key through which the event stream token is transmitted
when using the client in "single connection mode".

Read more: https://github.com/enisdenjo/graphql-sse/blob/master/PROTOCOL.md#single-connection-mode

___

### TOKEN\_QUERY\_KEY

**TOKEN\_QUERY\_KEY**: ``"token"``

URL query parameter key through which the event stream token is transmitted
when using the client in "single connection mode".

Read more: https://github.com/enisdenjo/graphql-sse/blob/master/PROTOCOL.md#single-connection-mode

___

### parseStreamData

**parseStreamData**(`e`, `data`): [`StreamData`](README.md#streamdata)
Expand Down
25 changes: 13 additions & 12 deletions src/__tests__/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import EventSource from 'eventsource';
import { startTServer, startDisposableServer } from './utils/tserver';
import { eventStream } from './utils/eventStream';
import { createClient, createHandler } from '../index';
import { TOKEN_HEADER_KEY, TOKEN_QUERY_KEY } from '../common';
import http from 'http';
import { schema } from './fixtures/simple';
import fetch from 'node-fetch';
Expand All @@ -17,20 +18,20 @@ it('should only accept valid accept headers', async () => {

let res = await request('GET', {
accept: 'gibberish',
['x-graphql-event-stream-token']: token,
[TOKEN_HEADER_KEY]: token,
});
expect(res.statusCode).toBe(406);

res = await request('GET', {
accept: 'application/graphql+json',
['x-graphql-event-stream-token']: token,
[TOKEN_HEADER_KEY]: token,
});
expect(res.statusCode).toBe(400);
expect(res.statusMessage).toBe('Missing query');

res = await request('GET', {
accept: 'application/json',
['x-graphql-event-stream-token']: token,
[TOKEN_HEADER_KEY]: token,
});
expect(res.statusCode).toBe(400);
expect(res.statusMessage).toBe('Missing query');
Expand Down Expand Up @@ -95,7 +96,7 @@ describe('single connection mode', () => {
// token can be sent through the header
let res = await request('PUT');
es = new EventSource(url, {
headers: { ['x-graphql-event-stream-token']: res.data },
headers: { [TOKEN_HEADER_KEY]: res.data },
});
await new Promise<void>((resolve, reject) => {
es.onopen = () => resolve();
Expand All @@ -108,7 +109,7 @@ describe('single connection mode', () => {

// token can be sent through the url
res = await request('PUT');
es = new EventSource(url + '?token=' + res.data);
es = new EventSource(url + '?' + TOKEN_QUERY_KEY + '=' + res.data);
await new Promise<void>((resolve, reject) => {
es.onopen = () => resolve();
es.onerror = (e) => {
Expand All @@ -126,7 +127,7 @@ describe('single connection mode', () => {

const { statusCode, statusMessage } = await request(
'POST',
{ 'x-graphql-event-stream-token': token },
{ [TOKEN_HEADER_KEY]: token },
{ query: '{ getValue }' },
);

Expand All @@ -139,7 +140,7 @@ describe('single connection mode', () => {

const { data: token } = await request('PUT');

const es = new EventSource(url + '?token=' + token);
const es = new EventSource(url + '?' + TOKEN_QUERY_KEY + '=' + token);
es.addEventListener('next', (event) => {
expect((event as any).data).toMatchSnapshot();
});
Expand All @@ -150,7 +151,7 @@ describe('single connection mode', () => {

const { statusCode } = await request(
'POST',
{ 'x-graphql-event-stream-token': token },
{ [TOKEN_HEADER_KEY]: token },
{ query: '{ getValue }', extensions: { operationId: '1' } },
);
expect(statusCode).toBe(202);
Expand All @@ -163,7 +164,7 @@ describe('single connection mode', () => {

const { data: token } = await request('PUT');

const es = new EventSource(url + '?token=' + token);
const es = new EventSource(url + '?' + TOKEN_QUERY_KEY + '=' + token);
es.addEventListener('next', (event) => {
// called 5 times
expect((event as any).data).toMatchSnapshot();
Expand All @@ -175,7 +176,7 @@ describe('single connection mode', () => {

const { statusCode } = await request(
'POST',
{ 'x-graphql-event-stream-token': token },
{ [TOKEN_HEADER_KEY]: token },
{ query: 'subscription { greetings }', extensions: { operationId: '1' } },
);
expect(statusCode).toBe(202);
Expand All @@ -186,7 +187,7 @@ describe('single connection mode', () => {

const { data: token } = await request('PUT');

const es = new EventSource(url + '?token=' + token);
const es = new EventSource(url + '?' + TOKEN_QUERY_KEY + '=' + token);
es.addEventListener('next', () => {
fail('Shouldnt have omitted');
});
Expand All @@ -196,7 +197,7 @@ describe('single connection mode', () => {

const { statusCode, data } = await request(
'POST',
{ 'x-graphql-event-stream-token': token },
{ [TOKEN_HEADER_KEY]: token },
{ query: '{ notExists }', extensions: { operationId: '1' } },
);
expect(statusCode).toBe(400);
Expand Down
3 changes: 2 additions & 1 deletion src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
StreamMessage,
ExecutionResult,
ExecutionPatchResult,
TOKEN_HEADER_KEY,
} from './common';

/** This file is the entry point for browsers, re-export common elements. */
Expand Down Expand Up @@ -289,7 +290,7 @@ export function createClient(options: ClientOptions): Client {
if (res.status !== 201) throw new NetworkError(res);

const token = await res.text();
headers['x-graphql-event-stream-token'] = token;
headers[TOKEN_HEADER_KEY] = token;

const connected = await connect({
signal: connCtrl.signal,
Expand Down
20 changes: 20 additions & 0 deletions src/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,26 @@

import type { DocumentNode, GraphQLError } from 'graphql';

/**
* Header key through which the event stream token is transmitted
* when using the client in "single connection mode".
*
* Read more: https://github.com/enisdenjo/graphql-sse/blob/master/PROTOCOL.md#single-connection-mode
*
* @category Common
*/
export const TOKEN_HEADER_KEY = 'x-graphql-event-stream-token' as const;

/**
* URL query parameter key through which the event stream token is transmitted
* when using the client in "single connection mode".
*
* Read more: https://github.com/enisdenjo/graphql-sse/blob/master/PROTOCOL.md#single-connection-mode
*
* @category Common
*/
export const TOKEN_QUERY_KEY = 'token' as const;

/**
* Parameters for GraphQL's request for execution.
*
Expand Down
7 changes: 4 additions & 3 deletions src/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import {
StreamDataForID,
ExecutionResult,
ExecutionPatchResult,
TOKEN_HEADER_KEY,
TOKEN_QUERY_KEY,
} from './common';

/**
Expand Down Expand Up @@ -334,15 +336,14 @@ export function createHandler<
subscribe = graphqlSubscribe,
authenticate = function extractOrCreateStreamToken(req) {
const headerToken =
req.headers['x-graphql-event-stream-token'] ||
req.headers['x-graphql-stream-token']; // @deprecated >v1.0.0
req.headers[TOKEN_HEADER_KEY] || req.headers['x-graphql-stream-token']; // @deprecated >v1.0.0
if (headerToken)
return Array.isArray(headerToken) ? headerToken.join('') : headerToken;

const urlToken = new URL(
req.url ?? '',
'http://localhost/',
).searchParams.get('token');
).searchParams.get(TOKEN_QUERY_KEY);
if (urlToken) return urlToken;

return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
Expand Down

0 comments on commit 7d7b694

Please sign in to comment.