Add a shortcut for PATCH.
Closes #29
R=rnystrom@google.com
Review URL: https://codereview.chromium.org//1243783002 .
diff --git a/.gitignore b/.gitignore
index 388eff0..7dbf035 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,7 @@
.pub/
build/
packages
+.packages
# Or the files created by dart2js.
*.dart.js
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 32912e3..2438fd6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.11.3
+
+* Add a `Client.patch` shortcut method and a matching top-level `patch` method.
+
## 0.11.2
* Add a `BrowserClient.withCredentials` property.
diff --git a/lib/http.dart b/lib/http.dart
index 5b9b1f9..0fbd11b 100644
--- a/lib/http.dart
+++ b/lib/http.dart
@@ -96,6 +96,30 @@
_withClient((client) => client.put(url,
headers: headers, body: body, encoding: encoding));
+/// Sends an HTTP PATCH request with the given headers and body to the given
+/// URL, which can be a [Uri] or a [String].
+///
+/// [body] sets the body of the request. It can be a [String], a [List<int>] or
+/// a [Map<String, String>]. If it's a String, it's encoded using [encoding] and
+/// used as the body of the request. The content-type of the request will
+/// default to "text/plain".
+///
+/// If [body] is a List, it's used as a list of bytes for the body of the
+/// request.
+///
+/// If [body] is a Map, it's encoded as form fields using [encoding]. The
+/// content-type of the request will be set to
+/// `"application/x-www-form-urlencoded"`; this cannot be overridden.
+///
+/// [encoding] defaults to [UTF8].
+///
+/// For more fine-grained control over the request, use [Request] or
+/// [StreamedRequest] instead.
+Future<Response> patch(url, {Map<String, String> headers, body,
+ Encoding encoding}) =>
+ _withClient((client) => client.patch(url,
+ headers: headers, body: body, encoding: encoding));
+
/// Sends an HTTP DELETE request with the given headers to the given URL, which
/// can be a [Uri] or a [String].
///
diff --git a/lib/src/base_client.dart b/lib/src/base_client.dart
index da38e70..ad85a67 100644
--- a/lib/src/base_client.dart
+++ b/lib/src/base_client.dart
@@ -78,6 +78,28 @@
Encoding encoding}) =>
_sendUnstreamed("PUT", url, headers, body, encoding);
+ /// Sends an HTTP PATCH request with the given headers and body to the given
+ /// URL, which can be a [Uri] or a [String].
+ ///
+ /// [body] sets the body of the request. It can be a [String], a [List<int>]
+ /// or a [Map<String, String>]. If it's a String, it's encoded using
+ /// [encoding] and used as the body of the request. The content-type of the
+ /// request will default to "text/plain".
+ ///
+ /// If [body] is a List, it's used as a list of bytes for the body of the
+ /// request.
+ ///
+ /// If [body] is a Map, it's encoded as form fields using [encoding]. The
+ /// content-type of the request will be set to
+ /// `"application/x-www-form-urlencoded"`; this cannot be overridden.
+ ///
+ /// [encoding] defaults to UTF-8.
+ ///
+ /// For more fine-grained control over the request, use [send] instead.
+ Future<Response> patch(url, {Map<String, String> headers, body,
+ Encoding encoding}) =>
+ _sendUnstreamed("PATCH", url, headers, body, encoding);
+
/// Sends an HTTP DELETE request with the given headers to the given URL,
/// which can be a [Uri] or a [String].
///
diff --git a/lib/src/client.dart b/lib/src/client.dart
index e29a9e0..eaeccfe 100644
--- a/lib/src/client.dart
+++ b/lib/src/client.dart
@@ -18,7 +18,7 @@
/// The interface for HTTP clients that take care of maintaining persistent
/// connections across multiple requests to the same server. If you only need to
/// send a single request, it's usually easier to use [head], [get], [post],
-/// [put], or [delete] instead.
+/// [put], [patch], or [delete] instead.
///
/// When creating an HTTP client class with additional functionality, you must
/// extend [BaseClient] rather than [Client]. In most cases, you can wrap
@@ -89,6 +89,27 @@
Future<Response> put(url, {Map<String, String> headers, body,
Encoding encoding});
+ /// Sends an HTTP PATCH request with the given headers and body to the given
+ /// URL, which can be a [Uri] or a [String].
+ ///
+ /// [body] sets the body of the request. It can be a [String], a [List<int>]
+ /// or a [Map<String, String>]. If it's a String, it's encoded using
+ /// [encoding] and used as the body of the request. The content-type of the
+ /// request will default to "text/plain".
+ ///
+ /// If [body] is a List, it's used as a list of bytes for the body of the
+ /// request.
+ ///
+ /// If [body] is a Map, it's encoded as form fields using [encoding]. The
+ /// content-type of the request will be set to
+ /// `"application/x-www-form-urlencoded"`; this cannot be overridden.
+ ///
+ /// [encoding] defaults to [UTF8].
+ ///
+ /// For more fine-grained control over the request, use [send] instead.
+ Future<Response> patch(url, {Map<String, String> headers, body,
+ Encoding encoding});
+
/// Sends an HTTP DELETE request with the given headers to the given URL,
/// which can be a [Uri] or a [String].
///
diff --git a/pubspec.yaml b/pubspec.yaml
index 6c8cd4a..db04d4f 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
name: http
-version: 0.11.2
+version: 0.11.3
author: "Dart Team <misc@dartlang.org>"
homepage: https://github.com/dart-lang/http
description: A composable, Future-based API for making HTTP requests.
diff --git a/test/io/http_test.dart b/test/io/http_test.dart
index 9ba5924..0725c61 100644
--- a/test/io/http_test.dart
+++ b/test/io/http_test.dart
@@ -253,6 +253,110 @@
}), completes);
});
+ test('patch', () {
+ expect(startServer().then((_) {
+ expect(http.patch(serverUrl, headers: {
+ 'X-Random-Header': 'Value',
+ 'X-Other-Header': 'Other Value',
+ 'Content-Type': 'text/plain',
+ 'User-Agent': 'Dart'
+ }).then((response) {
+ expect(response.statusCode, equals(200));
+ expect(response.body, parse(equals({
+ 'method': 'PATCH',
+ 'path': '/',
+ 'headers': {
+ 'accept-encoding': ['gzip'],
+ 'content-length': ['0'],
+ 'content-type': ['text/plain'],
+ 'user-agent': ['Dart'],
+ 'x-random-header': ['Value'],
+ 'x-other-header': ['Other Value']
+ }
+ })));
+ }), completes);
+ }), completes);
+ });
+
+ test('patch with string', () {
+ expect(startServer().then((_) {
+ expect(http.patch(serverUrl, headers: {
+ 'X-Random-Header': 'Value',
+ 'X-Other-Header': 'Other Value',
+ 'User-Agent': 'Dart'
+ }, body: 'request body').then((response) {
+ expect(response.statusCode, equals(200));
+ expect(response.body, parse(equals({
+ 'method': 'PATCH',
+ 'path': '/',
+ 'headers': {
+ 'content-type': ['text/plain; charset=utf-8'],
+ 'content-length': ['12'],
+ 'accept-encoding': ['gzip'],
+ 'user-agent': ['Dart'],
+ 'x-random-header': ['Value'],
+ 'x-other-header': ['Other Value']
+ },
+ 'body': 'request body'
+ })));
+ }), completes);
+ }), completes);
+ });
+
+ test('patch with bytes', () {
+ expect(startServer().then((_) {
+ expect(http.patch(serverUrl, headers: {
+ 'X-Random-Header': 'Value',
+ 'X-Other-Header': 'Other Value',
+ 'User-Agent': 'Dart'
+ }, body: [104, 101, 108, 108, 111]).then((response) {
+ expect(response.statusCode, equals(200));
+ expect(response.body, parse(equals({
+ 'method': 'PATCH',
+ 'path': '/',
+ 'headers': {
+ 'content-length': ['5'],
+ 'accept-encoding': ['gzip'],
+ 'user-agent': ['Dart'],
+ 'x-random-header': ['Value'],
+ 'x-other-header': ['Other Value']
+ },
+ 'body': [104, 101, 108, 108, 111]
+ })));
+ }), completes);
+ }), completes);
+ });
+
+ test('patch with fields', () {
+ expect(startServer().then((_) {
+ expect(http.patch(serverUrl, headers: {
+ 'X-Random-Header': 'Value',
+ 'X-Other-Header': 'Other Value',
+ 'User-Agent': 'Dart'
+ }, body: {
+ 'some-field': 'value',
+ 'other-field': 'other value'
+ }).then((response) {
+ expect(response.statusCode, equals(200));
+ expect(response.body, parse(equals({
+ 'method': 'PATCH',
+ 'path': '/',
+ 'headers': {
+ 'content-type': [
+ 'application/x-www-form-urlencoded; charset=utf-8'
+ ],
+ 'content-length': ['40'],
+ 'accept-encoding': ['gzip'],
+ 'user-agent': ['Dart'],
+ 'x-random-header': ['Value'],
+ 'x-other-header': ['Other Value']
+ },
+ 'body': 'some-field=value&other-field=other+value'
+ })));
+ }), completes);
+ }), completes);
+ });
+
test('delete', () {
expect(startServer().then((_) {
expect(http.delete(serverUrl, headers: {