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

Side by Side Diff: dart/sdk/lib/_internal/compiler/samples/leap_server/leap_server.dart

Issue 197923002: Mock up code completion. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge
Patch Set: Merged with r34309. Created 6 years, 9 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 | « no previous file | dart/site/try/build_try.gyp » ('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 library leap_server; 5 library leap_server;
6 6
7 import 'dart:io'; 7 import 'dart:io';
8 8
9 import 'dart:convert' show JSON, HtmlEscape;
10
11 /// Represents a "project" command. These commands are accessed from the URL
12 /// "/project?name".
13 class ProjectCommand {
14 final String name;
15
16 /// For each query parameter, this map describes rules for validating them.
17 final Map<String, String> rules;
18
19 final Function handle;
20
21 const ProjectCommand(this.name, this.rules, this.handle);
22 }
23
9 class Conversation { 24 class Conversation {
10 HttpRequest request; 25 HttpRequest request;
11 HttpResponse response; 26 HttpResponse response;
12 27
28 static const String PROJECT_PATH = '/project';
29
30 static const String PACKAGES_PATH = '/packages';
31
13 static const String CONTENT_TYPE = HttpHeaders.CONTENT_TYPE; 32 static const String CONTENT_TYPE = HttpHeaders.CONTENT_TYPE;
14 33
15 static const String LEAP_LANDING_PAGE = 34 static Uri documentRoot = Uri.base;
16 'sdk/lib/_internal/compiler/samples/leap/index.html';
17 35
18 static String landingPage = LEAP_LANDING_PAGE; 36 static Uri projectRoot = Uri.base.resolve('site/try/src/');
37
38 static Uri packageRoot = Uri.base.resolve('sdk/lib/_internal/');
39
40 static const List<ProjectCommand> COMMANDS = const <ProjectCommand>[
41 const ProjectCommand('list', const {'list': null}, handleProjectList),
42 ];
19 43
20 Conversation(this.request, this.response); 44 Conversation(this.request, this.response);
21 45
22 onClosed(_) { 46 onClosed(_) {
23 if (response.statusCode == HttpStatus.OK) return; 47 if (response.statusCode == HttpStatus.OK) return;
24 print('Request for ${request.uri} ${response.statusCode}'); 48 print('Request for ${request.uri} ${response.statusCode}');
25 } 49 }
26 50
27 notFound(path) { 51 notFound(path) {
28 response.statusCode = HttpStatus.NOT_FOUND; 52 response.statusCode = HttpStatus.NOT_FOUND;
29 response.write(htmlInfo('Not Found', 53 response.write(htmlInfo('Not Found',
30 'The file "$path" could not be found.')); 54 'The file "$path" could not be found.'));
31 response.close(); 55 response.close();
32 } 56 }
33 57
34 redirect(String location) { 58 redirect(String location) {
35 response.statusCode = HttpStatus.FOUND; 59 response.statusCode = HttpStatus.FOUND;
36 response.headers.add(HttpHeaders.LOCATION, location); 60 response.headers.add(HttpHeaders.LOCATION, location);
37 response.close(); 61 response.close();
38 } 62 }
39 63
64 badRequest(String problem) {
65 response.statusCode = HttpStatus.BAD_REQUEST;
66 response.write(htmlInfo("Bad request",
67 "Bad request '${request.uri}': $problem"));
68 response.close();
69 }
70
71 bool validate(Map<String, String> parameters, Map<String, String> rules) {
72 Iterable<String> problems = rules.keys
73 .where((name) => !parameters.containsKey(name))
74 .map((name) => "Missing parameter: '$name'.");
75 if (!problems.isEmpty) {
76 badRequest(problems.first);
77 return false;
78 }
79 Set extra = new Set.from(parameters.keys)..removeAll(rules.keys);
80 if (extra.isEmpty) return true;
81 String extraString = (extra.toList()..sort()).join("', '");
82 badRequest("Extra parameters: '$extraString'.");
83 return false;
84 }
85
86 static handleProjectList(Conversation self) {
87 String nativeDir = projectRoot.toFilePath();
88 Directory dir = new Directory(nativeDir);
89 var future = dir.list(recursive: true, followLinks: false).toList();
90 future.then((List<FileSystemEntity> entries) {
91 List<String> files = entries
92 .map((e) => e.path)
93 .where((p) => !p.endsWith('~') && p.startsWith(nativeDir))
94 .map((p) => p.substring(nativeDir.length))
95 .map((p) => new Uri.file(p).path).toList();
96 self.response
97 ..write(JSON.encode(files))
98 ..close();
99 });
100 }
101
102 handleProjectRequest() {
103 Map<String, String> parameters = request.uri.queryParameters;
104 for (ProjectCommand command in COMMANDS) {
105 if (parameters.containsKey(command.name)) {
106 if (validate(parameters, command.rules)) {
107 (command.handle)(this);
108 }
109 return;
110 }
111 }
112 String commands = COMMANDS.map((c) => c.name).join("', '");
113 badRequest("Valid commands are: '$commands'");
114 }
115
40 handle() { 116 handle() {
41 response.done 117 response.done
42 .then(onClosed) 118 .then(onClosed)
43 .catchError(onError); 119 .catchError(onError);
44 120
45 String path = request.uri.path; 121 Uri uri = request.uri;
46 if (path == '/') return redirect('/$landingPage'); 122 if (uri.path == PROJECT_PATH) {
47 if (path == '/favicon.ico') { 123 return handleProjectRequest();
48 path = '/sdk/lib/_internal/dartdoc/static/favicon.ico';
49 } 124 }
50 if (path.contains('..') || path.contains('%')) return notFound(path); 125 if (uri.path.endsWith('/')) {
51 var f = new File("./$path"); 126 uri = uri.resolve('index.html');
127 }
128 if (uri.path == '/css/fonts/fontawesome-webfont.woff') {
129 uri = uri.resolve('/fontawesome-webfont.woff');
130 }
131 if (uri.path.contains('..') || uri.path.contains('%')) {
132 return notFound(uri.path);
133 }
134 String path = uri.path;
135 Uri root = documentRoot;
136 String dartType = 'application/dart';
137 if (path.startsWith('/project/packages/')) {
138 root = packageRoot;
139 path = path.substring('/project/packages'.length);
140 } else if (path.startsWith('${PROJECT_PATH}/')) {
141 root = projectRoot;
142 path = path.substring(PROJECT_PATH.length);
143 dartType = 'text/plain';
144 } else if (path.startsWith('${PACKAGES_PATH}/')) {
145 root = packageRoot;
146 path = path.substring(PACKAGES_PATH.length);
147 }
148 var f = new File(root.resolve('.$path').toFilePath());
52 f.exists().then((bool exists) { 149 f.exists().then((bool exists) {
53 if (!exists) return notFound(path); 150 if (!exists) return notFound(path);
54 if (path.endsWith('.html')) { 151 if (path.endsWith('.html')) {
55 response.headers.set(CONTENT_TYPE, 'text/html'); 152 response.headers.set(CONTENT_TYPE, 'text/html');
56 } else if (path.endsWith('.dart')) { 153 } else if (path.endsWith('.dart')) {
57 response.headers.set(CONTENT_TYPE, 'application/dart'); 154 response.headers.set(CONTENT_TYPE, dartType);
58 } else if (path.endsWith('.js')) { 155 } else if (path.endsWith('.js')) {
59 response.headers.set(CONTENT_TYPE, 'application/javascript'); 156 response.headers.set(CONTENT_TYPE, 'application/javascript');
60 } else if (path.endsWith('.ico')) { 157 } else if (path.endsWith('.ico')) {
61 response.headers.set(CONTENT_TYPE, 'image/x-icon'); 158 response.headers.set(CONTENT_TYPE, 'image/x-icon');
62 } else if (path.endsWith('.appcache')) { 159 } else if (path.endsWith('.appcache')) {
63 response.headers.set(CONTENT_TYPE, 'text/cache-manifest'); 160 response.headers.set(CONTENT_TYPE, 'text/cache-manifest');
64 } 161 }
65 f.openRead().pipe(response).catchError(onError); 162 f.openRead().pipe(response).catchError(onError);
66 }); 163 });
67 } 164 }
68 165
69 static onRequest(HttpRequest request) { 166 static onRequest(HttpRequest request) {
70 new Conversation(request, request.response).handle(); 167 new Conversation(request, request.response).handle();
71 } 168 }
72 169
73 static onError(error) { 170 static onError(error) {
74 if (error is HttpException) { 171 if (error is HttpException) {
75 print('Error: ${error.message}'); 172 print('Error: ${error.message}');
76 } else { 173 } else {
77 print('Error: ${error}'); 174 print('Error: ${error}');
78 } 175 }
79 } 176 }
80 177
81 String htmlInfo(String title, String text) { 178 String htmlInfo(String title, String text) {
179 // No script injection, please.
180 title = const HtmlEscape().convert(title);
181 text = const HtmlEscape().convert(text);
82 return """ 182 return """
83 <!DOCTYPE html> 183 <!DOCTYPE html>
84 <html lang='en'> 184 <html lang='en'>
85 <head> 185 <head>
86 <title>$title</title> 186 <title>$title</title>
87 </head> 187 </head>
88 <body> 188 <body>
89 <h1>$title</h1> 189 <h1>$title</h1>
90 <p>$text</p> 190 <p>$text</p>
91 </body> 191 </body>
92 </html> 192 </html>
93 """; 193 """;
94 } 194 }
95 } 195 }
96 196
97 main(List<String> arguments) { 197 main(List<String> arguments) {
98 if (arguments.length > 0) { 198 if (arguments.length > 0) {
99 Conversation.landingPage = arguments[0]; 199 Conversation.documentRoot = Uri.base.resolve(arguments[0]);
100 } 200 }
101 var host = '127.0.0.1'; 201 var host = '127.0.0.1';
102 if (arguments.length > 1) { 202 if (arguments.length > 1) {
103 host = arguments[1]; 203 host = arguments[1];
104 } 204 }
105 int port = 0; 205 int port = 0;
106 if (arguments.length > 2) { 206 if (arguments.length > 2) {
107 port = int.parse(arguments[2]); 207 port = int.parse(arguments[2]);
108 } 208 }
209 if (arguments.length > 3) {
210 Conversation.projectRoot = Uri.base.resolve(arguments[3]);
211 }
212 if (arguments.length > 4) {
213 Conversation.packageRoot = Uri.base.resolve(arguments[4]);
214 }
109 HttpServer.bind(host, port).then((HttpServer server) { 215 HttpServer.bind(host, port).then((HttpServer server) {
110 print('HTTP server started on http://$host:${server.port}/'); 216 print('HTTP server started on http://$host:${server.port}/');
111 server.listen(Conversation.onRequest, onError: Conversation.onError); 217 server.listen(Conversation.onRequest, onError: Conversation.onError);
112 }).catchError((e) { 218 }).catchError((e) {
113 print("HttpServer.bind error: $e"); 219 print("HttpServer.bind error: $e");
114 exit(1); 220 exit(1);
115 }); 221 });
116 } 222 }
OLDNEW
« no previous file with comments | « no previous file | dart/site/try/build_try.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698