OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2014, the Dart 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 library remote_api_impl; |
| 6 |
| 7 import 'dart:async'; |
| 8 import 'dart:io'; |
| 9 import 'dart:convert' show UTF8, JSON; |
| 10 |
| 11 import '../../api/errors.dart' as errors; |
| 12 import '../../api/remote_api.dart' as remote_api; |
| 13 import '../appengine_context.dart'; |
| 14 |
| 15 import '../protobuf_api/rpc/rpc_service.dart'; |
| 16 import '../protobuf_api/internal/remote_api.pb.dart' |
| 17 as pb; |
| 18 |
| 19 class RemoteApiImpl extends remote_api.RemoteApi { |
| 20 static final TEXT_CONTENT_TYPE = |
| 21 new ContentType('text', 'plain', charset: 'utf-8'); |
| 22 static final JSON_CONTENT_TYPE = |
| 23 new ContentType('application', 'json', charset: 'utf-8'); |
| 24 static final BINARY_CONTENT_TYPE = |
| 25 new ContentType('application', 'octet-stream'); |
| 26 |
| 27 final RPCService _rpcService; |
| 28 final String _ticket; |
| 29 final AppengineContext _context; |
| 30 |
| 31 RemoteApiImpl(this._rpcService, this._context, this._ticket); |
| 32 |
| 33 Future handleRemoteApiRequest(HttpRequest httpRequest) { |
| 34 if (httpRequest.method == 'GET') { |
| 35 var rtok = httpRequest.uri.queryParameters['rtok']; |
| 36 if (rtok == null) rtok = '0'; |
| 37 var json = { |
| 38 'app_id' : _context.fullQualifiedApplicationId, |
| 39 'rtok' : rtok, |
| 40 }; |
| 41 return httpRequest.drain().then((_) { |
| 42 var data = UTF8.encode(JSON.encode(json)); |
| 43 return _sendData( |
| 44 httpRequest.response, HttpStatus.OK, JSON_CONTENT_TYPE, data); |
| 45 }); |
| 46 } else if (httpRequest.method == 'POST') { |
| 47 return httpRequest |
| 48 .fold(new BytesBuilder(), (buffer, data) => buffer..add(data)) |
| 49 .then((BytesBuilder result) { |
| 50 var request = new pb.Request.fromBuffer(result.takeBytes()); |
| 51 var response = new pb.Response(); |
| 52 return _rpcService.call(request.serviceName, request.method, |
| 53 request.request, ticket: _ticket) |
| 54 .then((result) { |
| 55 response.response = result; |
| 56 |
| 57 var data = response.writeToBuffer(); |
| 58 return _sendData( |
| 59 httpRequest.response, HttpStatus.OK, BINARY_CONTENT_TYPE, data); |
| 60 }).catchError((error) { |
| 61 response.applicationError = new pb.ApplicationError(); |
| 62 response.applicationError.code = error.code; |
| 63 response.applicationError.detail = error.message; |
| 64 |
| 65 var data = response.writeToBuffer(); |
| 66 return _sendData( |
| 67 httpRequest.response, HttpStatus.OK, BINARY_CONTENT_TYPE, data); |
| 68 }, test: (error) => error is RpcApplicationError) |
| 69 .then((_) => null); |
| 70 }); |
| 71 } else { |
| 72 return new Future.sync(() { |
| 73 throw new errors.ApplicationError( |
| 74 'RemoteApi will only handle GET and POST requests.'); |
| 75 }); |
| 76 } |
| 77 } |
| 78 |
| 79 Future _sendData(response, statusCode, contentType, data) { |
| 80 response.statusCode = statusCode; |
| 81 response.headers.contentType = contentType; |
| 82 response.headers.contentLength = data.length; |
| 83 response.add(data); |
| 84 return response.close(); |
| 85 } |
| 86 } |
OLD | NEW |