| 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 part of vmservice_io; | 5 part of vmservice_io; |
| 6 | 6 |
| 7 class WebSocketClient extends Client { | 7 class WebSocketClient extends Client { |
| 8 static const int PARSE_ERROR_CODE = 4000; | 8 static const int PARSE_ERROR_CODE = 4000; |
| 9 static const int BINARY_MESSAGE_ERROR_CODE = 4001; | 9 static const int BINARY_MESSAGE_ERROR_CODE = 4001; |
| 10 static const int NOT_MAP_ERROR_CODE = 4002; | 10 static const int NOT_MAP_ERROR_CODE = 4002; |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 98 } | 98 } |
| 99 } | 99 } |
| 100 | 100 |
| 101 class Server { | 101 class Server { |
| 102 static const WEBSOCKET_PATH = '/ws'; | 102 static const WEBSOCKET_PATH = '/ws'; |
| 103 static const ROOT_REDIRECT_PATH = '/index.html'; | 103 static const ROOT_REDIRECT_PATH = '/index.html'; |
| 104 | 104 |
| 105 final VMService _service; | 105 final VMService _service; |
| 106 final String _ip; | 106 final String _ip; |
| 107 final int _port; | 107 final int _port; |
| 108 | 108 final bool _originCheckDisabled; |
| 109 final List<String> _allowedOrigins = <String>[]; |
| 109 HttpServer _server; | 110 HttpServer _server; |
| 110 bool get running => _server != null; | 111 bool get running => _server != null; |
| 111 bool _displayMessages = false; | 112 bool _displayMessages = false; |
| 112 | 113 |
| 113 Server(this._service, this._ip, this._port) { | 114 Server(this._service, this._ip, this._port, this._originCheckDisabled) { |
| 114 _displayMessages = (_ip != '127.0.0.1' || _port != 8181); | 115 _displayMessages = (_ip != '127.0.0.1' || _port != 8181); |
| 115 } | 116 } |
| 116 | 117 |
| 118 void _addOrigin(String host, String port) { |
| 119 String origin = 'http://$host:$port'; |
| 120 _allowedOrigins.add(origin); |
| 121 } |
| 122 |
| 123 bool _isAllowedOrigin(String origin) { |
| 124 for (String allowedOrigin in _allowedOrigins) { |
| 125 if (origin.startsWith(allowedOrigin)) { |
| 126 return true; |
| 127 } |
| 128 } |
| 129 return false; |
| 130 } |
| 131 |
| 132 bool _originCheck(HttpRequest request) { |
| 133 if (_originCheckDisabled) { |
| 134 // Always allow. |
| 135 return true; |
| 136 } |
| 137 // First check the web-socket specific origin. |
| 138 List<String> origins = request.headers["Sec-WebSocket-Origin"]; |
| 139 if (origins == null) { |
| 140 // Fall back to the general Origin field. |
| 141 origins = request.headers["Origin"]; |
| 142 } |
| 143 if (origins == null) { |
| 144 // No origin sent. This is a non-browser client or a same-origin request. |
| 145 return true; |
| 146 } |
| 147 for (String origin in origins) { |
| 148 if (_isAllowedOrigin(origin)) { |
| 149 return true; |
| 150 } |
| 151 } |
| 152 return false; |
| 153 } |
| 154 |
| 117 void _requestHandler(HttpRequest request) { | 155 void _requestHandler(HttpRequest request) { |
| 118 // Allow cross origin requests with 'observatory' header. | 156 if (!_originCheck(request)) { |
| 119 request.response.headers.add('Access-Control-Allow-Origin', '*'); | 157 // This is a cross origin attempt to connect |
| 120 request.response.headers.add('Access-Control-Allow-Headers', | 158 request.response.close(); |
| 121 'Observatory-Version'); | 159 return; |
| 122 | 160 } |
| 123 if (request.method != 'GET') { | 161 if (request.method != 'GET') { |
| 124 // Not a GET request. Do nothing. | 162 // Not a GET request. Do nothing. |
| 125 request.response.close(); | 163 request.response.close(); |
| 126 return; | 164 return; |
| 127 } | 165 } |
| 128 | 166 |
| 129 final String path = | 167 final String path = |
| 130 request.uri.path == '/' ? ROOT_REDIRECT_PATH : request.uri.path; | 168 request.uri.path == '/' ? ROOT_REDIRECT_PATH : request.uri.path; |
| 131 | 169 |
| 132 if (path == WEBSOCKET_PATH) { | 170 if (path == WEBSOCKET_PATH) { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 158 rethrow; | 196 rethrow; |
| 159 } | 197 } |
| 160 } | 198 } |
| 161 | 199 |
| 162 Future startup() { | 200 Future startup() { |
| 163 if (_server != null) { | 201 if (_server != null) { |
| 164 // Already running. | 202 // Already running. |
| 165 return new Future.value(this); | 203 return new Future.value(this); |
| 166 } | 204 } |
| 167 | 205 |
| 206 // Clear allowed origins. |
| 207 _allowedOrigins.clear(); |
| 208 |
| 168 var address = new InternetAddress(_ip); | 209 var address = new InternetAddress(_ip); |
| 169 // Startup HTTP server. | 210 // Startup HTTP server. |
| 170 return HttpServer.bind(address, _port).then((s) { | 211 return HttpServer.bind(address, _port).then((s) { |
| 171 _server = s; | 212 _server = s; |
| 172 _server.listen(_requestHandler, cancelOnError: true); | 213 _server.listen(_requestHandler, cancelOnError: true); |
| 173 var ip = _server.address.address.toString(); | 214 var ip = _server.address.address.toString(); |
| 174 var port = _server.port.toString(); | 215 var port = _server.port.toString(); |
| 216 // Add the numeric ip and host name to our allowed origins. |
| 217 _addOrigin(ip, port); |
| 218 _addOrigin(_server.address.host.toString(), port); |
| 219 // Explicitly add localhost and 127.0.0.1. |
| 220 _addOrigin('localhost', port); |
| 221 _addOrigin('127.0.0.1', port); |
| 175 if (_displayMessages) { | 222 if (_displayMessages) { |
| 176 print('Observatory listening on http://$ip:$port'); | 223 print('Observatory listening on http://$ip:$port'); |
| 177 } | 224 } |
| 178 // Server is up and running. | 225 // Server is up and running. |
| 179 _notifyServerState(ip, _server.port); | 226 _notifyServerState(ip, _server.port); |
| 180 onServerAddressChange('http://$ip:$port'); | 227 onServerAddressChange('http://$ip:$port'); |
| 181 return this; | 228 return this; |
| 182 }).catchError((e, st) { | 229 }).catchError((e, st) { |
| 183 print('Could not start Observatory HTTP server:\n$e\n$st\n'); | 230 print('Could not start Observatory HTTP server:\n$e\n$st\n'); |
| 184 _notifyServerState("", 0); | 231 _notifyServerState("", 0); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 220 _notifyServerState("", 0); | 267 _notifyServerState("", 0); |
| 221 onServerAddressChange(null); | 268 onServerAddressChange(null); |
| 222 return this; | 269 return this; |
| 223 }); | 270 }); |
| 224 } | 271 } |
| 225 | 272 |
| 226 } | 273 } |
| 227 | 274 |
| 228 void _notifyServerState(String ip, int port) | 275 void _notifyServerState(String ip, int port) |
| 229 native "VMServiceIO_NotifyServerState"; | 276 native "VMServiceIO_NotifyServerState"; |
| OLD | NEW |