blob: 0843955e2bc4e3cb7266e66e366ed948952839c2 [file] [log] [blame]
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:convert';
import 'package:async/async.dart';
import 'package:http/http.dart';
import 'package:stream_channel/stream_channel.dart';
import 'package:test/test.dart';
import 'utils.dart';
class _Plus2Decoder extends Converter<List<int>, String> {
@override
String convert(List<int> input) =>
const Utf8Decoder().convert(input.map((e) => e + 2).toList());
}
class _Plus2Encoder extends Converter<String, List<int>> {
@override
List<int> convert(String input) =>
const Utf8Encoder().convert(input).map((e) => e - 2).toList();
}
/// An encoding, meant for testing, the just decrements input bytes by 2.
class _Plus2Encoding extends Encoding {
@override
Converter<List<int>, String> get decoder => _Plus2Decoder();
@override
Converter<String, List<int>> get encoder => _Plus2Encoder();
@override
String get name => 'plus2';
}
/// Tests that the [Client] correctly implements HTTP requests with bodies e.g.
/// 'POST'.
void testRequestBody(Client client) {
group('request body', () {
late final String host;
late final StreamChannel<Object?> httpServerChannel;
late final StreamQueue<Object?> httpServerQueue;
setUpAll(() async {
httpServerChannel = await startServer('request_body_server.dart');
httpServerQueue = StreamQueue(httpServerChannel.stream);
host = 'localhost:${await httpServerQueue.next}';
});
tearDownAll(() => httpServerChannel.sink.add(null));
test('client.post() with string body', () async {
await client.post(Uri.http(host, ''), body: 'Hello World!');
final serverReceivedContentType = await httpServerQueue.next;
final serverReceivedBody = await httpServerQueue.next;
expect(serverReceivedContentType, ['text/plain; charset=utf-8']);
expect(serverReceivedBody, 'Hello World!');
});
test('client.post() with string body and custom encoding', () async {
await client.post(Uri.http(host, ''),
body: 'Hello', encoding: _Plus2Encoding());
final serverReceivedContentType = await httpServerQueue.next;
final serverReceivedBody = await httpServerQueue.next;
expect(serverReceivedContentType, ['text/plain; charset=plus2']);
expect(serverReceivedBody, 'Fcjjm');
});
test('client.post() with map body', () async {
await client.post(Uri.http(host, ''), body: {'key': 'value'});
final serverReceivedContentType = await httpServerQueue.next;
final serverReceivedBody = await httpServerQueue.next;
expect(serverReceivedContentType,
['application/x-www-form-urlencoded; charset=utf-8']);
expect(serverReceivedBody, 'key=value');
});
test('client.post() with map body and encoding', () async {
await client.post(Uri.http(host, ''),
body: {'key': 'value'}, encoding: _Plus2Encoding());
final serverReceivedContentType = await httpServerQueue.next;
final serverReceivedBody = await httpServerQueue.next;
expect(serverReceivedContentType,
['application/x-www-form-urlencoded; charset=plus2']);
expect(serverReceivedBody, 'gau;r]hqa'); // key=value
});
test('client.post() with List<int>', () async {
await client.post(Uri.http(host, ''), body: [1, 2, 3, 4, 5]);
await httpServerQueue.next; // Content-Type.
final serverReceivedBody = await httpServerQueue.next as String;
// RFC 2616 7.2.1 says that:
// Any HTTP/1.1 message containing an entity-body SHOULD include a
// Content-Type header field defining the media type of that body.
// But we didn't set one explicitly so don't verify what the server
// received.
expect(serverReceivedBody.codeUnits, [1, 2, 3, 4, 5]);
});
test('client.post() with List<int> and content-type', () async {
await client.post(Uri.http(host, ''),
headers: {'Content-Type': 'image/png'}, body: [1, 2, 3, 4, 5]);
final serverReceivedContentType = await httpServerQueue.next;
final serverReceivedBody = await httpServerQueue.next as String;
expect(serverReceivedContentType, ['image/png']);
expect(serverReceivedBody.codeUnits, [1, 2, 3, 4, 5]);
});
test('client.post() with List<int> with encoding', () async {
// Encoding should not affect binary payloads.
await client.post(Uri.http(host, ''),
body: [1, 2, 3, 4, 5], encoding: _Plus2Encoding());
await httpServerQueue.next; // Content-Type.
final serverReceivedBody = await httpServerQueue.next as String;
// RFC 2616 7.2.1 says that:
// Any HTTP/1.1 message containing an entity-body SHOULD include a
// Content-Type header field defining the media type of that body.
// But we didn't set one explicitly so don't verify what the server
// received.
expect(serverReceivedBody.codeUnits, [1, 2, 3, 4, 5]);
});
test('client.post() with List<int> with encoding and content-type',
() async {
// Encoding should not affect the payload but it should affect the
// content-type.
await client.post(Uri.http(host, ''),
headers: {'Content-Type': 'image/png'},
body: [1, 2, 3, 4, 5],
encoding: _Plus2Encoding());
final serverReceivedContentType = await httpServerQueue.next;
final serverReceivedBody = await httpServerQueue.next as String;
expect(serverReceivedContentType, ['image/png; charset=plus2']);
expect(serverReceivedBody.codeUnits, [1, 2, 3, 4, 5]);
});
});
}