Transport library for sending HTTP requests and opening WebSockets.
HTTP support includes plain-text, JSON, form-data, and multipart data, as well as custom encoding. Also supports automatic retrying and request & response interception.
WebSocket support includes native WebSockets in the browser and the VM with the option to use SockJS in the browser.
All transport classes are platform-independent and can be configured to work in the browser or on the Dart VM. Additionally, all transport classes can be mocked out and controlled through an API included with this library.
As of version 3.0.0, w_transport will be following a versioning and stability commitment that guarantees a compatibility lifespan of two major versions.
If you're installing w_transport for the first time, simply depend on the latest major version and you'll get all patches and minor versions as they are released:
dependencies:
w_transport: ^3.0.0
If you're upgrading from version 2.x, you can use the above version range without breaking any existing code. Check out the 3.0.0 upgrade guide.
The main entry point contains all of the transport classes necessary for sending
HTTP requests and establishing WebSocket connections. It is also
platform-independent (depends on neither dart:html
nor dart:io
), which means
you can use it to build components, libraries, or APIs that will be reusable in
the browser and on the Dart VM.
import 'package:w_transport/w_transport.dart' as transport;
We strongly recommend importing with the prefix
transport
because there are some classes whose names conflict with classes from the Dart SDK.
The end consumer will make the decision between browser and VM, most likely in a
main()
block.
As of version 3.0.0 of the w_transport
package, the minimum required Dart SDK
version is 1.14.0 (released Jan 28, 2016).
This library follows semver to the best of our interpretation of it. We want this library to be a stable dependency that’s easy to keep current. A good explanation of the versioning scheme that we intend to follow can be seen here from React.js:
https://facebook.github.io/react/blog/2016/02/19/new-versioning-scheme.html
In short: our goal is for every major release to be backwards compatible with the previous major version, giving consumers a lifespan of two major versions to deal with deprecations.
This library was influenced in many ways by
the http
package, especially with regard
to multipart requests, and served as a useful source for references to pertinent
IETF RFCs.
This project leverages the dart_dev
package
for most of its tooling needs, including static analysis, code
formatting, running tests, collecting coverage, and serving examples.
Check out the dart_dev readme for more information.
To run integration tests, you'll need two JS dependencies for a SockJS server. Run
npm install
to download them.
October 10th, 2018
July 19th, 2018
Bug Fix: When using MockTransports
with fallThrough: true
, requests that
fall through now properly copy over contentLength
and contentType
if
applicable.
Dependency: Upgraded minimum sockjs_client_wrapper
version to 1.0.4 in
order to pull in SockJS v1.1.5.
May 17th, 2018
Bug Fix: The previous version introduced a new transformer for the
w_transport examples, but did not properly scope it to the examples/
directory. This led to the following error during a pub get
for
some consumers:
Precompiling dependencies...
Loading source assets...
Error on line 1, column 1 of https://pub.dartlang.org/api/packages/w_transport: Error loading transformer "over_react": package "over_react" is not a dependency.
This has been fixed. If you're still seeing this error, run
pub upgrade w_transport
to make sure you have the latest.
May 16th, 2018
MultipartRequest
was previously
adding every field to the FormData
twice - this has been fixed.April 25th, 2018
April 20th, 2018
January 29th, 2018
sockjs.js
detection now uses context.hasProperty()
instead of actually trying to access the SockJS
object on the window. This
fixes an exception that was being thrown silently in certain situations.January 4th, 2018
Improvement: Added support for the sockjs_client_wrapper
package. This will eventually replace our usage of the sockjs_client
Dart port
because the wrapper uses the actual JS library which is fully-featured and community supported.
The SockJS wrapper requires that the JS library be included in the HTML page. To avoid a breaking change, it will only be used if the JS library is detected on the window.
If you are using the SockJS configuration for WebSocket
and wish to leverage
this more fully-featured SockJS (which provides all of the SockJS protocols
e.g. xhr-polling
), all you need to do is add the JS script to your
application page:
https://github.com/workiva/sockjs_client_wrapper#usage
If you don't change anything, the SockJS configuration for WebSocket
will
still behave exactly the same and you should see no difference.
March 15th, 2017
done
Future resolving. Previously it was possible for the done
Future to
never resolve if the request was canceled at a certain point during the
request lifecycle.February 3rd, 2017
MockTransports
is installed with "fall-through" enabled,
the optional SockJS params that are available on the
new transport.WebSocket()
constructor are now properly passed through.
Previously, a standard WebSocket implementation would have been constructed
erroneously if useSockJS: true
was set, but it now correctly constructs the
SockJS implementation.January 18th, 2017
autoRetry.test
function is supplied and returns
true when the response
is null, a request that was canceled would
erroneously be retried. Canceling a request now properly makes it ineligible
for retry regardless of other factors.October 25th, 2016
This major release includes deprecations and an increased minimum Dart SDK version. This release should be backwards compatible with version 2.x.
To upgrade, check out the v3.0.0 upgrade guide.
There is a new pattern for configuring w_transport
for a particular
platform. Check out the Transport Platform Configuration guide.
There is a new way to install the transport mocks (instead of
configureWTransportForTest()
). Check out the
Mock Transports Installation guide.
Renamed entry points:
w_transport_browser.dart
--> browser.dart
w_transport_mock.dart
--> mock.dart
w_transport_vm.dart
--> vm.dart
Other renames:
Client
--> HttpClient
WSocket
--> WebSocket
WSocketException
--> WebSocketException
RetryBackOff.duration
--> RetryBackOff.interval
Other deprecations:
WSocketCloseEvent
MockBaseRequest
MockClient
MockFormRequest
MockJsonRequest
MockPlainTextRequest
MockResponse
MockStreamedRequest
MockStreamedResponse
MockWSocket
w_transport
documentation has been revamped with an emphasis on examples
and guides. Check them out now!October 14, 2016
Future
returned from WSocket.cancel()
no longer waits for
the WebSocket to be closed.September 8, 2016
StateError
may be thrown due to a Completer
being
completed more than once. This is fixed now.August 11, 2016
http_parser
dependency to speed up and/or
fix downstream consumers experiencing version conflicts.August 2, 2016
WSocket
instance and then canceling
the subscription before closing the socket would result in the "done" state
never being reached. This is fixed now and the Future
returned from
WSocket.done
and WSocket.close()
will always resolve once the connection
is closed.July 26, 2016
Improvement: All request classes now have a bool isDone
getter that can
be read to determine whether or not a request is complete (i.e. succeeded,
failed, or canceled).
Bug Fix: Calling request.abort()
more than once will no longer throw a
StateError
.
July 21, 2016
Improvement: Mock transport handlers can now be canceled. This will allow
consumers to remove HTTP or WebSocket mock handlers without having to call
MockTransports.reset()
or MockTransports.uninstall
.
var uri = Uri.parse('/example');
var myHttpHandler = MockTransports.http.when(uri, (request) { ... });
myHttpHandler.cancel();
var myWebSocketHandler = MockTransports.webSocket.when(uri,
handler: (protocols, headers) { ... });
myWebSocketHandler.cancel();
/// The same works for the `whenPattern()` methods, as well.
July 20, 2016
Bug Fix: previously, you could not retry a request that failed with a
null
response. This is now allowed, but still has the same default behavior.
To retry a request with a null
response, use the autoRetry.test
method
accordingly:
var request = new Request();
request.autoRetry
..enabled = true
..test = (request, response, willRetry) {
if (response == null) return true;
return willRetry;
};
June 23, 2016
Deprecation: autoRetry.backOff.duration
has been deprecated in
favor of the more aptly named autoRetry.backOff.interval
.
Improvement: Automatic request retrying will now add
jitter to the
backoff intervals by default. To disable jitter, set
autoRetry.backOff.withJitter = false;
.
Improvement: You can now put a cap on the backoff interval used during automatic request retrying.
request.autoRetry.backOff.maxInterval = new Duration(minutes: 2);
Bug Fix: A request's encoding
property can no longer be set to null.
This would have most likely caused an RTE when the request was sent, so now an
ArgumentError
will be thrown immediately.
Bug Fix: As of 2.6.0, if you were to set a request's content-type manually
without a charset or with an unknown charset, it was possible to hit an RTE
due to a null encoding
. The HttpBody
class has been updated to be more
resilient to a missing encoding or charset. Additionally, all request classes
will now pass in the value of its encoding
property, which should now always
be non-null.
June 20, 2016
Improvement: The MockTransport
utilities now support expecting
and registering handlers for HTTP requests and WS connections that
match a Pattern
instead of exactly matching a URI. Handlers will
also receive the Match
instance.
var response = new MockResponse.ok();
var webSocket = new MockWSocket();
var uriPattern = new RegExp('(http|ws)s:\/\/example.com\/(.*)');
// Capture any GET request to example.com/
MockTransports.http.expectPattern('GET', uriPattern, respondWith: response);
// Register a handler for any GET request to https://example.com/
// The `Match` instance will be given to the handler, where it can be used
// to read any of the captured groups.
MockTransports.http.whenPattern(uriPattern, (request, match) async {
print('path: ${match.group(2)}');
return response;
}, method: 'GET');
// Capture any WS connection attempt to example.com/
MockTransports.webSocket.expectPattern(uriPattern, connectTo: webSocket);
// Register a handler for an WS connection attempt to example.com/
// The `Match` instance will be given to the handler, where it can be used
// to read any of the captured groups.
MockTransports.webSocket.whenPattern(uriPattern, handler:
(uri, {protocols, headers, match}) async {
print('path: ${match.group(2)}');
return webSocket;
});
Improvement: the content-type for HTTP requests can now be set manually.
var request = new Request()
..uri = Uri.parse('/example')
..contentType =
new MediaType('application', 'x-custom', {'charset': UTF8.name});
The content-type still has a default value based on the type of request
(Request
- text/plain, JsonRequest
- application/json, etc.).
The content-type's charset parameter will still be updated automatically
when you set the encoding
, but once you manually set contentType
, this
behavior will stop. In other words, we are assuming that if you set
contentType
manually, you are intentionally overriding the defaults and
are taking responsibility of setting the charset
parameter appropriately.
Bug Fix: the StreamedRequest
now properly verifies that the request has
not been sent when setting contentType
. It will now throw a StateError
like the rest of the request types.
June 16, 2016
Encoding
dictated by the content-type
header, a
ResponseFormatException
will now be thrown with a much more descriptive
message. The content-type, encoding, and body will be included.June 15, 2016
Bug Fix: WSocket
extends Stream
and StreamSink
, but was not
fulfilling those contracts in all scenarios. In particular:
After obtaining a StreamSubscription
instance from a call to
WSocket.listen()
, reassigning the onData()
, onError()
, and onDone()
handlers had no effect.
var webSocket = await WSocket.connect(...);
var subscription = webSocket.listen((data) { ... });
// This does nothing:
subscription.onData((data) { ... });
// Same goes for onError() and onDone()
A subscription to a WSocket
instance did not properly respect pause and
resume signals. This could produce a memory leak by buffering WebSocket
events indefinitely.
A WSocket
instance was immediately listening to the underlying WebSocket
and buffering events from the underlying WebSocket until a listener was
registered. This is not how a standard Dart Stream
works.
The SockJS configuration was not properly handling the fact that the SockJS
Client
produces WebSocket events with a broadcast stream.
All of these issues have been addressed, and every WSocket
instance
should now behave exactly as a standard Stream
and StreamSink
would,
regardless of the platform (VM, browser, SockJS, or mock).
The
WSocketCloseEvent
class has been deprecated. This class was only used internally and should not have been exported as a part of the public API.
The WSocket implementations are no longer registering an
onError
handler for the underlying WebSocket stream. If an error occurs on the server, it will not add the error to the stream, it will just close the connection. As a result, theMockWSocket.triggerServerError()
method has been deprecated - useMockWSocket.triggerServerClose()
instead.
May 4, 2016
Improvement: FormRequest
now supports fields with multiple values.
var request = new FormRequest()
..fields['multi'] = ['one', 'two'];
SDK Compatibility: Dart 1.16 exposed a new Client
class from the
dart:html
library that conflicted with the Client
class in this library.
This has been fixed by adjusting our imports internally, but it may still
affect consumers of this library.
Documentation: fixed inaccurate documentation around mocking & testing with WebSockets.
March 2, 2016
Client
now properly inherit all of the
autoRetry
configuration. Previously the backOff
, forTimeouts
, and
maxRetries
settings were missing.February 11, 2016
Implemented retry back-off to allow fixed or exponential back-off between request retries. By default, there is no back-off.
// Fixed back-off: 1 second between attempts.
var request = new Request();
request.autoRetry
..enabled = true
..backOff = new RetryBackOff.fixed(new Duration(seconds: 1));
// Exponential back-off: 250ms, 500ms, 1s, 2s, etc (base*2^attempt)
var request = new Request();
request.autoRetry
..enabled = true
..backOff = new RetryBackOff.exponential(new Duration(milliseconds: 125));
Added methods to all request classes for manually retrying failures. This is mainly useful for corner cases where the request's success is dependent on something else and where automatic retrying won't help.
var request = new Request();
// send request, catch failure
var response = await request.retry(); // normal
var response = await request.streamRetry(); // streamed
Improved error messaging around failed requests. If automatic retrying is enabled, the error message for a failed request will include each individual attempt and why it failed.
February 8, 2016
Added an autoRetry.forTimeouts
flag (defaults to true
) to the Client
class and all request classes. This flag determines whether or not requests
that are canceled due to exceeding the timeout threshold should be retried.
// This request will retry if the timeout is exceeded.
var request = new Request()
..timeoutThreshold = new Duration(seconds: 10)
..autoRetry.enabled = true;
// This request will NOT retry if the timeout is exceeded.
var request = new Request()
..timeoutThreshold = new Duration(seconds: 10)
..autoRetry.enabled = true
..autoRetry.forTimeouts = false;
Added a Duration sockJSTimeout
config option to WSocket.connect()
.
// browser only
var socket = await WSocket.connect(Uri.parse('...'),
useSockJS: true, sockJSTimeout: new Duration(seconds: 5));
January 7, 2016
As of v2.0.0, this library could be configured to use SockJS under the hood when
the WSocket
class was used to establish WebSocket connections. This
configuration occurred on a global basis (meaning it affected every WSocket
instance) which is undesirable for applications with a mixed usage of native
WebSockets and SockJS. This global configuration has been deprecated.
As of v2.1.0, passing useSockJS: true
to the configureWTransportForBrowser()
method will cause a deprecation warning to be printed to the console.
The SockJS configuration should now occur on a per-socket basis via the
WSocket.connect()
method:
Uri uri = Uri.parse('ws://echo.websocket.org');
WSocket webSocket = await WSocket.connect(uri,
useSockJS: true, sockJSProtocolsWhitelist: ['websocket', 'xhr-streaming']);
Added a baseUri
field to Client
that all requests from the client will
inherit.
All request classes now support a timeout threshold via the timeoutTreshold
field. This was also added to the Client
class and all requests created from
a client will inherit this value.
Request and response interception is now supported. This can be done directly
on a request instance, but more usefully through a Client
instance. See
"request & response interception"
and "intercepting requests & responses from a client"
in the README.
All request classes and the Client
class now include an API for automatic
retrying via the autoRetry
field. See "automatic request retrying"
in the README.
Added a replace
method to Response
and StreamedResponse
to allow simple
creation of new responses based on another response, while changing only the
fields you specify. This is particularly useful during response interception.
.get(headers: {...})
)
are now merged with any existing headers on the request (previously they were
being ignored).November 24, 2015
The 2.0.0 release is a major breaking release. While many of the patterns from 1.0.x were maintained, the HTTP API was broken up into several request classes and two response classes for a much more robust and useful API. As such, there is no backwards compatibility, but a migration guide is included below.
WebSockets
HTTP
Request
(content-type: text/plain)JsonRequest
(content-type: application/json)FormRequest
(content-type: application/x-www-form-urlencoded)MultipartRequest
(content-type: multipart/form-data)StreamedRequest
).streamGet()
, streamPost()
, etc. on any
of the above request classes.Mocks
package:w_transport/w_transport_mock.dart
and call
configureWTransportForTest()
to configure w_transport to use mock
implementations for every class.MockTransports
class to control WebSocket connections and HTTP
requests.Testing
w_transport
has 99.7%
coverage!WRequest
#The WRequest
class attempted to cover all HTTP request use cases. Its closest
analog now is Request
- the class for sending plain-text requests. All other
request classes share a similar base API with additional support for a specific
type of request data (JSON, form, multipart, or streamed).
WResponse
#The WResponse
class made request meta data (status, headers) available as soon
as the request had finished; however, in an attempt to unify the API between the
dart:io
HTTP requests and dart:html
XHR requests, the response body was only
available asynchronously (as a stream, an untyped future, or decoded to text).
This meant two asynchronous steps were required for every request - one to get
the response, and one to get the response body.
This has been greatly improved by switching to two different response classes:
Response
- response meta data and body available synchronouslyStreamedResponse
- response meta data available synchronously, body
available as a stream of bytesJune 23, 2015
Bug Fixes:
null
.WHttp
instance.May 21, 2015
Add this to your package's pubspec.yaml file:
dependencies:
w_transport: ^3.2.8
You can install packages from the command line:
with pub:
$ pub get
with Flutter:
$ flutter packages get
Alternatively, your editor might support pub get
or flutter packages get
.
Check the docs for your editor to learn more.
Now in your Dart code, you can use:
import 'package:w_transport/w_transport.dart';
Version | Uploaded | Documentation | Archive |
---|---|---|---|
3.2.8 | Oct 11, 2018 |
|
|
3.2.7 | Oct 10, 2018 |
|
|
3.2.6 | Jul 19, 2018 |
|
|
3.2.5 | May 17, 2018 |
|
|
3.2.4 | May 17, 2018 |
|
|
3.2.3 | Apr 26, 2018 |
|
|
3.2.2 | Apr 20, 2018 |
|
|
3.2.1 | Jan 29, 2018 |
|
|
3.2.0 | Jan 10, 2018 |
|
|
3.1.2 | Sep 25, 2017 |
|
|
Popularity:
Describes how popular the package is relative to other packages.
[more]
|
75
|
Health:
Code health derived from static analysis.
[more]
|
91
|
Maintenance:
Reflects how tidy and up-to-date the package is.
[more]
|
0
|
Overall:
Weighted score of the above.
[more]
|
65
|
We analyzed this package on Feb 14, 2019, and provided a score, details, and suggestions below. Analysis was completed with status completed using:
Detected platforms: Flutter, web, other
No platform restriction found in primary library
package:w_transport/w_transport.dart
.
Fix lib/browser.dart
. (-1.49 points)
Analysis of lib/browser.dart
reported 3 hints:
line 50 col 47: Use =
to separate a named parameter from its default value.
line 51 col 48: Use =
to separate a named parameter from its default value.
line 52 col 56: Use =
to separate a named parameter from its default value.
Fix lib/src/browser_transport_platform_with_sockjs.dart
. (-1 points)
Analysis of lib/src/browser_transport_platform_with_sockjs.dart
reported 2 hints:
line 35 col 32: Use =
to separate a named parameter from its default value.
line 36 col 23: Use =
to separate a named parameter from its default value.
Fix lib/src/http/auto_retry.dart
. (-1 points)
Analysis of lib/src/http/auto_retry.dart
reported 2 hints:
line 185 col 23: Use =
to separate a named parameter from its default value.
line 191 col 59: Use =
to separate a named parameter from its default value.
Fix additional 8 files with analysis or formatting issues. (-6 points)
Additional issues in the following files:
lib/src/http/browser/request_mixin.dart
(2 hints)lib/src/web_socket/browser/sockjs.dart
(2 hints)lib/src/web_socket/browser/sockjs_port.dart
(2 hints)lib/src/web_socket/browser/sockjs_wrapper.dart
(2 hints)lib/src/http/common/request.dart
(1 hint)lib/src/http/mock/request_mixin.dart
(1 hint)lib/src/http/vm/request_mixin.dart
(1 hint)lib/src/mocks/mock_transports.dart
(1 hint)Prefer published dependencies. (-100 points)
The source code in a git
repository is mutable and could disappear.
Use constrained dependencies. (-20 points)
The pubspec.yaml
contains 1 dependency without version constraints. Specify version ranges for the following dependencies: sockjs_client
.
The description is too long. (-10 points)
Search engines display only the first part of the description. Try to keep the value of the description
field in your package's pubspec.yaml
file between 60 and 180 characters.
Update README.md
. (-2 points)
1 image link is insecure (e.g. http://codecov.io/github/Workiva/w_transport/coverage.svg?branch=master
), use https
URLs instead.
Package | Constraint | Resolved | Available |
---|---|---|---|
Direct dependencies | |||
Dart SDK | >=1.24.3 <3.0.0 | ||
dart2_constant | ^1.0.1 | 1.0.2+dart2 | |
fluri | ^1.2.2 | 1.2.5 | |
http_parser | >=2.2.0 <4.0.0 | 3.1.3 | |
meta | ^1.1.0 | 1.1.7 | |
mime | ^0.9.3 | 0.9.6+2 | |
sockjs_client | 0.3.5 | ||
sockjs_client_wrapper | ^1.0.5 | 1.0.8 | |
Transitive dependencies | |||
charcode | 1.1.2 | ||
collection | 1.14.11 | ||
intl | 0.15.7 | ||
js | 0.6.1+1 | ||
logging | 0.11.3+2 | ||
path | 1.6.2 | ||
source_span | 1.5.4 | ||
string_scanner | 1.0.4 | ||
term_glyph | 1.1.0 | ||
typed_data | 1.1.6 | ||
w_common | 1.15.0 | ||
Dev dependencies | |||
build_runner | >=0.6.0 <2.0.0 | ||
build_test | >=0.9.0 <1.0.0 | ||
build_web_compilers | >=0.2.0 <1.0.0 | ||
coverage | >=0.10.0 <0.13.0 | ||
dart_dev | ^2.0.0 | ||
dart_style | ^1.0.8 | ||
dependency_validator | ^1.2.1 | ||
http_server | ^0.9.6 | ||
mockito | >=2.0.2 <4.0.0 | ||
test | >=0.12.30 <2.0.0 | ||
uuid | >=0.5.3 <2.0.0 |