Skip to content

Commit

Permalink
Should preserve ws and http in the middle of a pointer (#1991)
Browse files Browse the repository at this point in the history
  • Loading branch information
kamilkisiela committed Sep 3, 2020
1 parent 9150404 commit 78c1f1f
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 23 deletions.
18 changes: 16 additions & 2 deletions packages/loaders/url/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,10 @@ export class UrlLoader implements DocumentLoader<LoadFromUrlOptions> {
defaultMethod: 'GET' | 'POST';
useGETForQueries: boolean;
}): AsyncExecutor {
const HTTP_URL = pointer.replace('ws:', 'http:').replace('wss:', 'https:');
const HTTP_URL = switchProtocols(pointer, {
wss: 'https',
ws: 'http',
});
return async ({ document, variables }: { document: DocumentNode; variables: any; info: GraphQLResolveInfo }) => {
let method = defaultMethod;
if (useGETForQueries) {
Expand Down Expand Up @@ -134,7 +137,10 @@ export class UrlLoader implements DocumentLoader<LoadFromUrlOptions> {
}

buildSubscriber(pointer: string, webSocketImpl: typeof w3cwebsocket): Subscriber {
const WS_URL = pointer.replace('http:', 'ws:').replace('https:', 'wss:');
const WS_URL = switchProtocols(pointer, {
https: 'wss',
http: 'ws',
});
const subscriptionClient = new SubscriptionClient(WS_URL, {}, webSocketImpl);
return async <TReturn, TArgs>({ document, variables }: { document: DocumentNode; variables: TArgs }) => {
return observableToAsyncIterable(
Expand Down Expand Up @@ -237,3 +243,11 @@ export class UrlLoader implements DocumentLoader<LoadFromUrlOptions> {
throw new Error('Loader Url has no sync mode');
}
}

function switchProtocols(pointer: string, protocolMap: Record<string, string>): string {
const protocols: [string, string][] = Object.keys(protocolMap).map(source => [source, protocolMap[source]]);
return protocols.reduce(
(prev, [source, target]) => prev.replace(`${source}://`, `${target}://`).replace(`${source}:\\`, `${target}:\\`),
pointer
);
}
102 changes: 81 additions & 21 deletions packages/loaders/url/tests/url-loader.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const SHOULD_NOT_GET_HERE_ERROR = 'SHOULD_NOT_GET_HERE';
describe('Schema URL Loader', () => {
const loader = new UrlLoader();

const testTypeDefs = /* GraphQL */`
const testTypeDefs = /* GraphQL */ `
schema { query: CustomQuery }
"""Test type comment"""
type CustomQuery {
Expand All @@ -23,8 +23,8 @@ type CustomQuery {
const testResolvers = {
CustomQuery: {
a: (_: never, { testVariable }: { testVariable: string }) => testVariable || 'a',
}
}
},
};

const testSchema = makeExecutableSchema({ typeDefs: testTypeDefs, resolvers: testResolvers });

Expand Down Expand Up @@ -63,12 +63,15 @@ type CustomQuery {
});

it('Should pass default headers', async () => {
let headers: Record<string, string> = {}
let headers: Record<string, string> = {};

const server = mockGraphQLServer({
schema: testSchema, host: testHost, path: testPathChecker, intercept(ctx) {
headers = ctx.req.headers
}
schema: testSchema,
host: testHost,
path: testPathChecker,
intercept(ctx) {
headers = ctx.req.headers;
},
});

const schema = await loader.load(testUrl, {});
Expand All @@ -84,11 +87,14 @@ type CustomQuery {
});

it('Should pass extra headers when they are specified as object', async () => {
let headers: Record<string, string> = {}
let headers: Record<string, string> = {};
const server = mockGraphQLServer({
schema: testSchema, host: testHost, path: testPathChecker, intercept(ctx) {
headers = ctx.req.headers
}
schema: testSchema,
host: testHost,
path: testPathChecker,
intercept(ctx) {
headers = ctx.req.headers;
},
});

const schema = await loader.load(testUrl, { headers: { Auth: '1' } });
Expand All @@ -105,11 +111,14 @@ type CustomQuery {
});

it('Should pass extra headers when they are specified as array', async () => {
let headers: Record<string, string> = {}
let headers: Record<string, string> = {};
const server = mockGraphQLServer({
schema: testSchema, host: testHost, path: testPathChecker, intercept(ctx) {
headers = ctx.req.headers
}
schema: testSchema,
host: testHost,
path: testPathChecker,
intercept(ctx) {
headers = ctx.req.headers;
},
});
const schema = await loader.load(testUrl, { headers: [{ A: '1' }, { B: '2', C: '3' }] });

Expand Down Expand Up @@ -140,12 +149,11 @@ type CustomQuery {
expect(await loader.canLoad(cwd(), {})).toBeFalsy();
});
it('should handle useGETForQueries correctly', async () => {

const server = mockGraphQLServer({ schema: testSchema, host: testHost, path: testPathChecker, method: 'GET' });

const source = await loader.load(testUrl, {
descriptions: false,
useGETForQueries: true
useGETForQueries: true,
});

server.done();
Expand All @@ -156,22 +164,74 @@ type CustomQuery {

const result = await execute({
schema: source.schema,
document: parse(/* GraphQL */`
document: parse(/* GraphQL */ `
query TestQuery($testVariable: String) {
a(testVariable: $testVariable)
}
`),
variableValues: {
testVariable: testVariableValue
}
testVariable: testVariableValue,
},
});

server2.done();

expect(result?.errors).toBeFalsy();

expect(result?.data?.a).toBe(testVariableValue);
});

it('Should preserve "ws" and "http" in the middle of a pointer', async () => {
const address = {
host: 'http://foo.ws:8080',
path: '/graphql',
};
const url = address.host + address.path;
const server = mockGraphQLServer({ schema: testSchema, host: address.host, path: address.path });
const result = await loader.load(url, {});

server.done();

expect(result.schema).toBeDefined();
expect(printSchemaWithDirectives(result.schema)).toBe(testTypeDefs);
});

it('Should replace ws:// with http:// in buildAsyncExecutor', async () => {
const address = {
host: 'ws://foo:8080',
path: '/graphql',
};
const url = address.host + address.path;
const server = mockGraphQLServer({
schema: testSchema,
host: address.host.replace('ws', 'http'),
path: address.path,
});
const result = await loader.load(url, {});

})
server.done();

expect(result.schema).toBeDefined();
expect(printSchemaWithDirectives(result.schema)).toBe(testTypeDefs);
});

it('Should replace wss:// with https:// in buildAsyncExecutor', async () => {
const address = {
host: 'wss://foo:8080',
path: '/graphql',
};
const url = address.host + address.path;
const server = mockGraphQLServer({
schema: testSchema,
host: address.host.replace('wss', 'https'),
path: address.path,
});
const result = await loader.load(url, {});

server.done();

expect(result.schema).toBeDefined();
expect(printSchemaWithDirectives(result.schema)).toBe(testTypeDefs);
});
});
});

0 comments on commit 78c1f1f

Please sign in to comment.