Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(586)

Side by Side Diff: sdk/lib/io/http_impl.dart

Issue 11829025: Re-implement http sessions. (Closed) Base URL: https://dart.googlecode.com/svn/experimental/lib_v2_io/dart
Patch Set: Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « sdk/lib/io/http_headers.dart ('k') | tests/standalone/io/http_session_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 5
6 class _HttpIncoming extends StreamController<List<int>> { 6 class _HttpIncoming extends StreamController<List<int>> {
7 final Function _pause; 7 final Function _pause;
8 final Function _resume; 8 final Function _resume;
9 bool _ignore = false; 9 bool _ignore = false;
10 final SignalCompleter _dataCompleter = new SignalCompleter(); 10 final SignalCompleter _dataCompleter = new SignalCompleter();
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
59 super.close(); 59 super.close();
60 } 60 }
61 61
62 void add(List<int> data) { 62 void add(List<int> data) {
63 if (!_ignore) super.add(data); 63 if (!_ignore) super.add(data);
64 } 64 }
65 } 65 }
66 66
67 class _HttpInboundMessage extends Stream<List<int>> { 67 class _HttpInboundMessage extends Stream<List<int>> {
68 final _HttpIncoming _incoming; 68 final _HttpIncoming _incoming;
69 List<Cookie> _cookies;
69 70
70 _HttpInboundMessage(_HttpIncoming this._incoming); 71 _HttpInboundMessage(_HttpIncoming this._incoming);
71 72
73 List<Cookie> get cookies {
74 if (_cookies != null) return _cookies;
75 return _cookies = headers._parseCookies();
76 }
77
72 HttpHeaders get headers => _incoming.headers; 78 HttpHeaders get headers => _incoming.headers;
73 String get protocolVersion => headers.protocolVersion; 79 String get protocolVersion => headers.protocolVersion;
74 int get contentLength => headers.contentLength; 80 int get contentLength => headers.contentLength;
75 } 81 }
76 82
77 83
78 class _HttpRequest extends _HttpInboundMessage implements HttpRequest { 84 class _HttpRequest extends _HttpInboundMessage implements HttpRequest {
79 final HttpResponse response; 85 final HttpResponse response;
80 86
81 // Lazy initialized parsed query parameters. 87 // Lazy initialized parsed query parameters.
82 Map<String, String> _queryParameters; 88 Map<String, String> _queryParameters;
83 89
84 _HttpRequest(_HttpResponse this.response, _HttpIncoming _incoming) 90 final _HttpServer _httpServer;
91
92 HttpSession _session;
93
94 _HttpRequest(_HttpResponse this.response,
95 _HttpIncoming _incoming,
96 _HttpServer this._httpServer)
85 : super(_incoming) { 97 : super(_incoming) {
86 response.headers.persistentConnection = headers.persistentConnection; 98 response.headers.persistentConnection = headers.persistentConnection;
99
100 if (_httpServer._sessionManagerInstance != null) {
101 // Map to session if exists.
102 var sessionId = cookies.reduce(null, (last, cookie) {
103 if (last != null) return last;
104 return cookie.name.toUpperCase() == _DART_SESSION_ID ?
105 cookie.value : null;
106 });
107 if (sessionId != null) {
108 _session = _httpServer._sessionManager.getSession(sessionId);
109 if (_session != null) {
110 _session._markSeen();
111 }
112 }
113 }
87 } 114 }
88 115
89 StreamSubscription<T> listen(void onData(List<int> event), 116 StreamSubscription<T> listen(void onData(List<int> event),
90 {void onError(AsyncError error), 117 {void onError(AsyncError error),
91 void onDone(), 118 void onDone(),
92 bool unsubscribeOnError}) { 119 bool unsubscribeOnError}) {
93 return _incoming.listen(onData, 120 return _incoming.listen(onData,
94 onError: onError, 121 onError: onError,
95 onDone: onDone, 122 onDone: onDone,
96 unsubscribeOnError: unsubscribeOnError); 123 unsubscribeOnError: unsubscribeOnError);
97 } 124 }
98 125
99 Map<String, String> get queryParameters { 126 Map<String, String> get queryParameters {
100 if (_queryParameters == null) { 127 if (_queryParameters == null) {
101 _queryParameters = _HttpUtils.splitQueryString(uri.query); 128 _queryParameters = _HttpUtils.splitQueryString(uri.query);
102 } 129 }
103 return _queryParameters; 130 return _queryParameters;
104 } 131 }
105 132
106 Uri get uri => _incoming.uri; 133 Uri get uri => _incoming.uri;
107 134
108 String get method => _incoming.method; 135 String get method => _incoming.method;
136
137 HttpSession session([init(HttpSession session)]) {
138 if (_session != null) {
139 // It's already mapped, use it.
140 return _session;
141 }
142 // Create session, store it in connection, and return.
143 return _session = _httpServer._sessionManager.createSession(init);
144 }
109 } 145 }
110 146
111 147
112 class _HttpClientResponse 148 class _HttpClientResponse
113 extends _HttpInboundMessage implements HttpClientResponse { 149 extends _HttpInboundMessage implements HttpClientResponse {
114 List<RedirectInfo> get redirects => _httpRequest._responseRedirects; 150 List<RedirectInfo> get redirects => _httpRequest._responseRedirects;
115 151
116 // The HttpClient this response belongs to. 152 // The HttpClient this response belongs to.
117 final _HttpClient _httpClient; 153 final _HttpClient _httpClient;
118 154
119 // The HttpClientRequest of this response. 155 // The HttpClientRequest of this response.
120 final _HttpClientRequest _httpRequest; 156 final _HttpClientRequest _httpRequest;
121 157
158 List<Cookie> _cookies;
159
122 _HttpClientResponse(_HttpIncoming _incoming, 160 _HttpClientResponse(_HttpIncoming _incoming,
123 _HttpClientRequest this._httpRequest, 161 _HttpClientRequest this._httpRequest,
124 _HttpClient this._httpClient) 162 _HttpClient this._httpClient)
125 : super(_incoming); 163 : super(_incoming);
126 164
127 int get statusCode => _incoming.statusCode; 165 int get statusCode => _incoming.statusCode;
128 String get reasonPhrase => _incoming.reasonPhrase; 166 String get reasonPhrase => _incoming.reasonPhrase;
129 167
168 List<Cookie> get cookies {
169 if (_cookies != null) return _cookies;
170 _cookies = new List<Cookie>();
171 List<String> values = headers["set-cookie"];
172 if (values != null) {
173 values.forEach((value) {
174 _cookies.add(new Cookie.fromSetCookieValue(value));
175 });
176 }
177 return _cookies;
178 }
179
130 bool get isRedirect { 180 bool get isRedirect {
131 if (_httpRequest.method == "GET" || _httpRequest.method == "HEAD") { 181 if (_httpRequest.method == "GET" || _httpRequest.method == "HEAD") {
132 return statusCode == HttpStatus.MOVED_PERMANENTLY || 182 return statusCode == HttpStatus.MOVED_PERMANENTLY ||
133 statusCode == HttpStatus.FOUND || 183 statusCode == HttpStatus.FOUND ||
134 statusCode == HttpStatus.SEE_OTHER || 184 statusCode == HttpStatus.SEE_OTHER ||
135 statusCode == HttpStatus.TEMPORARY_REDIRECT; 185 statusCode == HttpStatus.TEMPORARY_REDIRECT;
136 } else if (_httpRequest.method == "POST") { 186 } else if (_httpRequest.method == "POST") {
137 return statusCode == HttpStatus.SEE_OTHER; 187 return statusCode == HttpStatus.SEE_OTHER;
138 } 188 }
139 return false; 189 return false;
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
309 final _HttpHeaders headers; 359 final _HttpHeaders headers;
310 360
311 final _HttpOutgoing _outgoing; 361 final _HttpOutgoing _outgoing;
312 bool _headersWritten = false; 362 bool _headersWritten = false;
313 bool _chunked = false; 363 bool _chunked = false;
314 } 364 }
315 365
316 366
317 class _HttpResponse extends _HttpOutboundMessage<HttpResponse> 367 class _HttpResponse extends _HttpOutboundMessage<HttpResponse>
318 implements HttpResponse { 368 implements HttpResponse {
319 _HttpResponse(String protocolVersion, _HttpOutgoing _outgoing) 369 int statusCode = 200;
370 String reasonPhrase = "OK";
371
372 List<Cookie> _cookies;
373 _HttpRequest _httpRequest;
374
375 _HttpResponse(String protocolVersion,
376 _HttpOutgoing _outgoing)
320 : super(protocolVersion, _outgoing); 377 : super(protocolVersion, _outgoing);
321 378
322 int statusCode = 200; 379 List<Cookie> get cookies {
323 380 if (_cookies == null) _cookies = new List<Cookie>();
324 String reasonPhrase = "OK"; 381 return _cookies;
382 }
325 383
326 void _writeHeader() { 384 void _writeHeader() {
327 writeSP() => add([_CharCode.SP]); 385 writeSP() => add([_CharCode.SP]);
328 writeCRLF() => add([_CharCode.CR, _CharCode.LF]); 386 writeCRLF() => add([_CharCode.CR, _CharCode.LF]);
329 387
330 // Write status line. 388 // Write status line.
331 if (headers.protocolVersion == "1.1") { 389 if (headers.protocolVersion == "1.1") {
332 add(_Const.HTTP11); 390 add(_Const.HTTP11);
333 } else { 391 } else {
334 add(_Const.HTTP10); 392 add(_Const.HTTP10);
335 } 393 }
336 writeSP(); 394 writeSP();
337 addString(statusCode.toString()); 395 addString(statusCode.toString());
338 writeSP(); 396 writeSP();
339 addString(reasonPhrase); 397 addString(reasonPhrase);
340 writeCRLF(); 398 writeCRLF();
341 399
400 var session = _httpRequest._session;
401 if (session != null && !session._destroyed) {
402 // Make sure we only send the current session id.
403 bool found = false;
404 for (int i = 0; i < cookies.length; i++) {
405 if (cookies[i].name.toUpperCase() == _DART_SESSION_ID) {
406 cookies[i].value = session.id;
407 cookies[i].httpOnly = true;
408 found = true;
409 break;
410 }
411 }
412 if (!found) {
413 cookies.add(new Cookie(_DART_SESSION_ID, session.id)..httpOnly = true);
414 }
415 }
416 // Add all the cookies set to the headers.
417 if (_cookies != null) {
418 _cookies.forEach((cookie) {
419 headers.add("set-cookie", cookie);
420 });
421 }
422
342 headers._finalize(); 423 headers._finalize();
343 424
344 // Write headers. 425 // Write headers.
345 headers._write(this); 426 headers._write(this);
346 writeCRLF(); 427 writeCRLF();
347 } 428 }
348 } 429 }
349 430
350 431
351 class _HttpClientRequest extends _HttpOutboundMessage<HttpClientRequest> 432 class _HttpClientRequest extends _HttpOutboundMessage<HttpClientRequest>
(...skipping 491 matching lines...) Expand 10 before | Expand all | Expand 10 after
843 void _removeCredentials(_Credentials cr) { 924 void _removeCredentials(_Credentials cr) {
844 int index = _credentials.indexOf(cr); 925 int index = _credentials.indexOf(cr);
845 if (index != -1) { 926 if (index != -1) {
846 _credentials.removeAt(index); 927 _credentials.removeAt(index);
847 } 928 }
848 } 929 }
849 } 930 }
850 931
851 932
852 class _HttpConnection { 933 class _HttpConnection {
853 _HttpConnection(Socket this._socket, Function this._handleRequest) { 934 final Socket _socket;
935 final _HttpServer _httpServer;
936
937 _HttpConnection(Socket this._socket, _HttpServer this._httpServer) {
854 var parser = new _HttpParser.requestParser(); 938 var parser = new _HttpParser.requestParser();
855 _socket.pipe(parser); 939 _socket.pipe(parser);
856 parser.listen( 940 parser.listen(
857 (incoming) { 941 (incoming) {
858 var outgoing = new _HttpOutgoing(); 942 var outgoing = new _HttpOutgoing();
859 outgoing.stream.then(_socket.writeStream); 943 outgoing.stream.then(_socket.writeStream);
860 var response = new _HttpResponse( 944 var response = new _HttpResponse(
861 incoming.headers.protocolVersion, 945 incoming.headers.protocolVersion,
862 outgoing); 946 outgoing);
863 var request = new _HttpRequest(response, incoming); 947 var request = new _HttpRequest(response, incoming, _httpServer);
948 response._httpRequest = request;
864 outgoing.dataDone.then(() { 949 outgoing.dataDone.then(() {
865 if (response.headers.persistentConnection) { 950 if (response.headers.persistentConnection) {
866 // Mark incoming as done, preparing for next HTTP request. 951 // Mark incoming as done, preparing for next HTTP request.
867 incoming.done(); 952 incoming.done();
868 } else { 953 } else {
869 // Close socket, keep-alive not used. 954 // Close socket, keep-alive not used.
870 _socket.destroy(); 955 _socket.destroy();
871 } 956 }
872 }); 957 });
873 _handleRequest(request); 958 _httpServer._handleRequest(request);
874 }, 959 },
875 onDone: () { 960 onDone: () {
876 // TODO(ajohnsen): Remove connection from active connection queue. 961 // TODO(ajohnsen): Remove connection from active connection queue.
877 }, 962 },
878 onError: (error) { 963 onError: (error) {
879 // TODO(ajohnsen): Handle errors. 964 // TODO(ajohnsen): Handle errors.
880 }); 965 });
881 } 966 }
882
883 final Function _handleRequest;
884
885 final Socket _socket;
886 } 967 }
887 968
888 969
889 // HTTP server waiting for socket connections. 970 // HTTP server waiting for socket connections.
890 class _HttpServer extends Stream<HttpRequest> implements HttpServer { 971 class _HttpServer extends Stream<HttpRequest> implements HttpServer {
891 _HttpServer(String host, int port, int backlog) 972 _HttpServer(String host, int port, int backlog)
892 : _serverSocket = new ServerSocket(host, port, backlog), 973 : _serverSocket = new ServerSocket(host, port, backlog),
893 _closeServer = true; 974 _closeServer = true;
894 975
895 _HttpServer.listenOn(ServerSocket this._serverSocket) 976 _HttpServer.listenOn(ServerSocket this._serverSocket)
896 : _closeServer = false; 977 : _closeServer = false;
897 978
898 StreamSubscription<T> listen(void onData(T event), 979 StreamSubscription<T> listen(void onData(T event),
899 {void onError(AsyncError error), 980 {void onError(AsyncError error),
900 void onDone(), 981 void onDone(),
901 bool unsubscribeOnError}) { 982 bool unsubscribeOnError}) {
902 _serverSubscription = _serverSocket.listen((Socket socket) { 983 _serverSubscription = _serverSocket.listen((Socket socket) {
903 // Accept the client connection. 984 // Accept the client connection.
904 _HttpConnection connection = new _HttpConnection(socket, _handleRequest); 985 _HttpConnection connection = new _HttpConnection(socket, this);
905 _connections.add(connection); 986 _connections.add(connection);
906 // TODO(ajohnsen): Listen to closed sockets. 987 // TODO(ajohnsen): Listen to closed sockets.
907 }); 988 });
908 return _controller.listen(onData, 989 return _controller.listen(onData,
909 onError: onError, 990 onError: onError,
910 onDone: onDone, 991 onDone: onDone,
911 unsubscribeOnError: unsubscribeOnError); 992 unsubscribeOnError: unsubscribeOnError);
912 } 993 }
913 994
914 void close() { 995 void close() {
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after
1162 1243
1163 1244
1164 class _RedirectInfo implements RedirectInfo { 1245 class _RedirectInfo implements RedirectInfo {
1165 const _RedirectInfo(int this.statusCode, 1246 const _RedirectInfo(int this.statusCode,
1166 String this.method, 1247 String this.method,
1167 Uri this.location); 1248 Uri this.location);
1168 final int statusCode; 1249 final int statusCode;
1169 final String method; 1250 final String method;
1170 final Uri location; 1251 final Uri location;
1171 } 1252 }
OLDNEW
« no previous file with comments | « sdk/lib/io/http_headers.dart ('k') | tests/standalone/io/http_session_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698