| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2015, the Dartino 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 import 'dart:dartino'; | |
| 6 import 'dart:typed_data'; | |
| 7 | |
| 8 import 'package:file/file.dart'; | |
| 9 import 'package:http/http.dart'; | |
| 10 import 'package:socket/socket.dart'; | |
| 11 | |
| 12 abstract class _Connection { | |
| 13 final String host; | |
| 14 final int port; | |
| 15 final bool open; | |
| 16 void close(); | |
| 17 Socket accept(); | |
| 18 } | |
| 19 | |
| 20 class _ConnectionImpl implements _Connection { | |
| 21 final String host; | |
| 22 ServerSocket _socket; | |
| 23 get port => _socket.port; | |
| 24 _ConnectionImpl(this.host, port) { | |
| 25 _socket = new ServerSocket(host, port); | |
| 26 } | |
| 27 bool get open => _socket != null; | |
| 28 void close() { | |
| 29 if (!open) return; | |
| 30 _socket.close(); | |
| 31 _socket = null; | |
| 32 } | |
| 33 Socket accept() => _socket.accept(); | |
| 34 } | |
| 35 | |
| 36 class _ConnectionInvertedImpl implements _Connection { | |
| 37 final String host = '127.0.0.1'; | |
| 38 final int port; | |
| 39 bool open = true; | |
| 40 _ConnectionInvertedImpl(this.port) { | |
| 41 // Signal availability to the "client". | |
| 42 accept().close(); | |
| 43 } | |
| 44 void close() { | |
| 45 open = false; | |
| 46 } | |
| 47 Socket accept() { | |
| 48 return new Socket.connect(host, port); | |
| 49 } | |
| 50 } | |
| 51 | |
| 52 abstract class DataStorage { | |
| 53 ByteBuffer readResponseFile(String resource); | |
| 54 | |
| 55 String encode(String resource) { | |
| 56 List<String> parts = resource.split('/'); | |
| 57 parts.add(Uri.encodeComponent(parts.removeLast())); | |
| 58 return parts.join('/'); | |
| 59 } | |
| 60 } | |
| 61 | |
| 62 class FileDataStorage extends DataStorage { | |
| 63 String _dataDir = 'samples/github/lib/src/github_mock_data'; | |
| 64 | |
| 65 ByteBuffer readResponseFile(String resource) { | |
| 66 String path = '$_dataDir/${encode(resource)}.data'; | |
| 67 if (File.existsAsFile(path)) { | |
| 68 File file = new File.open(path); | |
| 69 return file.read(file.length); | |
| 70 } | |
| 71 return null; | |
| 72 } | |
| 73 } | |
| 74 | |
| 75 class GithubMock { | |
| 76 final int delay; | |
| 77 bool verbose = false; | |
| 78 DataStorage dataStorage = new FileDataStorage(); | |
| 79 _Connection _connection; | |
| 80 static const String _requestSuffix = ' HTTP/1.1'; | |
| 81 | |
| 82 String get host => _connection.host; | |
| 83 int get port => _connection.port; | |
| 84 | |
| 85 GithubMock([host = '127.0.0.1', int port = 0, int this.delay = 0]) { | |
| 86 _connection = new _ConnectionImpl(host, port); | |
| 87 } | |
| 88 | |
| 89 GithubMock.invertedForTesting(int port, [int this.delay = 0]) { | |
| 90 _connection = new _ConnectionInvertedImpl(port); | |
| 91 } | |
| 92 | |
| 93 void close() { | |
| 94 _connection.close(); | |
| 95 } | |
| 96 | |
| 97 void spawn() { | |
| 98 Fiber.fork(run); | |
| 99 } | |
| 100 | |
| 101 void run() { | |
| 102 if (verbose) print('Running server on $host:$port'); | |
| 103 while (_connection.open) { | |
| 104 try { | |
| 105 _accept(_connection.accept()); | |
| 106 } on SocketException catch (_) { | |
| 107 // outstanding accept throws when the server closes. | |
| 108 } | |
| 109 } | |
| 110 if (verbose) print('Terminated server'); | |
| 111 } | |
| 112 | |
| 113 void _accept(Socket socket) { | |
| 114 if (delay > 0) sleep(delay); | |
| 115 var data = new Uint8List.view(socket.readNext()); | |
| 116 var request = new String.fromCharCodes(data); | |
| 117 | |
| 118 // TODO(zerny): Use String.indexOf for start/end once implemented. | |
| 119 int start = -1; | |
| 120 for (int i = 0; i < request.length; ++i) { | |
| 121 if (request[i] == '/') { | |
| 122 start = i + 1; | |
| 123 break; | |
| 124 } | |
| 125 } | |
| 126 if (start < 0) { | |
| 127 print('GithubMock: Ill-formed request.'); | |
| 128 socket.close(); | |
| 129 return; | |
| 130 } | |
| 131 | |
| 132 int end = -1; | |
| 133 for (int i = start; i < request.length; ++i) { | |
| 134 if (_requestSuffix == request.substring(i, i + _requestSuffix.length)) { | |
| 135 end = i; | |
| 136 break; | |
| 137 } | |
| 138 } | |
| 139 if (end < 0) { | |
| 140 print('GithubMock: Ill-formed request.'); | |
| 141 socket.close(); | |
| 142 return; | |
| 143 } | |
| 144 | |
| 145 String resource = request.substring(start, end); | |
| 146 int code = 200; | |
| 147 var response = dataStorage.readResponseFile(resource); | |
| 148 | |
| 149 if (response == null) { | |
| 150 code = 404; | |
| 151 response = dataStorage.readResponseFile('404'); | |
| 152 } | |
| 153 | |
| 154 if (verbose) { | |
| 155 print('Response $code on request for $resource'); | |
| 156 } | |
| 157 | |
| 158 socket.write(response); | |
| 159 socket.close(); | |
| 160 } | |
| 161 } | |
| OLD | NEW |