{ "info": { "author": "Matt Bachmann", "author_email": "bachmann.matt@gmail.com", "bugtrack_url": null, "classifiers": [ "Intended Audience :: Developers", "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: Implementation :: CPython" ], "description": "# Thrift Explorer\n[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/ambv/black)\n[![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](https://github.com/Bachmann1234/thrift-explorer/blob/master/LICENSE)\n[![Build Status](https://travis-ci.org/Bachmann1234/Thrift-Explorer.svg?branch=master)](https://travis-ci.org/Bachmann1234/Thrift-Explorer)\n[![Coverage Status](https://coveralls.io/repos/github/Bachmann1234/Thrift-Explorer/badge.svg?branch=master)](https://coveralls.io/github/Bachmann1234/Thrift-Explorer?branch=master)\n[![PyPI version](https://badge.fury.io/py/thrift-explorer.svg)](https://badge.fury.io/py/thrift-explorer)\n\n[Apache Thrift](https://thrift.apache.org/) is a language agnostic framework that enables typed communication between services. \n\nThrift explorer is intended to be a tool aimed at developers who use thrift services. Enabling the user to explore their services without having to write or maintain any code. \n\n# This project is alpha\n\nI am still finding fundemental issues with the implementation and am working though them. Slowly but surely\n\n## How does this work\n\nYou place your service thrifts in a directory and configure Thrift Explorer to pull from it. Then make http calls to Thrift Explorer providing information such as host/port and \nit will forward your request to it and return the response.\n\n## Example Usage\n\nExample calls are provided as part of a [Postman Collection](ThriftExplorer.postman_collection.json). However, Lets walk though a basic session.\n\nIf you are working on a todo thrift service that you have running on your machine you can use thrift explorer to make calls to it. With the todo server running you \nadd the todo thrifts to thrift explorer and start the server. (I will be using [curl](https://curl.haxx.se/) to make requests and [jq](https://stedolan.github.io/jq/) to pretty print the responses)\n\nYou can see what services are loaded\n\n```json\ncurl -Ss localhost:5000 | jq '.' \n{\n \"thrifts\": [\n {\n \"thrift\": \"Batman.thrift\",\n \"service\": \"BatPuter\",\n \"methods\": [\n \"ping\",\n \"getVillain\",\n \"addVillain\",\n \"saveCase\"\n ]\n },\n {\n \"thrift\": \"todo.thrift\",\n \"service\": \"TodoService\",\n \"methods\": [\n \"ping\",\n \"listTasks\",\n \"numTasks\",\n \"getTask\",\n \"createTask\",\n \"completeTask\",\n \"fancyNewMethod\"\n ]\n }\n ]\n}\n```\n\nList the methods of a particular service\n\n```json\ncurl -Ss localhost:5000/todo/TodoService/ | jq '.' \n{\n \"thrift\": \"todo.thrift\",\n \"service\": \"TodoService\",\n \"methods\": [\n \"ping\",\n \"listTasks\",\n \"numTasks\",\n \"getTask\",\n \"createTask\",\n \"completeTask\",\n \"fancyNewMethod\"\n ]\n}\n```\n\nMake a call to one of the methods of that service (the response is in the \"data\" field of the response body)\n\n```json\ncurl -Ss -X POST \\ \n http://localhost:5000/todo/TodoService/createTask/ \\\n -H 'Content-Type: application/json' \\\n -d '{\n \"host\": \"localhost\",\n \"port\": 6000,\n \"protocol\": \"tbinaryprotocol\",\n \"transport\": \"tbufferedtransport\",\n \"request_body\": {\"description\": \"task 1\", \"dueDate\": \"12-12-2012\"}\n }' | jq \".\"\n{\n \"status\": \"Success\",\n \"request\": {\n \"thrift_file\": \"todo.thrift\",\n \"service_name\": \"TodoService\",\n \"endpoint_name\": \"createTask\",\n \"host\": \"localhost\",\n \"port\": 6000,\n \"protocol\": \"tbinaryprotocol\",\n \"transport\": \"tbufferedtransport\",\n \"request_body\": {\n \"description\": \"task 1\",\n \"dueDate\": \"12-12-2012\"\n }\n },\n \"data\": {\n \"__thrift_struct_class__\": \"Task\",\n \"taskId\": \"1\",\n \"description\": \"task 1\",\n \"dueDate\": \"12-12-2012\"\n },\n \"time_to_make_request\": \"0:00:00.008794\",\n \"time_to_connect\": \"0:00:00.001502\"\n}\n```\n\nand just for fun we will make another call\n\n```json\ncurl -Ss -X POST \\ \n http://localhost:5000/todo/TodoService/getTask/ \\\n -H 'Content-Type: application/json' \\\n -d '{\n \"host\": \"localhost\",\n \"port\": 6000,\n \"protocol\": \"tbinaryprotocol\",\n \"transport\": \"tbufferedtransport\",\n \"request_body\": {\"taskId\": \"1\"}\n }' | jq \".\"\n{\n \"status\": \"Success\",\n \"request\": {\n \"thrift_file\": \"todo.thrift\",\n \"service_name\": \"TodoService\",\n \"endpoint_name\": \"getTask\",\n \"host\": \"localhost\",\n \"port\": 6000,\n \"protocol\": \"tbinaryprotocol\",\n \"transport\": \"tbufferedtransport\",\n \"request_body\": {\n \"taskId\": \"1\"\n }\n },\n \"data\": {\n \"__thrift_struct_class__\": \"Task\",\n \"taskId\": \"1\",\n \"description\": \"task 1\",\n \"dueDate\": \"12-12-2012\"\n },\n \"time_to_make_request\": \"0:00:00.001283\",\n \"time_to_connect\": \"0:00:00.000554\"\n}\n```\n\nIf you make a mistake making a request thrift explorer tries to be helpful telling you the mistake you made\n\n```json\ncurl -sS -X POST \\ \n http://localhost:5000/todo/TodoService/completeTask/ \\\n -d '{\n \"host\": \"localhost\",\n \"port\": 6000,\n \"protocol\": \"tbinaryprotocol\",\n \"transport\": \"tbufferedtransport\",\n \"request_body\": {\"description\": \"task 1\"}\n }' | jq '.'\n{\n \"errors\": [\n {\n \"code\": \"ErrorCode.REQUIRED_FIELD_MISSING\",\n \"message\": \"Required Field 'taskId' not found\",\n \"arg_spec\": {\n \"name\": \"taskId\",\n \"required\": true,\n \"type_info\": {\"ttype\": \"string\"},\n },\n }\n ]\n}\n```\n\n\nand if you just want to get the thrift itself you can do that to\n\n```java\ncurl -Ss localhost:5000/todo/\ninclude \"basethrifts/Exceptions.thrift\"\n\nstruct Task {\n 1: optional string taskId;\n 2: optional string description;\n 3: optional string dueDate;\n}\n\nservice TodoService {\n void ping();\n list listTasks();\n i64 numTasks();\n Task getTask(1: string taskId) throws (1: Exceptions.NotFound notfound);\n Task createTask(1: string description, 2: string dueDate);\n void completeTask(1: required string taskId) throws (1: Exceptions.NotFound notfound);\n void fancyNewMethod(); // Not implemented by the server to simulate that kind of error\n}\n```\n\n## Installation and Running the server\n\n### Installation with pip\n\nIf you are comfortable with python environments and python packaging you can install this with pip. I suggest using a virtual environment.\n\n```\npip install thrift-explorer\n```\n\nThen you may either use the flask development server or you can install a wsgi server. I am going to use gunicorn\n\n```\npip install gunicorn\n```\n\nThen you set the environment variables you will use to configure the server. See [Configuring the server](#configuring-the-server) for details. At a minimum you must set THRIFT_DIRECTORY\n\n```\nexport THRIFT_DIRECTORY=$(pwd)/example-thrifts/\n```\n\nThen start it!\n\n```\ngunicorn -b 127.0.0.1:5000 thrift_explorer.wsgi\n[2018-10-07 12:01:30 -0400] [7864] [INFO] Starting gunicorn 19.9.0\n[2018-10-07 12:01:30 -0400] [7864] [INFO] Listening at: http://127.0.0.1:5000 (7864)\n[2018-10-07 12:01:30 -0400] [7864] [INFO] Using worker: sync\n[2018-10-07 12:01:30 -0400] [7867] [INFO] Booting worker with pid: 7867\n```\n\n### Installation with docker\n\nIf you would rather not work with the python directly you can pull down a docker container\n\n```\ndocker pull bachmann1234/thrift-explorer\n```\n\nWhen running the docker container you are going to need to pass in a directory containing the thrifts the server will load in.\nThis will be provided via the source parameter. In the example below I pass in the example-thrifts directory in this very repo \n\n```\ndocker run --mount type=bind,source=$(pwd)/example-thrifts,target=/thrifts -p 5000:80 bachmann1234/thrift-explorer\n```\n\nIn english this command is saying \"run the thrift-explorer server with example-thrifts as its thrift directory. Make it so that server is accessible to me at port 8000\". You can also\npass in other environment variables in this command to configure the server. See [Configuring the server](#configuring-the-server) for details.\n\nFor a more detailed explanation of the docker command [consult the docker documentation](https://docs.docker.com/engine/reference/run/)\n\nOne gotcha: When using the docker container you need to be mindful of how networking works with docker. For example. If you are running thrift-explorer with the docker container\nand you need it to access a service running on your localhost you would use the hostname \"host.docker.internal\" (at least on docker-for-mac). For example\n\n```json\ncurl -Ss -X POST \\ \n http://localhost:4000/todo/TodoService/createTask/ \\\n -H 'Content-Type: application/json' \\\n -d '{\n \"host\": \"host.docker.internal\",\n \"port\": 6000,\n \"protocol\": \"tbinaryprotocol\",\n \"transport\": \"tbufferedtransport\",\n \"request_body\": {\"description\": \"task 1\", \"dueDate\": \"12-12-2012\"}\n }' | jq \".\"\n{\n \"status\": \"Success\",\n \"request\": {\n \"thrift_file\": \"todo.thrift\",\n \"service_name\": \"TodoService\",\n \"endpoint_name\": \"createTask\",\n \"host\": \"host.docker.internal\",\n \"port\": 6000,\n \"protocol\": \"tbinaryprotocol\",\n \"transport\": \"tbufferedtransport\",\n \"request_body\": {\n \"description\": \"task 1\",\n \"dueDate\": \"12-12-2012\"\n }\n },\n \"data\": {\n \"__thrift_struct_class__\": \"Task\",\n \"taskId\": \"2\",\n \"description\": \"task 1\",\n \"dueDate\": \"12-12-2012\"\n },\n \"time_to_make_request\": \"0:00:00.012562\",\n \"time_to_connect\": \"0:00:00.001214\"\n}\n```\n\n### Configuring the server \n\nThe service is configured via environment variables\n\n| Variable | Description | Default | Required |\n|--------------------------|-------------------------------------------------------------------------------|--------------------|----------|\n| THRIFT_DIRECTORY | The directory where the thrifts you want the server to be aware of are stored | | Yes |\n| DEFAULT_THRIFT_PROTOCOL | What thrift protocol should the server assume if one is not provided | TBinaryProtocol | No |\n| DEFAULT_THRIFT_TRANSPORT | What thrift transport should the server assume if one is not provided | TBufferedTransport | No |\n\n\n\n\n## Running the example thrift server\n\nThis repo contains some example thrifts and one example thrift service. See [Todo Thrift](/example-thrifts/todo.thrift) for a service definition.\n\nTo run it just set your pythonpath appropriately (see [My environment](/environment.fish) for how I setup my environment (I use fish shell)). Then run\n\n```\npython tests/todoserver/service.py\n```\n\nThis service is intended as a development/testing aid. It is not required for using thrift explorer", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/Bachmann1234/thriftExplorer", "keywords": "", "license": "GPLv3", "maintainer": "", "maintainer_email": "", "name": "thrift-explorer", "package_url": "https://pypi.org/project/thrift-explorer/", "platform": "", "project_url": "https://pypi.org/project/thrift-explorer/", "project_urls": { "Homepage": "https://github.com/Bachmann1234/thriftExplorer" }, "release_url": "https://pypi.org/project/thrift-explorer/0.8/", "requires_dist": null, "requires_python": ">=3.7.0", "summary": "Potentially useful utility for working with thrift files", "version": "0.8" }, "last_serial": 4433994, "releases": { "0.6": [ { "comment_text": "", "digests": { "md5": "9c002904490a45fc297971a0ecd30aa3", "sha256": "53166724234d7d0590a4e83c6560b9e105279135ec2dc1c4b5dacb5f8a8ef45b" }, "downloads": -1, "filename": "thrift-explorer-0.6.tar.gz", "has_sig": false, "md5_digest": "9c002904490a45fc297971a0ecd30aa3", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.7.0", "size": 28596, "upload_time": "2018-10-07T16:13:05", "url": "https://files.pythonhosted.org/packages/f6/13/0c845edeecd607354661c152857289b2e2ee0451d3245d6d594590833116/thrift-explorer-0.6.tar.gz" } ], "0.7": [ { "comment_text": "", "digests": { "md5": "fafc28af2ef8755ab1236dc3c253fb26", "sha256": "017bb253f0783324375c39de1198d0f5c667ee05942212e69431cda2387ce7a9" }, "downloads": -1, "filename": "thrift-explorer-0.7.tar.gz", "has_sig": false, "md5_digest": "fafc28af2ef8755ab1236dc3c253fb26", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.7.0", "size": 30055, "upload_time": "2018-10-11T03:34:44", "url": "https://files.pythonhosted.org/packages/24/a4/849bb41bc7066973284b1fae1a25a4e925a298f6c22554ed9dde9cd6d50f/thrift-explorer-0.7.tar.gz" } ], "0.8": [ { "comment_text": "", "digests": { "md5": "ea75731b2d54f7bdf94d56b8fe5126c4", "sha256": "14f2e816f3d7b518a4096feaa03f73c3420bb9565d43b003f7d162e48cfff4f0" }, "downloads": -1, "filename": "thrift-explorer-0.8.tar.gz", "has_sig": false, "md5_digest": "ea75731b2d54f7bdf94d56b8fe5126c4", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.7.0", "size": 30072, "upload_time": "2018-10-31T01:55:10", "url": "https://files.pythonhosted.org/packages/1b/a9/d30b1bfd0a8c6aefac9781076f91ebdc73afd10f5f3cec42e5f409a398d3/thrift-explorer-0.8.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "ea75731b2d54f7bdf94d56b8fe5126c4", "sha256": "14f2e816f3d7b518a4096feaa03f73c3420bb9565d43b003f7d162e48cfff4f0" }, "downloads": -1, "filename": "thrift-explorer-0.8.tar.gz", "has_sig": false, "md5_digest": "ea75731b2d54f7bdf94d56b8fe5126c4", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.7.0", "size": 30072, "upload_time": "2018-10-31T01:55:10", "url": "https://files.pythonhosted.org/packages/1b/a9/d30b1bfd0a8c6aefac9781076f91ebdc73afd10f5f3cec42e5f409a398d3/thrift-explorer-0.8.tar.gz" } ] }