{ "info": { "author": "Kevin L. Mitchell", "author_email": "kevin.mitchell@rackspace.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Environment :: Web Environment", "Framework :: Paste", "Intended Audience :: System Administrators", "License :: OSI Approved :: Apache Software License", "Operating System :: OS Independent", "Programming Language :: Python" ], "description": "===========================================\nAVersion WSGI Version Selection Application\n===========================================\n\nAVersion is a version selection application for WSGI stacks built with\nPasteDeploy. It allows multiple versions of a given application to be\naddressed via URI or content type parameter.\n\nHow AVersion Works\n==================\n\nAVersion is a composite application, similar to the Paste ``urlmap``.\nIt is configured with several different applications--each of which\nrepresents a different version of the desired end application. It can\nalso be configured with a special application which handles\nunversioned API requests, e.g., by returning a list of the available\nversions. AVersion then selects the appropriate application to pass a\ngiven request to, based on the URI prefix, or a version parameter on\nthe content type or types specified in the \"Content-Type\" or \"Accept\"\nheaders. In addition, AVersion can determine the best content type\nfor the reply, based on the URI suffix (e.g., \".json\" could map to\ncontent type \"application/json\") or the \"Accept\" header.\n\nConfiguring AVersion\n====================\n\nThe first step in configuring AVersion is to set up the section of the\nPaste INI configuration file::\n\n [composite:main]\n use = egg:aversion#aversion\n\nThe next step is to specify the recognized versions and their\nassociated applications. The default application--the one called if\nno version can be determined--is specified by the ``version`` key.\nThe specific versions are then specified by prefixing a version\nspecification with ``version.``; e.g., if you call the second version\nof your application \"v2\", you would specify ``version.v2``. The value\nof any of these keys is a Paste application. If you have a\n\"vers_list\" application and \"api_v1\" and \"api_v2\" as the two versions\nof your API, this configuration would look like::\n\n version = vers_list\n version.v1 = api_v1\n version.v2 = api_v2\n\n [app:vers_list]\n ...\n\n [app:api_v1]\n ...\n\n [app:api_v2]\n ...\n\nThis declares the available versions, but we have not provided any\ncriteria to select the version to route a request to. We will\nconsider a simple URI mapping first; these options are declared by\nprefixing the URI prefix with ``uri.``, and the value will be one of\nthe declared version identifiers. For example, let us say that the\nURI \"/v1\" will map to the \"v1\" API, while \"/v2\" maps to the \"v2\" API;\nthe relevant configuration would then be::\n\n uri./v1 = v1\n uri./v2 = v2\n\nNote that these URI prefixes will be normalized, e.g., \"//v1//\"\nnormalizes to \"/v1\". Also, AVersion takes care to ensure that the\nlongest match will be used; if one of your URIs was \"/v1.1\" and the\nother was \"/v1\", a request to \"/v1.1/foo\" would be routed to the\nfirst. Finally, the prefixes are assumed to be complete path\nfragments; the configuration shown above would not route a request to\n\"/v2-foo\" to the \"v2\" application, while \"/v2/foo\" would be so routed.\n\nSome applications also need to allow specifying the API version\nthrough a parameter on the content type. For instance, if the\n\"Content-Type\" header on a request body is set to\n\"application/json;version=2\", we want to select the \"v2\" API when the\nrequest is made against \"/\". (The version determined from the URI\ntrumps any version determined from \"Content-Type\" or \"Accept\".)\nSimilarly, if the \"Accept\" header includes\n\"application/json;version=2\", and the version cannot be determined\nfrom the URI prefix or the \"Content-Type\" header, then we want to use\nthe \"version\" parameter on that selected content type.\n\nTo configure the recognized content types, and to set up rules that\nallow selection of the correct version, declare the types as\nconfiguration keys prefixed with ``type.``, e.g.,\n``type.application/json``. The value of this configuration key can\nthen declare the version with a simple text substitution, e.g.::\n\n type.application/json = version:\"v%(version)s\"\n\nThe text substitution should result in the name of the version, as\ndeclared above. It is also possible to alter the type, e.g., if a\ngiven content type actually maps to another. Consider, for instance::\n\n type.application/vnd.fooapp = type:\"application/%(fmt)s\"\n version:\"v%(version)s\"\n\nIn this example, the content type\n\"application/vnd.fooapp;fmt=json;version=2\" would make a call to the\n\"v2\" API, with the \"Accept\" header rewritten to select\n\"application/json\".\n\nBoth the \"type\" and \"version\" tokens are optional in the ``type.``\nconfiguration values. When the \"type\" token is omitted, the existing\ncontent type is used, and when the \"version\" token is omitted, no\nversion determination is made. Do note, however, that the\n\"Content-Type\" header of the response will likely be that appearing in\nthe \"type\" token; future work may be done to correct this.\n\nSince the ``type.`` keys can overwrite the content types specified in\nthe \"Accept\" header, there is one more optional type of key that can\nselect the content type based on the URI suffix. For instance, the\napplication may desire that, if the \".json\" suffix is present, the\nselected content type should be \"application/json\". To configure\nthis, simply use the suffix as a configuration key; the value will be\nthe desired content type::\n\n .json = application/json\n\nFinally, the ``type.`` keys may select a version other than the one\nwhich is desired. For instance, the two API versions \"v1.1\" and\n\"v2\"--appearing as a parameter to a content type--may identify the\nsame version of the API. To enable this, use the ``alias.`` keys,\nlike so::\n\n alias.v1.1 = v2\n\nIn this example, the content type\n\"application/vnd.fooapp;fmt=json;version=1.1\" would also make a call\nto the \"v2\" API.\n\nAlthough the above description of ``alias.`` references content types,\naliasing also works for URIs, e.g.::\n\n uri./v1.1 = v1.1\n\nHere, accesses to the \"/v1.1\" endpoint will also be passed to the \"v2\"\napi.\n\nPutting this all together, a complete AVersion configuration may look\nlike the following::\n\n [composite:main]\n use = egg:aversion#aversion\n\n # Specify the version applications\n version = vers_list\n version.v1 = api_v1\n version.v2 = api_v2\n\n # Specify an alias\n alias.v1.1 = v2\n\n # Map the URI prefixes\n uri./v1 = v1\n uri./v1.1 = v1.1\n uri./v2 = v2\n\n # Recognize several types\n type.application/json = version:\"v%(version)s\"\n type.application/xml = version:\"v%(version)s\"\n type.application/vnd.fooapp = type:\"application/%(fmt)s\"\n version:\"v%(version)s\"\n\n # Also recognize URI suffixes\n .json = application/json\n .xml = application/xml\n\n [app:vers_list]\n # Specify the vers_list application\n ...\n\n [app:api_v1]\n # Specify the v1 API application\n ...\n\n [app:api_v2]\n # Specify the v2 API application\n ...\n\nExtending AVersion\n==================\n\nAVersion processes a given request first for the URI prefixes and\nsuffixes, then for a version specified by the \"Content-Type\" header on\nthe request body, then for a version and content type set through the\n\"Accept\" header (for which it implements the HTTP best-match content\ntype algorithm). The first content type and version found in this\nprocessing will be used.\n\nIt is possible to extend the ``aversion.AVersion`` class to alter the\norder of these processing steps, or to provide other processing\nsteps. The key is to override the ``_process()`` method. This method\ntakes one required argument--the request object--and one optional\n\"result\" argument, and returns the result. (If the result argument is\nnot provided, ``_process()`` allocates an instance of\n``aversion.Result``.) It calls each of ``_proc_uri()``,\n``_proc_ctype_header()``, and ``_proc_accept_header()`` in turn.\n\nDevelopers may also be interested in some of the available utility\nfunctions, which are used by AVersion. The ``quoted_split()``\nfunction can handle splitting multi-valued headers, like the \"Accept\"\nheader, even in the face of quoted arguments possibly containing the\nseparator. The ``parse_ctype()`` function takes a content type,\ncomplete with its parameters, and returns the bare content type and a\ndictionary containing those parameters. Finally, ``best_match()``\nimplements the best-match algorithm for content types, and may be\nuseful as an example for implementing matchers for other \"Accept-\\*\"\nheaders.\n\nAdvanced AVersion Usage\n=======================\n\nAVersion adds several variables to the WSGI environment that may be\nuseful to applications. The added WSGI environment variables all\nbegin with ``aversion.`` and are described below.\n\n``aversion.version``\n--------------------\n\nThe ``aversion.version`` variable contains the name of the selected\nversion. If the default application is selected, this value will be\n``None``. Otherwise, it will be a string identifying the configured\nversion.\n\n``aversion.config``\n-------------------\n\nThe ``aversion.config`` variable contains a dictionary of three\nentries: \"versions\", \"aliases\", and \"types\". Each of these entries\ncontains a dictionary which contains further information about the\nconfigured components, as described below.\n\n``versions``\n The ``versions`` element of the ``aversion.config`` variable is\n keyed by version names. Each version is described by a dictionary\n of three or four entries: the ``name`` key contains the name of\n the version; ``app`` is a reference to the WSGI application\n implementing that API version; ``params`` is a dictionary\n containing version parameters (see `Advanced AVersion\n Configuration`_); and ``prefixes``, if present, contains a list of\n configured URI prefixes for that version.\n\n``aliases``\n The ``aliases`` element of the ``aversion.config`` variable is\n keyed by aliases. Each alias is described by a dictionary of\n three entries: the ``alias`` key contains the name of the alias;\n the ``version`` key contains the canonical version name\n corresponding to the alias; and ``params`` is a dictionary\n containing alias parameters (see `Advanced AVersion\n Configuration`_).\n\n``types``\n The ``types`` element of the ``aversion.config`` variable is keyed\n by content types. Each content type is described by a dictionary\n of two or three entries: the ``name`` key contains the name of the\n content type; the ``params`` key is a dictionary containing\n content type parameters (see `Advanced AVersion Configuration`_);\n and ``suffixes``, if present, contains a list of configured URI\n suffixes for that type.\n\nExamples of ``aversion.config``\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nWhat follows is an example of the value of ``aversion.config``, as it\nwould appear if the above example configuration was used; note that\n``params`` is an empty dictionary in all cases (`Advanced AVersion\nConfiguration`_ covers parameters for versions, aliases, and content\ntypes in more detail)::\n\n {\n 'versions': {\n 'v1': {\n 'name': 'v1',\n 'app': ,\n 'params': {},\n 'prefixes': ['/v1'],\n },\n 'v2': {\n 'name': 'v2',\n 'app': ,\n 'params': {},\n 'prefixes': ['/v2'],\n },\n },\n 'aliases': {\n 'v1.1': {\n 'alias': 'v1.1',\n 'version': 'v2',\n 'params': {},\n },\n },\n 'types': {\n 'application/json': {\n 'name': 'application/json',\n 'params': {},\n 'suffixes': ['.json'],\n },\n 'application/xml': {\n 'name': 'application/xml',\n 'params': {},\n 'suffixes': ['.xml'],\n },\n 'application/vnd.fooapp': {\n 'name': 'application/vnd.fooapp',\n 'params': {},\n },\n },\n }\n\nIt is also worth noting that the type \"application/vnd.fooapp\" has no\nconfigured suffixes, and so the ``suffixes`` key is omitted from its\ndescription. Similarly, if a version was declared for which there was\nno corresponding URI prefix, that version would not have a\n``prefixes`` key.\n\nVariables Associated with the \"Content-Type\" Header\n---------------------------------------------------\n\nThere are three variables associated with the \"Content-Type\" header.\nThey are only set if a \"Content-Type\" header is set on the request,\nand is matched by a type rule, and are described below.\n\n``aversion.request_type``\n This is the final content type for the body of the request, after\n transformation by the type rule. This value will also be used to\n overwrite the \"Content-Type\" header.\n\n``aversion.orig_request_type``\n This is the name of the matching type rule.\n\n``aversion.content_type``\n This will be the original value of the \"Content-Type\" header.\n\nVariables Associated with the \"Accept\" Header\n---------------------------------------------\n\nThere are three variables associated with the \"Accept\" header. They\nare set if the requested content type can be determined. The\nrequested content type may be determined from a URI suffix or from the\ncontents of the \"Accept\" header, and are described below.\n\n``aversion.response_type``\n This is the final content type requested by the client, after\n transformation by the type rule. This value will also be used to\n overwrite the \"Accept\" header.\n\n``aversion.orig_response_type``\n This is the name of the matching type rule. If the content type\n was determined from a URI suffix, this value will be ``None``.\n\n``aversion.accept``\n This will be the original value of the \"Accept\" header. If none\n was present in the request (e.g., if the requested content type\n was determined from a URI suffix rule), this value will be\n ``None``.\n\nAdvanced AVersion Configuration\n===============================\n\nThe discussion about the ``aversion.config`` WSGI environment variable\nreferred to parameters on versions, aliases, and content types. These\nparameters are specifically for the benefit of applications, and are\nignored by AVersion; they can be used for communicating important\ninformation about the configured versions, aliases, and content types\nto the applications, particularly the default application.\n\nTo configure parameters on versions, simply add 'key=\"value\"' after\nthe version application name, e.g.::\n\n version.v1 = api_v1 key1=\"value1\" key2=\"value2\"\n\nFor aliases, the syntax is similar::\n\n alias.v1.1 = v2 key1=\"value1\" key2=\"value2\"\n\nThe syntax is a little more complex for content type rules; the\n'key=\"value\"' tokens must be prefixed with \"param:\", e.g.::\n\n type.application/json = version:\"v%(version)s\"\n param:key1=\"value1\" param:key2=\"value2\"\n\nNote that all values must be quoted. Both double quotes and single\nquotes are acceptable quote characters, and it is safe to include\nspaces within the quoted text.\n\nThere is one more advanced configuration topic. By default, AVersion\noverwrites the \"Accept\" and \"Content-Type\" headers. Since the\ninformation it would use for this overwriting is available in the WSGI\nenvironment, it is possible to disable this behavior by setting the\n``overwrite_headers`` configuration key to \"off\". (Recognized values\nare: \"false\", \"f\", \"off\", \"no\", \"disable\", and \"0\"; \"true\", \"t\", \"on\",\n\"yes\", \"enable\", and any non-zero integer are recognized as \"on\", the\ndefault value for ``overwrite_headers``.)", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/klmitch/aversion", "keywords": null, "license": "Apache License (2.0)", "maintainer": null, "maintainer_email": null, "name": "aversion", "package_url": "https://pypi.org/project/aversion/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/aversion/", "project_urls": { "Download": "UNKNOWN", "Homepage": "https://github.com/klmitch/aversion" }, "release_url": "https://pypi.org/project/aversion/0.1.0/", "requires_dist": null, "requires_python": null, "summary": "AVersion WSGI Version Selection Application", "version": "0.1.0" }, "last_serial": 786639, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "4d0805b1c918d2d9a0491c2fc3f3e56b", "sha256": "4f2f7c1371a95653485a4acc21daeb546b1a9c9ef2b1639b4d92c9e46b01e4ef" }, "downloads": -1, "filename": "aversion-0.1.0.tar.gz", "has_sig": false, "md5_digest": "4d0805b1c918d2d9a0491c2fc3f3e56b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 27978, "upload_time": "2013-02-12T23:30:02", "url": "https://files.pythonhosted.org/packages/13/b4/c198db20759bd9defd427a89bdb26fe25bf6ebde1b9dea793db573530123/aversion-0.1.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "4d0805b1c918d2d9a0491c2fc3f3e56b", "sha256": "4f2f7c1371a95653485a4acc21daeb546b1a9c9ef2b1639b4d92c9e46b01e4ef" }, "downloads": -1, "filename": "aversion-0.1.0.tar.gz", "has_sig": false, "md5_digest": "4d0805b1c918d2d9a0491c2fc3f3e56b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 27978, "upload_time": "2013-02-12T23:30:02", "url": "https://files.pythonhosted.org/packages/13/b4/c198db20759bd9defd427a89bdb26fe25bf6ebde1b9dea793db573530123/aversion-0.1.0.tar.gz" } ] }