| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 import 'dart:async'; | 5 import 'dart:async'; |
| 6 import 'dart:crypto'; | 6 import 'dart:crypto'; |
| 7 import 'dart:io'; | 7 import 'dart:io'; |
| 8 import 'dart:isolate'; | 8 import 'dart:isolate'; |
| 9 import 'dart:uri'; | 9 import 'dart:uri'; |
| 10 import 'dart:utf'; | 10 import 'dart:utf'; |
| 11 | 11 |
| 12 class Server { | 12 class Server { |
| 13 HttpServer server; | 13 HttpServer server; |
| 14 bool passwordChanged = false; | 14 bool passwordChanged = false; |
| 15 | 15 |
| 16 Server() : server = new HttpServer(); | 16 Future<Server> start() { |
| 17 var completer = new Completer(); |
| 18 HttpServer.bind().then((s) { |
| 19 server = s; |
| 20 server.listen((HttpRequest request) { |
| 21 var response = request.response; |
| 22 if (request.uri.path == "/passwdchg") { |
| 23 passwordChanged = true; |
| 24 response.close(); |
| 25 return; |
| 26 }; |
| 17 | 27 |
| 18 void start() { | 28 String username; |
| 19 server.listen("127.0.0.1", 0); | 29 String password; |
| 20 server.defaultRequestHandler = | 30 if (request.uri.path == "/") { |
| 21 (HttpRequest request, HttpResponse response) { | 31 username = "username"; |
| 22 String username; | 32 password = "password"; |
| 23 String password; | 33 } else { |
| 24 if (request.path == "/") { | 34 username = request.uri.path.substring(1, 6); |
| 25 username = "username"; | 35 password = request.uri.path.substring(1, 6); |
| 26 password = "password"; | 36 } |
| 27 } else { | 37 if (passwordChanged) password = "${password}1"; |
| 28 username = request.path.substring(1, 6); | 38 if (request.headers[HttpHeaders.AUTHORIZATION] != null) { |
| 29 password = request.path.substring(1, 6); | 39 Expect.equals(1, request.headers[HttpHeaders.AUTHORIZATION].length); |
| 30 } | 40 String authorization = |
| 31 if (passwordChanged) password = "${password}1"; | 41 request.headers[HttpHeaders.AUTHORIZATION][0]; |
| 32 if (request.headers[HttpHeaders.AUTHORIZATION] != null) { | 42 List<String> tokens = authorization.split(" "); |
| 33 Expect.equals(1, request.headers[HttpHeaders.AUTHORIZATION].length); | 43 Expect.equals("Basic", tokens[0]); |
| 34 String authorization = | 44 String auth = |
| 35 request.headers[HttpHeaders.AUTHORIZATION][0]; | 45 CryptoUtils.bytesToBase64(encodeUtf8("$username:$password")); |
| 36 List<String> tokens = authorization.split(" "); | 46 if (passwordChanged && auth != tokens[1]) { |
| 37 Expect.equals("Basic", tokens[0]); | |
| 38 String auth = | |
| 39 CryptoUtils.bytesToBase64(encodeUtf8("$username:$password")); | |
| 40 if (passwordChanged && auth != tokens[1]) { | |
| 41 response.statusCode = HttpStatus.UNAUTHORIZED; | |
| 42 response.headers.set(HttpHeaders.WWW_AUTHENTICATE, | |
| 43 "Basic, realm=realm"); | |
| 44 } else { | |
| 45 Expect.equals(auth, tokens[1]); | |
| 46 } | |
| 47 } else { | |
| 48 response.statusCode = HttpStatus.UNAUTHORIZED; | 47 response.statusCode = HttpStatus.UNAUTHORIZED; |
| 49 response.headers.set(HttpHeaders.WWW_AUTHENTICATE, | 48 response.headers.set(HttpHeaders.WWW_AUTHENTICATE, |
| 50 "Basic, realm=realm"); | 49 "Basic, realm=realm"); |
| 50 } else { |
| 51 Expect.equals(auth, tokens[1]); |
| 51 } | 52 } |
| 52 response.outputStream.close(); | 53 } else { |
| 53 }; | 54 response.statusCode = HttpStatus.UNAUTHORIZED; |
| 54 server.addRequestHandler( | 55 response.headers.set(HttpHeaders.WWW_AUTHENTICATE, |
| 55 (HttpRequest request) => request.path == "/passwdchg", | 56 "Basic, realm=realm"); |
| 56 (HttpRequest request, HttpResponse response) { | 57 } |
| 57 passwordChanged = true; | 58 response.close(); |
| 58 response.outputStream.close(); | 59 }); |
| 59 }); | 60 completer.complete(this); |
| 61 }); |
| 62 return completer.future; |
| 60 } | 63 } |
| 61 | 64 |
| 62 void shutdown() { | 65 void shutdown() { |
| 63 server.close(); | 66 server.close(); |
| 64 } | 67 } |
| 65 | 68 |
| 66 int get port => server.port; | 69 int get port => server.port; |
| 67 } | 70 } |
| 68 | 71 |
| 69 Server setupServer() { | 72 Future<Server> setupServer() { |
| 70 Server server = new Server(); | 73 return new Server().start(); |
| 71 server.start(); | |
| 72 return server; | |
| 73 } | 74 } |
| 74 | 75 |
| 75 void testUrlUserInfo() { | 76 void testUrlUserInfo() { |
| 76 Server server = setupServer(); | 77 setupServer().then((server) { |
| 77 HttpClient client = new HttpClient(); | 78 HttpClient client = new HttpClient(); |
| 78 | 79 |
| 79 HttpClientConnection conn = | 80 client.getUrl(Uri.parse( |
| 80 client.getUrl( | 81 "http://username:password@127.0.0.1:${server.port}/")) |
| 81 Uri.parse( | 82 .then((request) => request.close()) |
| 82 "http://username:password@127.0.0.1:${server.port}/")); | 83 .then((HttpClientResponse response) { |
| 83 conn.onResponse = (HttpClientResponse response) { | 84 response.listen((_) {}, onDone: () { |
| 84 response.inputStream.onData = response.inputStream.read; | 85 server.shutdown(); |
| 85 response.inputStream.onClosed = () { | 86 client.close(); |
| 86 server.shutdown(); | 87 }); |
| 87 client.shutdown(); | 88 }); |
| 88 }; | 89 }); |
| 89 }; | |
| 90 } | 90 } |
| 91 | 91 |
| 92 void testBasicNoCredentials() { | 92 void testBasicNoCredentials() { |
| 93 Server server = setupServer(); | 93 setupServer().then((server) { |
| 94 HttpClient client = new HttpClient(); | 94 HttpClient client = new HttpClient(); |
| 95 | 95 |
| 96 Future makeRequest(Uri url) { | 96 Future makeRequest(Uri url) { |
| 97 Completer completer = new Completer(); | 97 return client.getUrl(url) |
| 98 HttpClientConnection conn = client.getUrl(url); | 98 .then((HttpClientRequest request) => request.close()) |
| 99 conn.onResponse = (HttpClientResponse response) { | 99 .then((HttpClientResponse response) { |
| 100 Expect.equals(HttpStatus.UNAUTHORIZED, response.statusCode); | 100 Expect.equals(HttpStatus.UNAUTHORIZED, response.statusCode); |
| 101 response.inputStream.onData = response.inputStream.read; | 101 return response.reduce(null, (x, y) {}); |
| 102 response.inputStream.onClosed = () => completer.complete(null); | 102 }); |
| 103 }; | 103 } |
| 104 return completer.future; | |
| 105 } | |
| 106 | 104 |
| 107 var futures = []; | 105 var futures = []; |
| 108 for (int i = 0; i < 5; i++) { | 106 for (int i = 0; i < 5; i++) { |
| 109 futures.add( | 107 futures.add( |
| 110 makeRequest( | 108 makeRequest( |
| 111 Uri.parse("http://127.0.0.1:${server.port}/test$i"))); | 109 Uri.parse("http://127.0.0.1:${server.port}/test$i"))); |
| 112 futures.add( | 110 futures.add( |
| 113 makeRequest( | 111 makeRequest( |
| 114 Uri.parse("http://127.0.0.1:${server.port}/test$i/xxx"))); | 112 Uri.parse( |
| 115 } | 113 "http://127.0.0.1:${server.port}/test$i/xxx"))); |
| 116 Future.wait(futures).then((_) { | 114 } |
| 117 server.shutdown(); | 115 Future.wait(futures).then((_) { |
| 118 client.shutdown(); | 116 server.shutdown(); |
| 117 client.close(); |
| 118 }); |
| 119 }); | 119 }); |
| 120 } | 120 } |
| 121 | 121 |
| 122 void testBasicCredentials() { | 122 void testBasicCredentials() { |
| 123 Server server = setupServer(); | 123 setupServer().then((server) { |
| 124 HttpClient client = new HttpClient(); | 124 HttpClient client = new HttpClient(); |
| 125 | 125 |
| 126 Future makeRequest(Uri url) { | 126 Future makeRequest(Uri url) { |
| 127 Completer completer = new Completer(); | 127 return client.getUrl(url) |
| 128 HttpClientConnection conn = client.getUrl(url); | 128 .then((HttpClientRequest request) => request.close()) |
| 129 conn.onResponse = (HttpClientResponse response) { | 129 .then((HttpClientResponse response) { |
| 130 Expect.equals(HttpStatus.OK, response.statusCode); | 130 Expect.equals(HttpStatus.OK, response.statusCode); |
| 131 response.inputStream.onData = response.inputStream.read; | 131 return response.reduce(null, (x, y) {}); |
| 132 response.inputStream.onClosed = () => completer.complete(null); | 132 }); |
| 133 }; | 133 } |
| 134 return completer.future; | |
| 135 } | |
| 136 | 134 |
| 137 for (int i = 0; i < 5; i++) { | 135 for (int i = 0; i < 5; i++) { |
| 138 client.addCredentials( | 136 client.addCredentials( |
| 139 Uri.parse("http://127.0.0.1:${server.port}/test$i"), | 137 Uri.parse("http://127.0.0.1:${server.port}/test$i"), |
| 140 "realm", | 138 "realm", |
| 141 new HttpClientBasicCredentials("test$i", "test$i")); | 139 new HttpClientBasicCredentials("test$i", "test$i")); |
| 142 } | 140 } |
| 143 | 141 |
| 144 var futures = []; | |
| 145 for (int i = 0; i < 5; i++) { | |
| 146 futures.add( | |
| 147 makeRequest( | |
| 148 Uri.parse("http://127.0.0.1:${server.port}/test$i"))); | |
| 149 futures.add( | |
| 150 makeRequest( | |
| 151 Uri.parse("http://127.0.0.1:${server.port}/test$i/xxx"))); | |
| 152 } | |
| 153 Future.wait(futures).then((_) { | |
| 154 server.shutdown(); | |
| 155 client.shutdown(); | |
| 156 }); | |
| 157 } | |
| 158 | |
| 159 void testBasicAuthenticateCallback() { | |
| 160 Server server = setupServer(); | |
| 161 HttpClient client = new HttpClient(); | |
| 162 bool passwordChanged = false; | |
| 163 | |
| 164 client.authenticate = (Uri url, String scheme, String realm) { | |
| 165 Expect.equals("Basic", scheme); | |
| 166 Expect.equals("realm", realm); | |
| 167 String username = url.path.substring(1, 6); | |
| 168 String password = url.path.substring(1, 6); | |
| 169 if (passwordChanged) password = "${password}1"; | |
| 170 Completer completer = new Completer(); | |
| 171 new Timer(const Duration(milliseconds: 10), () { | |
| 172 client.addCredentials( | |
| 173 url, realm, new HttpClientBasicCredentials(username, password)); | |
| 174 completer.complete(true); | |
| 175 }); | |
| 176 return completer.future; | |
| 177 }; | |
| 178 | |
| 179 Future makeRequest(Uri url) { | |
| 180 Completer completer = new Completer(); | |
| 181 HttpClientConnection conn = client.getUrl(url); | |
| 182 conn.onResponse = (HttpClientResponse response) { | |
| 183 Expect.equals(HttpStatus.OK, response.statusCode); | |
| 184 response.inputStream.onData = response.inputStream.read; | |
| 185 response.inputStream.onClosed = () => completer.complete(null); | |
| 186 }; | |
| 187 return completer.future; | |
| 188 } | |
| 189 | |
| 190 List<Future> makeRequests() { | |
| 191 var futures = []; | 142 var futures = []; |
| 192 for (int i = 0; i < 5; i++) { | 143 for (int i = 0; i < 5; i++) { |
| 193 futures.add( | 144 futures.add( |
| 194 makeRequest( | 145 makeRequest( |
| 195 Uri.parse("http://127.0.0.1:${server.port}/test$i"))); | 146 Uri.parse("http://127.0.0.1:${server.port}/test$i"))); |
| 196 futures.add( | 147 futures.add( |
| 197 makeRequest( | 148 makeRequest( |
| 198 Uri.parse( | 149 Uri.parse( |
| 199 "http://127.0.0.1:${server.port}/test$i/xxx"))); | 150 "http://127.0.0.1:${server.port}/test$i/xxx"))); |
| 200 } | 151 } |
| 201 return futures; | 152 Future.wait(futures).then((_) { |
| 202 } | 153 server.shutdown(); |
| 154 client.close(); |
| 155 }); |
| 156 }); |
| 157 } |
| 203 | 158 |
| 204 Future.wait(makeRequests()).then((_) { | 159 void testBasicAuthenticateCallback() { |
| 205 makeRequest( | 160 setupServer().then((server) { |
| 206 Uri.parse( | 161 HttpClient client = new HttpClient(); |
| 207 "http://127.0.0.1:${server.port}/passwdchg")).then((_) { | 162 bool passwordChanged = false; |
| 208 passwordChanged = true; | 163 |
| 209 Future.wait(makeRequests()).then((_) { | 164 client.authenticate = (Uri url, String scheme, String realm) { |
| 210 server.shutdown(); | 165 Expect.equals("Basic", scheme); |
| 211 client.shutdown(); | 166 Expect.equals("realm", realm); |
| 167 String username = url.path.substring(1, 6); |
| 168 String password = url.path.substring(1, 6); |
| 169 if (passwordChanged) password = "${password}1"; |
| 170 Completer completer = new Completer(); |
| 171 new Timer(10, (_) { |
| 172 client.addCredentials( |
| 173 url, realm, new HttpClientBasicCredentials(username, password)); |
| 174 completer.complete(true); |
| 175 }); |
| 176 return completer.future; |
| 177 }; |
| 178 |
| 179 Future makeRequest(Uri url) { |
| 180 return client.getUrl(url) |
| 181 .then((HttpClientRequest request) => request.close()) |
| 182 .then((HttpClientResponse response) { |
| 183 Expect.equals(HttpStatus.OK, response.statusCode); |
| 184 return response.reduce(null, (x, y) {}); |
| 185 }); |
| 186 } |
| 187 |
| 188 List<Future> makeRequests() { |
| 189 var futures = []; |
| 190 for (int i = 0; i < 5; i++) { |
| 191 futures.add( |
| 192 makeRequest( |
| 193 Uri.parse("http://127.0.0.1:${server.port}/test$i"))); |
| 194 futures.add( |
| 195 makeRequest( |
| 196 Uri.parse("http://127.0.0.1:${server.port}/test$i/xxx"))); |
| 197 } |
| 198 return futures; |
| 199 } |
| 200 |
| 201 Future.wait(makeRequests()).then((_) { |
| 202 makeRequest( |
| 203 Uri.parse("http://127.0.0.1:${server.port}/passwdchg")).then((_) { |
| 204 passwordChanged = true; |
| 205 Future.wait(makeRequests()).then((_) { |
| 206 server.shutdown(); |
| 207 client.close(); |
| 208 }); |
| 212 }); | 209 }); |
| 213 }); | 210 }); |
| 214 }); | 211 }); |
| 215 } | 212 } |
| 216 | 213 |
| 217 void testLocalServerBasic() { | 214 void testLocalServerBasic() { |
| 218 HttpClient client = new HttpClient(); | 215 HttpClient client = new HttpClient(); |
| 219 | 216 |
| 220 client.authenticate = (Uri url, String scheme, String realm) { | 217 client.authenticate = (Uri url, String scheme, String realm) { |
| 221 client.addCredentials( | 218 client.addCredentials( |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 262 main() { | 259 main() { |
| 263 testUrlUserInfo(); | 260 testUrlUserInfo(); |
| 264 testBasicNoCredentials(); | 261 testBasicNoCredentials(); |
| 265 testBasicCredentials(); | 262 testBasicCredentials(); |
| 266 testBasicAuthenticateCallback(); | 263 testBasicAuthenticateCallback(); |
| 267 // These teste are not normally run. They can be used for locally | 264 // These teste are not normally run. They can be used for locally |
| 268 // testing with another web server (e.g. Apache). | 265 // testing with another web server (e.g. Apache). |
| 269 //testLocalServerBasic(); | 266 //testLocalServerBasic(); |
| 270 //testLocalServerDigest(); | 267 //testLocalServerDigest(); |
| 271 } | 268 } |
| OLD | NEW |