Skip to content

Commit

Permalink
feat(client): websocket usable on browser
Browse files Browse the repository at this point in the history
  • Loading branch information
truongsinh committed Jun 5, 2019
1 parent bb849cd commit 47aafee
Show file tree
Hide file tree
Showing 10 changed files with 87 additions and 11 deletions.
27 changes: 25 additions & 2 deletions packages/graphql/lib/src/link/web_socket/link_web_socket.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'package:graphql/src/link/fetch_result.dart';
import 'package:graphql/src/link/link.dart';
import 'package:graphql/src/link/operation.dart';
import 'package:graphql/src/socket_client.dart';
import 'package:graphql/src/utilities/platform.dart' show isHtml;
import 'package:graphql/src/websocket/messages.dart';
import 'package:meta/meta.dart';

Expand All @@ -22,13 +23,32 @@ class WebSocketLink extends Link {
/// Creates a new [WebSocketLink] instance with the specified config.
WebSocketLink(
{@required this.url,
@deprecated
// ignore: deprecated_member_use_from_same_package
this.headers,
this.reconnectOnHeaderChange = true,
this.config = const SocketClientConfig()})
: super() {
if (headers != null) {
assert(
!isHtml,
'Cannot set websocket headers with dart:html websockets. '
'If these are for authentication, another approach must be used, '
'such as initPayload.',
);
print(
'WARNING: Using direct websocket headers which will be removed soon, '
'as it is incompatable with dart:html. '
'If you need this direct header access, '
'please comment on this PR with details on your usecase: '
'https://github.com/zino-app/graphql-flutter/pull/323',
);
}
request = _doOperation;
}

final String url;
final Map<String, dynamic> headers;
final bool reconnectOnHeaderChange;
final SocketClientConfig config;

Expand All @@ -41,6 +61,10 @@ class WebSocketLink extends Link {
if (context != null && context.containsKey('headers')) {
concatHeaders.addAll(context['headers'] as Map<String, dynamic>);
}
// @todo deprecated
if (headers != null) {
concatHeaders.addAll(headers);
}

if (_socketClient == null) {
connectOrReconnect(headers: concatHeaders);
Expand All @@ -57,8 +81,7 @@ class WebSocketLink extends Link {
/// Connects or reconnects to the server with the specified headers.
void connectOrReconnect({Map<String, dynamic> headers}) {
_socketClient?.dispose();
_socketClient =
SocketClient(url, config: config);
_socketClient = SocketClient(url, config: config);
}

/// Disposes the underlying socket client explicitly. Only use this, if you want to disconnect from
Expand Down
3 changes: 3 additions & 0 deletions packages/graphql/lib/src/utilities/platform.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export './platform_stub.dart'
if (dart.library.html) './platform_html.dart'
if (dart.library.io) './platform_io.dart';
2 changes: 2 additions & 0 deletions packages/graphql/lib/src/utilities/platform_html.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
final isHtml = true;
final isIo = false;
2 changes: 2 additions & 0 deletions packages/graphql/lib/src/utilities/platform_io.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
final isHtml = false;
final isIo = true;
2 changes: 2 additions & 0 deletions packages/graphql/lib/src/utilities/platform_stub.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
final isHtml = false;
final isIo = false;
9 changes: 9 additions & 0 deletions packages/graphql/test/helpers.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// This
import 'dart:async';
import 'dart:mirrors';
import 'dart:convert';
import 'dart:io' show File, Directory;
Expand All @@ -9,6 +10,14 @@ import 'package:http/http.dart' as http;

import 'package:graphql/client.dart';

overridePrint(testFn(List<String> log)) => () {
final log = <String>[];
final spec = new ZoneSpecification(print: (_, __, ___, String msg) {
log.add(msg);
});
return Zone.current.fork(specification: spec).run(() => testFn(log));
};

NormalizedInMemoryCache getTestCache() => NormalizedInMemoryCache(
dataIdFromObject: typenameDataIdFromObject,
storageProvider: () => Directory.systemTemp.createTemp('file_test_'),
Expand Down
10 changes: 2 additions & 8 deletions packages/graphql/test/in_memory_storage_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import 'dart:io' show Directory, FileSystemException;
import 'package:test/test.dart';
import 'package:graphql/src/cache/in_memory.dart';

import 'helpers.dart';

const String aKey = 'aKey';
const String bKey = 'bKey';
const String cKey = 'cKey';
Expand Down Expand Up @@ -158,11 +160,3 @@ void main() {
}));
});
}

overridePrint(testFn(List<String> log)) => () {
final log = <String>[];
final spec = new ZoneSpecification(print: (_, __, ___, String msg) {
log.add(msg);
});
return Zone.current.fork(specification: spec).run(() => testFn(log));
};
18 changes: 18 additions & 0 deletions packages/graphql/test/link_web_socket_test_html.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
@TestOn('browser')

import 'package:test/test.dart';
import 'package:graphql/src/link/web_socket/link_web_socket.dart';

void main() {
group('Link Websocket', () {
test('simple connection', () {
expect(
() => WebSocketLink(
url: 'ws://echo.websocket.org',
// ignore: deprecated_member_use_from_same_package
headers: {'foo': 'bar'},
),
throwsA(TypeMatcher<AssertionError>()));
});
});
}
23 changes: 23 additions & 0 deletions packages/graphql/test/link_web_socket_test_io.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
@TestOn('vm')

import 'package:test/test.dart';
import 'package:graphql/src/link/web_socket/link_web_socket.dart';

import 'helpers.dart';

void main() {
group('Link Websocket', () {
test('simple connection', overridePrint((List<String> log) {
WebSocketLink(
url: 'ws://echo.websocket.org',
// ignore: deprecated_member_use_from_same_package
headers: {'foo': 'bar'},
);
expect(log, [
'Cannot set websocket headers with dart:html websockets. '
'If these are for authentication, another approach must be used, '
'such as initPayload.'
]);
}));
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class GraphQLWidgetScreen extends StatelessWidget {
getToken: () async => 'Bearer $YOUR_PERSONAL_ACCESS_TOKEN',
);

Link link = authLink.concat(httpLink);
Link link = authLink.concat(httpLink as Link);
if (ENABLE_WEBSOCKETS) {
final WebSocketLink websocketLink = WebSocketLink(
url: 'ws://localhost:8080/ws/graphql',
Expand Down

0 comments on commit 47aafee

Please sign in to comment.