| David Reiss | f78ec2b | 2009-01-31 21:59:32 +0000 | [diff] [blame] | 1 | # | 
| David Reiss | ea2cba8 | 2009-03-30 21:35:00 +0000 | [diff] [blame] | 2 | # Licensed to the Apache Software Foundation (ASF) under one | 
|  | 3 | # or more contributor license agreements. See the NOTICE file | 
|  | 4 | # distributed with this work for additional information | 
|  | 5 | # regarding copyright ownership. The ASF licenses this file | 
|  | 6 | # to you under the Apache License, Version 2.0 (the | 
|  | 7 | # "License"); you may not use this file except in compliance | 
|  | 8 | # with the License. You may obtain a copy of the License at | 
|  | 9 | # | 
|  | 10 | #   http://www.apache.org/licenses/LICENSE-2.0 | 
|  | 11 | # | 
|  | 12 | # Unless required by applicable law or agreed to in writing, | 
|  | 13 | # software distributed under the License is distributed on an | 
|  | 14 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | 
|  | 15 | # KIND, either express or implied. See the License for the | 
|  | 16 | # specific language governing permissions and limitations | 
|  | 17 | # under the License. | 
|  | 18 | # | 
| David Reiss | f78ec2b | 2009-01-31 21:59:32 +0000 | [diff] [blame] | 19 |  | 
|  | 20 | import BaseHTTPServer | 
|  | 21 |  | 
|  | 22 | from thrift.server import TServer | 
|  | 23 | from thrift.transport import TTransport | 
|  | 24 |  | 
| David Reiss | a9ca25a | 2010-09-02 15:36:03 +0000 | [diff] [blame] | 25 | class ResponseException(Exception): | 
|  | 26 | """Allows handlers to override the HTTP response | 
|  | 27 |  | 
|  | 28 | Normally, THttpServer always sends a 200 response.  If a handler wants | 
|  | 29 | to override this behavior (e.g., to simulate a misconfigured or | 
|  | 30 | overloaded web server during testing), it can raise a ResponseException. | 
|  | 31 | The function passed to the constructor will be called with the | 
|  | 32 | RequestHandler as its only argument. | 
|  | 33 | """ | 
|  | 34 | def __init__(self, handler): | 
|  | 35 | self.handler = handler | 
|  | 36 |  | 
|  | 37 |  | 
| David Reiss | f78ec2b | 2009-01-31 21:59:32 +0000 | [diff] [blame] | 38 | class THttpServer(TServer.TServer): | 
|  | 39 | """A simple HTTP-based Thrift server | 
|  | 40 |  | 
|  | 41 | This class is not very performant, but it is useful (for example) for | 
|  | 42 | acting as a mock version of an Apache-based PHP Thrift endpoint.""" | 
|  | 43 |  | 
|  | 44 | def __init__(self, processor, server_address, | 
| Bryan Duxbury | d6a02ff | 2010-09-02 15:14:27 +0000 | [diff] [blame] | 45 | inputProtocolFactory, outputProtocolFactory = None, | 
|  | 46 | server_class = BaseHTTPServer.HTTPServer): | 
| David Reiss | f78ec2b | 2009-01-31 21:59:32 +0000 | [diff] [blame] | 47 | """Set up protocol factories and HTTP server. | 
|  | 48 |  | 
|  | 49 | See BaseHTTPServer for server_address. | 
|  | 50 | See TServer for protocol factories.""" | 
|  | 51 |  | 
|  | 52 | if outputProtocolFactory is None: | 
|  | 53 | outputProtocolFactory = inputProtocolFactory | 
|  | 54 |  | 
|  | 55 | TServer.TServer.__init__(self, processor, None, None, None, | 
|  | 56 | inputProtocolFactory, outputProtocolFactory) | 
|  | 57 |  | 
|  | 58 | thttpserver = self | 
|  | 59 |  | 
|  | 60 | class RequestHander(BaseHTTPServer.BaseHTTPRequestHandler): | 
|  | 61 | def do_POST(self): | 
|  | 62 | # Don't care about the request path. | 
| David Reiss | f78ec2b | 2009-01-31 21:59:32 +0000 | [diff] [blame] | 63 | itrans = TTransport.TFileObjectTransport(self.rfile) | 
|  | 64 | otrans = TTransport.TFileObjectTransport(self.wfile) | 
| Bryan Duxbury | d6a02ff | 2010-09-02 15:14:27 +0000 | [diff] [blame] | 65 | itrans = TTransport.TBufferedTransport(itrans, int(self.headers['Content-Length'])) | 
| David Reiss | a9ca25a | 2010-09-02 15:36:03 +0000 | [diff] [blame] | 66 | otrans = TTransport.TMemoryBuffer() | 
| David Reiss | f78ec2b | 2009-01-31 21:59:32 +0000 | [diff] [blame] | 67 | iprot = thttpserver.inputProtocolFactory.getProtocol(itrans) | 
|  | 68 | oprot = thttpserver.outputProtocolFactory.getProtocol(otrans) | 
| David Reiss | a9ca25a | 2010-09-02 15:36:03 +0000 | [diff] [blame] | 69 | try: | 
|  | 70 | thttpserver.processor.process(iprot, oprot) | 
|  | 71 | except ResponseException, exn: | 
|  | 72 | exn.handler(self) | 
|  | 73 | else: | 
|  | 74 | self.send_response(200) | 
|  | 75 | self.send_header("content-type", "application/x-thrift") | 
|  | 76 | self.end_headers() | 
|  | 77 | self.wfile.write(otrans.getvalue()) | 
| David Reiss | f78ec2b | 2009-01-31 21:59:32 +0000 | [diff] [blame] | 78 |  | 
| Bryan Duxbury | d6a02ff | 2010-09-02 15:14:27 +0000 | [diff] [blame] | 79 | self.httpd = server_class(server_address, RequestHander) | 
| David Reiss | f78ec2b | 2009-01-31 21:59:32 +0000 | [diff] [blame] | 80 |  | 
|  | 81 | def serve(self): | 
|  | 82 | self.httpd.serve_forever() |