Skip to content

Commit 4b0e3b1

Browse files
committed
feat(Http): Http service can make cross-site requests (get, post, put, etc.) which use credentials (such as cookies or authorization headers).
Closes dart-archive#945
1 parent 6bbd7f6 commit 4b0e3b1

File tree

2 files changed

+89
-25
lines changed

2 files changed

+89
-25
lines changed

lib/core_dom/http.dart

+35-25
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,8 @@ class Http {
410410
* - headers: Map of strings or functions which return strings representing
411411
* HTTP headers to send to the server. If the return value of a function
412412
* is null, the header will not be sent.
413+
* - withCredentials: True if cross-site requests should use credentials such as cookies or
414+
* authorization headers; false otherwise. If not specified, defaults to false.
413415
* - xsrfHeaderName: TBI
414416
* - xsrfCookieName: TBI
415417
* - interceptors: Either a [HttpInterceptor] or a [HttpInterceptors]
@@ -422,6 +424,7 @@ class Http {
422424
data,
423425
Map<String, dynamic> params,
424426
Map<String, dynamic> headers,
427+
bool withCredentials: false,
425428
xsrfHeaderName,
426429
xsrfCookieName,
427430
interceptors,
@@ -481,7 +484,8 @@ class Http {
481484
var result = _backend.request(url,
482485
method: method,
483486
requestHeaders: config.headers,
484-
sendData: config.data).then((dom.HttpRequest value) {
487+
sendData: config.data,
488+
withCredentials: withCredentials).then((dom.HttpRequest value) {
485489
// TODO: Uncomment after apps migrate off of this class.
486490
// assert(value.status >= 200 && value.status < 300);
487491

@@ -535,15 +539,16 @@ class Http {
535539
String data,
536540
Map<String, dynamic> params,
537541
Map<String, String> headers,
542+
bool withCredentials: false,
538543
xsrfHeaderName,
539544
xsrfCookieName,
540545
interceptors,
541546
cache,
542547
timeout
543-
}) => call(method: 'GET', url: url, data: data, params: params,
544-
headers: headers, xsrfHeaderName: xsrfHeaderName,
545-
xsrfCookieName: xsrfCookieName, interceptors: interceptors,
546-
cache: cache, timeout: timeout);
548+
}) => call(method: 'GET', url: url, data: data, params: params, headers: headers,
549+
withCredentials: withCredentials, xsrfHeaderName: xsrfHeaderName,
550+
xsrfCookieName: xsrfCookieName, interceptors: interceptors, cache: cache,
551+
timeout: timeout);
547552

548553
/**
549554
* Shortcut method for DELETE requests. See [call] for a complete description
@@ -553,15 +558,16 @@ class Http {
553558
String data,
554559
Map<String, dynamic> params,
555560
Map<String, String> headers,
561+
bool withCredentials: false,
556562
xsrfHeaderName,
557563
xsrfCookieName,
558564
interceptors,
559565
cache,
560566
timeout
561-
}) => call(method: 'DELETE', url: url, data: data, params: params,
562-
headers: headers, xsrfHeaderName: xsrfHeaderName,
563-
xsrfCookieName: xsrfCookieName, interceptors: interceptors,
564-
cache: cache, timeout: timeout);
567+
}) => call(method: 'DELETE', url: url, data: data, params: params, headers: headers,
568+
withCredentials: withCredentials, xsrfHeaderName: xsrfHeaderName,
569+
xsrfCookieName: xsrfCookieName, interceptors: interceptors, cache: cache,
570+
timeout: timeout);
565571

566572
/**
567573
* Shortcut method for HEAD requests. See [call] for a complete description
@@ -571,15 +577,16 @@ class Http {
571577
String data,
572578
Map<String, dynamic> params,
573579
Map<String, String> headers,
580+
bool withCredentials: false,
574581
xsrfHeaderName,
575582
xsrfCookieName,
576583
interceptors,
577584
cache,
578585
timeout
579-
}) => call(method: 'HEAD', url: url, data: data, params: params,
580-
headers: headers, xsrfHeaderName: xsrfHeaderName,
581-
xsrfCookieName: xsrfCookieName, interceptors: interceptors,
582-
cache: cache, timeout: timeout);
586+
}) => call(method: 'HEAD', url: url, data: data, params: params, headers: headers,
587+
withCredentials: withCredentials, xsrfHeaderName: xsrfHeaderName,
588+
xsrfCookieName: xsrfCookieName, interceptors: interceptors, cache: cache,
589+
timeout: timeout);
583590

584591
/**
585592
* Shortcut method for PUT requests. See [call] for a complete description
@@ -588,15 +595,16 @@ class Http {
588595
async.Future<HttpResponse> put(String url, String data, {
589596
Map<String, dynamic> params,
590597
Map<String, String> headers,
598+
bool withCredentials: false,
591599
xsrfHeaderName,
592600
xsrfCookieName,
593601
interceptors,
594602
cache,
595603
timeout
596-
}) => call(method: 'PUT', url: url, data: data, params: params,
597-
headers: headers, xsrfHeaderName: xsrfHeaderName,
598-
xsrfCookieName: xsrfCookieName, interceptors: interceptors,
599-
cache: cache, timeout: timeout);
604+
}) => call(method: 'PUT', url: url, data: data, params: params, headers: headers,
605+
withCredentials: withCredentials, xsrfHeaderName: xsrfHeaderName,
606+
xsrfCookieName: xsrfCookieName, interceptors: interceptors, cache: cache,
607+
timeout: timeout);
600608

601609
/**
602610
* Shortcut method for POST requests. See [call] for a complete description
@@ -605,15 +613,16 @@ class Http {
605613
async.Future<HttpResponse> post(String url, String data, {
606614
Map<String, dynamic> params,
607615
Map<String, String> headers,
616+
bool withCredentials: false,
608617
xsrfHeaderName,
609618
xsrfCookieName,
610619
interceptors,
611620
cache,
612621
timeout
613-
}) => call(method: 'POST', url: url, data: data, params: params,
614-
headers: headers, xsrfHeaderName: xsrfHeaderName,
615-
xsrfCookieName: xsrfCookieName, interceptors: interceptors,
616-
cache: cache, timeout: timeout);
622+
}) => call(method: 'POST', url: url, data: data, params: params, headers: headers,
623+
withCredentials: withCredentials, xsrfHeaderName: xsrfHeaderName,
624+
xsrfCookieName: xsrfCookieName, interceptors: interceptors, cache: cache,
625+
timeout: timeout);
617626

618627
/**
619628
* Shortcut method for JSONP requests. See [call] for a complete description
@@ -623,15 +632,16 @@ class Http {
623632
String data,
624633
Map<String, dynamic> params,
625634
Map<String, String> headers,
635+
bool withCredentials: false,
626636
xsrfHeaderName,
627637
xsrfCookieName,
628638
interceptors,
629639
cache,
630640
timeout
631-
}) => call(method: 'JSONP', url: url, data: data, params: params,
632-
headers: headers, xsrfHeaderName: xsrfHeaderName,
633-
xsrfCookieName: xsrfCookieName, interceptors: interceptors,
634-
cache: cache, timeout: timeout);
641+
}) => call(method: 'JSONP', url: url, data: data, params: params, headers: headers,
642+
withCredentials: withCredentials, xsrfHeaderName: xsrfHeaderName,
643+
xsrfCookieName: xsrfCookieName, interceptors: interceptors, cache: cache,
644+
timeout: timeout);
635645

636646
/**
637647
* Parse raw headers into key-value object

test/core_dom/http_spec.dart

+54
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,23 @@ void main() {
9898
flush();
9999
}));
100100

101+
describe('backend', () {
102+
beforeEachModule((Module module) {
103+
FakeBackend fakeBackend = new FakeBackend();
104+
module.bind(HttpBackend, toFactory: (i) => fakeBackend);
105+
module.bind(FakeBackend, toFactory: (i) => i.get(HttpBackend));
106+
});
107+
108+
it('should pass on withCredentials to backend and use GET as default method',
109+
async((FakeBackend backend) {
110+
http(url: '/url', method: 'GET', withCredentials: true);
111+
microLeap();
112+
expect(backend.url).toEqual('/url');
113+
expect(backend.method).toEqual('GET');
114+
expect(backend.withCredentials).toBeTruthy();
115+
}));
116+
});
117+
101118

102119
describe('params', () {
103120
it('should do basic request with params and encode', async(() {
@@ -1356,3 +1373,40 @@ class FakeFile implements File {
13561373
Blob slice([int start, int end, String contentType]) => null;
13571374
int get lastModified => new DateTime.now().millisecondsSinceEpoch;
13581375
}
1376+
1377+
class FakeBackend extends Mock implements HttpBackend {
1378+
1379+
String url;
1380+
String method;
1381+
bool withCredentials;
1382+
String responseType;
1383+
String mimeType;
1384+
Map<String, String> requestHeaders;
1385+
dynamic sendData;
1386+
1387+
Future<HttpRequest> request(String url, {
1388+
String method,
1389+
bool withCredentials,
1390+
String responseType,
1391+
String mimeType,
1392+
Map<String, String> requestHeaders,
1393+
sendData,
1394+
void onProgress(ProgressEvent e)}) {
1395+
this.url = url;
1396+
this.method = method;
1397+
this.withCredentials = withCredentials;
1398+
this.responseType = responseType;
1399+
this.mimeType = mimeType;
1400+
this.requestHeaders = requestHeaders;
1401+
this.sendData = sendData;
1402+
HttpRequest request = new HttpRequest();
1403+
return new Future.value(new HttpRequest());
1404+
}
1405+
}
1406+
1407+
class FakeHttpRequest extends Mock implements HttpRequest {
1408+
FakeHttpRequest() {
1409+
when(callsTo('get status')).thenReturn(200);
1410+
when(callsTo('get responseText')).thenReturn('Fake Request');
1411+
}
1412+
}

0 commit comments

Comments
 (0)