| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | |
| 2 // for details. All rights reserved. Use of this source code is governed by a | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 library http.test.io_utils; | |
| 6 | |
| 7 import 'dart:async'; | |
| 8 import 'dart:convert'; | |
| 9 import 'dart:io'; | |
| 10 | |
| 11 import 'package:http/http.dart'; | |
| 12 import 'package:http/src/utils.dart'; | |
| 13 import 'package:unittest/unittest.dart'; | |
| 14 | |
| 15 export '../utils.dart'; | |
| 16 | |
| 17 /// The current server instance. | |
| 18 HttpServer _server; | |
| 19 | |
| 20 /// The URL for the current server instance. | |
| 21 Uri get serverUrl => Uri.parse('http://localhost:${_server.port}'); | |
| 22 | |
| 23 /// Starts a new HTTP server. | |
| 24 Future startServer() { | |
| 25 return HttpServer.bind("localhost", 0).then((s) { | |
| 26 _server = s; | |
| 27 s.listen((request) { | |
| 28 var path = request.uri.path; | |
| 29 var response = request.response; | |
| 30 | |
| 31 if (path == '/error') { | |
| 32 response.statusCode = 400; | |
| 33 response.contentLength = 0; | |
| 34 response.close(); | |
| 35 return; | |
| 36 } | |
| 37 | |
| 38 if (path == '/loop') { | |
| 39 var n = int.parse(request.uri.query); | |
| 40 response.statusCode = 302; | |
| 41 response.headers.set('location', | |
| 42 serverUrl.resolve('/loop?${n + 1}').toString()); | |
| 43 response.contentLength = 0; | |
| 44 response.close(); | |
| 45 return; | |
| 46 } | |
| 47 | |
| 48 if (path == '/redirect') { | |
| 49 response.statusCode = 302; | |
| 50 response.headers.set('location', serverUrl.resolve('/').toString()); | |
| 51 response.contentLength = 0; | |
| 52 response.close(); | |
| 53 return; | |
| 54 } | |
| 55 | |
| 56 if (path == '/no-content-length') { | |
| 57 response.statusCode = 200; | |
| 58 response.contentLength = -1; | |
| 59 response.write('body'); | |
| 60 response.close(); | |
| 61 return; | |
| 62 } | |
| 63 | |
| 64 new ByteStream(request).toBytes().then((requestBodyBytes) { | |
| 65 var outputEncoding; | |
| 66 var encodingName = request.uri.queryParameters['response-encoding']; | |
| 67 if (encodingName != null) { | |
| 68 outputEncoding = requiredEncodingForCharset(encodingName); | |
| 69 } else { | |
| 70 outputEncoding = ASCII; | |
| 71 } | |
| 72 | |
| 73 response.headers.contentType = | |
| 74 new ContentType( | |
| 75 "application", "json", charset: outputEncoding.name); | |
| 76 response.headers.set('single', 'value'); | |
| 77 | |
| 78 var requestBody; | |
| 79 if (requestBodyBytes.isEmpty) { | |
| 80 requestBody = null; | |
| 81 } else if (request.headers.contentType != null && | |
| 82 request.headers.contentType.charset != null) { | |
| 83 var encoding = requiredEncodingForCharset( | |
| 84 request.headers.contentType.charset); | |
| 85 requestBody = encoding.decode(requestBodyBytes); | |
| 86 } else { | |
| 87 requestBody = requestBodyBytes; | |
| 88 } | |
| 89 | |
| 90 var content = { | |
| 91 'method': request.method, | |
| 92 'path': request.uri.path, | |
| 93 'headers': {} | |
| 94 }; | |
| 95 if (requestBody != null) content['body'] = requestBody; | |
| 96 request.headers.forEach((name, values) { | |
| 97 // These headers are automatically generated by dart:io, so we don't | |
| 98 // want to test them here. | |
| 99 if (name == 'cookie' || name == 'host') return; | |
| 100 | |
| 101 content['headers'][name] = values; | |
| 102 }); | |
| 103 | |
| 104 var body = JSON.encode(content); | |
| 105 response.contentLength = body.length; | |
| 106 response.write(body); | |
| 107 response.close(); | |
| 108 }); | |
| 109 }); | |
| 110 }); | |
| 111 } | |
| 112 | |
| 113 /// Stops the current HTTP server. | |
| 114 void stopServer() { | |
| 115 if (_server != null) { | |
| 116 _server.close(); | |
| 117 _server = null; | |
| 118 } | |
| 119 } | |
| 120 | |
| 121 /// A matcher for functions that throw HttpException. | |
| 122 Matcher get throwsClientException => | |
| 123 throwsA(new isInstanceOf<ClientException>()); | |
| 124 | |
| 125 /// A matcher for RedirectLimitExceededExceptions. | |
| 126 const isRedirectLimitExceededException = | |
| 127 const _RedirectLimitExceededException(); | |
| 128 | |
| 129 /// A matcher for functions that throw RedirectLimitExceededException. | |
| 130 const Matcher throwsRedirectLimitExceededException = | |
| 131 const Throws(isRedirectLimitExceededException); | |
| 132 | |
| 133 class _RedirectLimitExceededException extends TypeMatcher { | |
| 134 const _RedirectLimitExceededException() : | |
| 135 super("RedirectLimitExceededException"); | |
| 136 | |
| 137 bool matches(item, Map matchState) => | |
| 138 item is RedirectException && item.message == "Redirect limit exceeded"; | |
| 139 } | |
| 140 | |
| 141 /// A matcher for SocketExceptions. | |
| 142 const isSocketException = const _SocketException(); | |
| 143 | |
| 144 /// A matcher for functions that throw SocketException. | |
| 145 const Matcher throwsSocketException = | |
| 146 const Throws(isSocketException); | |
| 147 | |
| 148 class _SocketException extends TypeMatcher { | |
| 149 const _SocketException() : super("SocketException"); | |
| 150 bool matches(item, Map matchState) => item is SocketException; | |
| 151 } | |
| OLD | NEW |