| OLD | NEW |
| 1 // Copyright (c) 2013, 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 // VMOptions= | 5 // VMOptions= |
| 6 // VMOptions=--short_socket_read | 6 // VMOptions=--short_socket_read |
| 7 // VMOptions=--short_socket_write | 7 // VMOptions=--short_socket_write |
| 8 // VMOptions=--short_socket_read --short_socket_write | 8 // VMOptions=--short_socket_read --short_socket_write |
| 9 | 9 |
| 10 import "package:expect/expect.dart"; | 10 import "package:expect/expect.dart"; |
| 11 import "dart:isolate"; | 11 import "dart:isolate"; |
| 12 import "dart:io"; | 12 import "dart:io"; |
| 13 | 13 |
| 14 class IsolatedHttpServer { | 14 class IsolatedHttpServer { |
| 15 IsolatedHttpServer() | 15 IsolatedHttpServer() |
| 16 : _statusPort = new ReceivePort(), | 16 : _statusPort = new ReceivePort(), |
| 17 _serverPort = null { | 17 _serverPort = null; |
| 18 _serverPort = spawnFunction(startIsolatedHttpServer); | |
| 19 } | |
| 20 | 18 |
| 21 void setServerStartedHandler(void startedCallback(int port)) { | 19 void setServerStartedHandler(void startedCallback(int port)) { |
| 22 _startedCallback = startedCallback; | 20 _startedCallback = startedCallback; |
| 23 } | 21 } |
| 24 | 22 |
| 25 void start() { | 23 void start([bool chunkedEncoding = false]) { |
| 24 ReceivePort receivePort = new ReceivePort(); |
| 25 var remote = Isolate.spawn(startIsolatedHttpServer, receivePort.sendPort); |
| 26 receivePort.first.then((port) { |
| 27 _serverPort = port; |
| 28 |
| 29 if (chunkedEncoding) { |
| 30 // Send chunked encoding message to the server. |
| 31 port.send([new IsolatedHttpServerCommand.chunkedEncoding(), |
| 32 _statusPort.sendPort]); |
| 33 } |
| 34 |
| 35 // Send server start message to the server. |
| 36 var command = new IsolatedHttpServerCommand.start(); |
| 37 port.send([command, _statusPort.sendPort]); |
| 38 }); |
| 39 |
| 26 // Handle status messages from the server. | 40 // Handle status messages from the server. |
| 27 _statusPort.receive((var status, SendPort replyTo) { | 41 _statusPort.listen((var status) { |
| 28 if (status.isStarted) { | 42 if (status.isStarted) { |
| 29 _startedCallback(status.port); | 43 _startedCallback(status.port); |
| 30 } | 44 } |
| 31 }); | 45 }); |
| 32 | |
| 33 // Send server start message to the server. | |
| 34 var command = new IsolatedHttpServerCommand.start(); | |
| 35 _serverPort.send(command, _statusPort.toSendPort()); | |
| 36 } | 46 } |
| 37 | 47 |
| 38 void shutdown() { | 48 void shutdown() { |
| 39 // Send server stop message to the server. | 49 // Send server stop message to the server. |
| 40 _serverPort.send(new IsolatedHttpServerCommand.stop(), | 50 _serverPort.send([new IsolatedHttpServerCommand.stop(), |
| 41 _statusPort.toSendPort()); | 51 _statusPort.sendPort]); |
| 42 _statusPort.close(); | 52 _statusPort.close(); |
| 43 } | 53 } |
| 44 | 54 |
| 45 void chunkedEncoding() { | |
| 46 // Send chunked encoding message to the server. | |
| 47 _serverPort.send( | |
| 48 new IsolatedHttpServerCommand.chunkedEncoding(), | |
| 49 _statusPort.toSendPort()); | |
| 50 } | |
| 51 | |
| 52 ReceivePort _statusPort; // Port for receiving messages from the server. | 55 ReceivePort _statusPort; // Port for receiving messages from the server. |
| 53 SendPort _serverPort; // Port for sending messages to the server. | 56 SendPort _serverPort; // Port for sending messages to the server. |
| 54 var _startedCallback; | 57 var _startedCallback; |
| 55 } | 58 } |
| 56 | 59 |
| 57 | 60 |
| 58 class IsolatedHttpServerCommand { | 61 class IsolatedHttpServerCommand { |
| 59 static const START = 0; | 62 static const START = 0; |
| 60 static const STOP = 1; | 63 static const STOP = 1; |
| 61 static const CHUNKED_ENCODING = 2; | 64 static const CHUNKED_ENCODING = 2; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 85 bool get isStopped => _state == STOPPED; | 88 bool get isStopped => _state == STOPPED; |
| 86 bool get isError => _state == ERROR; | 89 bool get isError => _state == ERROR; |
| 87 | 90 |
| 88 int get port => _port; | 91 int get port => _port; |
| 89 | 92 |
| 90 int _state; | 93 int _state; |
| 91 int _port; | 94 int _port; |
| 92 } | 95 } |
| 93 | 96 |
| 94 | 97 |
| 95 void startIsolatedHttpServer() { | 98 void startIsolatedHttpServer(SendPort replyTo) { |
| 96 var server = new TestServer(); | 99 var server = new TestServer(); |
| 97 server.init(); | 100 server.init(); |
| 98 port.receive(server.dispatch); | 101 replyTo.send(server.dispatchSendPort); |
| 99 } | 102 } |
| 100 | 103 |
| 101 class TestServer { | 104 class TestServer { |
| 102 // Echo the request content back to the response. | 105 // Echo the request content back to the response. |
| 103 void _echoHandler(HttpRequest request) { | 106 void _echoHandler(HttpRequest request) { |
| 104 var response = request.response; | 107 var response = request.response; |
| 105 Expect.equals("POST", request.method); | 108 Expect.equals("POST", request.method); |
| 106 response.contentLength = request.contentLength; | 109 response.contentLength = request.contentLength; |
| 107 request.pipe(response); | 110 request.pipe(response); |
| 108 } | 111 } |
| 109 | 112 |
| 110 // Return a 404. | 113 // Return a 404. |
| 111 void _notFoundHandler(HttpRequest request) { | 114 void _notFoundHandler(HttpRequest request) { |
| 112 var response = request.response; | 115 var response = request.response; |
| 113 response.statusCode = HttpStatus.NOT_FOUND; | 116 response.statusCode = HttpStatus.NOT_FOUND; |
| 114 response.headers.set("Content-Type", "text/html; charset=UTF-8"); | 117 response.headers.set("Content-Type", "text/html; charset=UTF-8"); |
| 115 response.write("Page not found"); | 118 response.write("Page not found"); |
| 116 response.close(); | 119 response.close(); |
| 117 } | 120 } |
| 118 | 121 |
| 119 | 122 |
| 120 void init() { | 123 void init() { |
| 121 // Setup request handlers. | 124 // Setup request handlers. |
| 122 _requestHandlers = new Map(); | 125 _requestHandlers = new Map(); |
| 123 _requestHandlers["/echo"] = _echoHandler; | 126 _requestHandlers["/echo"] = _echoHandler; |
| 127 _dispatchPort = new ReceivePort(); |
| 128 _dispatchPort.listen(dispatch); |
| 124 } | 129 } |
| 125 | 130 |
| 126 void dispatch(message, SendPort replyTo) { | 131 SendPort get dispatchSendPort => _dispatchPort.sendPort; |
| 127 if (message.isStart) { | 132 |
| 133 void dispatch(message) { |
| 134 IsolatedHttpServerCommand command = message[0]; |
| 135 SendPort replyTo = message[1]; |
| 136 if (command.isStart) { |
| 128 try { | 137 try { |
| 129 HttpServer.bind("127.0.0.1", 0).then((server) { | 138 HttpServer.bind("127.0.0.1", 0).then((server) { |
| 130 _server = server; | 139 _server = server; |
| 131 _server.listen(_requestReceivedHandler); | 140 _server.listen(_requestReceivedHandler); |
| 132 replyTo.send( | 141 replyTo.send( |
| 133 new IsolatedHttpServerStatus.started(_server.port), null); | 142 new IsolatedHttpServerStatus.started(_server.port), null); |
| 134 }); | 143 }); |
| 135 } catch (e) { | 144 } catch (e) { |
| 136 replyTo.send(new IsolatedHttpServerStatus.error(), null); | 145 replyTo.send(new IsolatedHttpServerStatus.error(), null); |
| 137 } | 146 } |
| 138 } else if (message.isStop) { | 147 } else if (command.isStop) { |
| 139 _server.close(); | 148 _server.close(); |
| 140 port.close(); | 149 _dispatchPort.close(); |
| 141 replyTo.send(new IsolatedHttpServerStatus.stopped(), null); | 150 replyTo.send(new IsolatedHttpServerStatus.stopped(), null); |
| 142 } else if (message.isChunkedEncoding) { | 151 } else if (command.isChunkedEncoding) { |
| 143 _chunkedEncoding = true; | 152 _chunkedEncoding = true; |
| 144 } | 153 } |
| 145 } | 154 } |
| 146 | 155 |
| 147 void _requestReceivedHandler(HttpRequest request) { | 156 void _requestReceivedHandler(HttpRequest request) { |
| 148 var requestHandler =_requestHandlers[request.uri.path]; | 157 var requestHandler =_requestHandlers[request.uri.path]; |
| 149 if (requestHandler != null) { | 158 if (requestHandler != null) { |
| 150 requestHandler(request); | 159 requestHandler(request); |
| 151 } else { | 160 } else { |
| 152 _notFoundHandler(request); | 161 _notFoundHandler(request); |
| 153 } | 162 } |
| 154 } | 163 } |
| 155 | 164 |
| 156 HttpServer _server; // HTTP server instance. | 165 HttpServer _server; // HTTP server instance. |
| 166 ReceivePort _dispatchPort; |
| 157 Map _requestHandlers; | 167 Map _requestHandlers; |
| 158 bool _chunkedEncoding = false; | 168 bool _chunkedEncoding = false; |
| 159 } | 169 } |
| 160 | 170 |
| 161 void testRead(bool chunkedEncoding) { | 171 void testRead(bool chunkedEncoding) { |
| 162 String data = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; | 172 String data = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; |
| 163 final int kMessageCount = 10; | 173 final int kMessageCount = 10; |
| 164 | 174 |
| 165 IsolatedHttpServer server = new IsolatedHttpServer(); | 175 IsolatedHttpServer server = new IsolatedHttpServer(); |
| 166 | 176 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 193 httpClient.close(); | 203 httpClient.close(); |
| 194 server.shutdown(); | 204 server.shutdown(); |
| 195 } | 205 } |
| 196 }); | 206 }); |
| 197 }); | 207 }); |
| 198 } | 208 } |
| 199 sendRequest(); | 209 sendRequest(); |
| 200 } | 210 } |
| 201 | 211 |
| 202 server.setServerStartedHandler(runTest); | 212 server.setServerStartedHandler(runTest); |
| 203 if (chunkedEncoding) { | 213 server.start(chunkedEncoding); |
| 204 server.chunkedEncoding(); | |
| 205 } | |
| 206 server.start(); | |
| 207 } | 214 } |
| 208 | 215 |
| 209 void main() { | 216 void main() { |
| 210 testRead(true); | 217 testRead(true); |
| 211 testRead(false); | 218 testRead(false); |
| 212 } | 219 } |
| OLD | NEW |