{ "info": { "author": "F\u00c1BI\u00c1N Tam\u00e1s L\u00e1szl\u00f3", "author_email": "giganetom@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Environment :: Plugins", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", "Programming Language :: Python", "Topic :: Software Development :: Libraries" ], "description": "pyicap\n======\n\nA Python 3 framework for writing ICAP servers\n\nInstallation\n------------\n\nYou can use the package right away, if you copy the pyicap.py file\nonto your PYTHONPATH, or the directory of your python module.\n\nA setup.py is provided with the package, run it to install the\npackage:\n\n sudo ./setup.py install\n\npip3/easy_install doesn't know about this yet\n\nYou can also install with pip or easy-install:\n\n sudo pip install pyicap\n\nWhat is ICAP?\n-------------\n\nFor a dry and precise technical description see RFC 3507.\n\nICAP is a protocol that is used by HTTP proxies to ask a separate\nservice (an ICAP server) to do modification on HTTP requests and\nresponses it proxies. Such proxy is an ICAP client.\n\nICAP can be used to check permissions, scan viruses, place ads or\notherwise modify the headers, content or request URL or HTTP requests\nand/or responses. These can be done without modifying the proxy server's\ncode.\n\nThe popular proxy software Squid 3.x supports the ICAP protocol, and\nthis framework was tested with Squid3.\n\nDesign\n------\n\nThe ICAP protocol closely resembles HTTP/1.1, so I choosed to modify\nPython's stock BaseHTTPServer class for the purpose.\n\nIt is important to note that ICAP _IS NOT_ an application of HTTP,\nneither a protocoll wrapped into it. If a relationship must be stated,\nI's say ICAP is a sibling of HTTP rather it's child.\n\nBecause of this relationship a HTTP server or client cannot be trivially\nextended (or even monkey-patched) to handle ICAP. This is why I choose\nto copy, then completely rewrite the BaseHTTPServer class\n\nHow it works?\n-------------\n\nYou can use a framework by importing stuff from the pyicap package,\nextending the protocol handler class and starting the server, passing\nyour handler to it:\n\n```python\n#!/bin/env python\n# -*- coding: utf8 -*-\n\nimport random\nimport SocketServer\n\nfrom pyicap import *\n\nclass ThreadingSimpleServer(SocketServer.ThreadingMixIn, ICAPServer):\n pass\n\nclass ICAPHandler(BaseICAPRequestHandler):\n\n def echo_OPTIONS(self):\n self.set_icap_response(200)\n self.set_icap_header('Methods', 'RESPMOD')\n self.set_icap_header('Preview', '0')\n self.send_headers(False)\n\n def echo_RESPMOD(self):\n self.no_adaptation_required()\n\nport = 13440\n\nserver = ThreadingSimpleServer(('', port), ICAPHandler)\ntry:\n while 1:\n server.handle_request()\nexcept KeyboardInterrupt:\n print \"Finished\"\n\n```\n\nThe above example is a rewritten SimpleHTTPServer example with\nthreading. The SocketServer.ThreadingMixin can be used with ICAPServer\njust like you would use it with SimpleHTTPServer.\n\nFor every service endpoint there is a pair of methods. The current\nexample simply does nothing by telling the ICAP client that the request\nneeds no modification.\n\nICAP defines three HTTP-like methods: OPTIONS, REQMOD and RESPMOD.\n\nOPTIONS must be handled in every case. An endpoint has to support either\nREQMOD or RESPMOD, but not both. However, this is not enforced, and\naccording to the squid 3 documentation, such overloading will even work\nwith squid.\n\nREQMOD is called, when a HTTP request must be modified - like checking\naccess to an URL, stripping or adding query string parameters or POST\ndata, modifying headers or otherwise mangling the request.\n\nRESPMOD is called when a HTTP response must be modified - such as\nchecking to-be-downloaded files for viruses, watermarking images or\naudio files, placing ad banners, or otherwise modifying the content\nand/or the headers of the request.\n\nICAP works with URLs just like HTTP. Every ICAP service has an URL like:\n\nicap://icap.myorganization.com/place_banners\n\nThe PyICAP framework will parse this URL, determines the ICAP method to\ncall (OPTIONS, REQMOD or RESPMOD), and calls one of the handler methods\nthat the user (probably) provided. If the ICAP server can't find a\nhandler method, it returns a 404 error.\n\nIn this particular example, the place_banners_*() method is called (*\ncan be reqmod or respmod).\n\nAn OPTIONS request triggers the related _options() method, in this case\nthe place_banners_options().\n\nVarious information can be extracted from the ICAP request by examining\ncertain fields of the handler object:\n\n* enc_req: encapsulated request line, list with 3 elements\n* enc_req_headers: encapsulated request headers, dictionary of lists\n* enc_res_status: encapsulated response status\n* enc_res_headers: encapsulated response headers\n* has_body: True, if the ICAP request has a body\n* servicename: name of the service endpoint\n* encapsulated: contains the \"Encapsulated:\" header's content as a dict\n* ieof: True, if read_chunk() encounters an ieof chunk extension\n* command: the current ICAP command\n* request_uri: contains the full request URI of the ICAP request\n* version: the version if the current ICAP request\n* preview: None, or an integer that arrived in the Preview header\n* allow: Contains a set() of Allow:-ed stuff\n* icap_response_code: contains the response code if set_icap_reponse\n was called.\n\nThere are several helper methods that can be called while serving a\nrequets:\n\n* send_error(error_code): Sends and entire ICAP error response\n* no_adaptation_required(): Sends a response that means that leaves the\n encapsulated message unaltered. It honors the Allow header, and only\n sends 204 No adaptation required if the client allowed such response.\n* cont(): Sends an ICAP 100 Continue response to the client. Can be\n used to request the client to continue sending data after a preview.\n* read_chunk(): Reads a chunk from the client. Be aware that this call\n blocks. If there is no available data on the line, and Connection: \n keep-alive is used, it will cause the server to hang. This method\n should only be called if it's sure there will be data available\n eventually. If it returns an empty string, it means that it's the\n last chunk, and no further read should be executed. It also sets the\n ieof variable to True, if the ieof chunk extension is encountered.\n This extension is sent during a preview if the encapsulated message\n fits in the preview entirelly. If ieof is True continue() must not be\n called.\n* set_icap_response(code): sets the ICAP response\n* set_enc_status(stats): Sets the encapsulated status line\n* set_enc_request(request): Sets the encapsulated request line\n* set_enc_header(header, value): Set an encapsulated header. Multiple\n calls will cause the header to be sent more than once. This is useful\n for example for Cookie: headers.\n* set_icap_header(header, value): Set an ICAP header. Note that this should\n not be used normally, since all necesary ICAP headers are set\n automatically by the framework (such as ISTag, Encapsulated, Date,\n Server, etc.)\n* send_headers(has_body=False): can be used after setting ICAP and\n encapsulated headers. The parameter has_body signals the existance of\n an encapsulated message body.\n* send_chunk(data): writes a chunk to the client. An empty chunk must\n be written as the last chunk. Data must be sent after send appropriate\n headers either with send_header() or enc_header()/icap_header() +\n send_headers(). The two header-sending methods must not be mixed.\n If sending data with send_headers, the has_body parameter must be set\n to properly indicate the existance or absence of an encapsulated\n message body.\n\n\n\n\n", "description_content_type": null, "docs_url": "https://pythonhosted.org/pyicap/", "download_url": "https://github.com/netom/pyicap/tarball/1.0b1#egg=pyicap-1.0b1", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/netom/pyicap/", "keywords": null, "license": "BSD License", "maintainer": null, "maintainer_email": null, "name": "pyicap", "package_url": "https://pypi.org/project/pyicap/", "platform": "OS Independent", "project_url": "https://pypi.org/project/pyicap/", "project_urls": { "Download": "https://github.com/netom/pyicap/tarball/1.0b1#egg=pyicap-1.0b1", "Homepage": "https://github.com/netom/pyicap/" }, "release_url": "https://pypi.org/project/pyicap/1.0b1/", "requires_dist": null, "requires_python": null, "summary": "A framework for writing ICAP servers", "version": "1.0b1" }, "last_serial": 2755786, "releases": { "1.0a1": [], "1.0a2": [], "1.0a3": [], "1.0a4": [], "1.0a5": [], "1.0a6": [], "1.0a7": [ { "comment_text": "", "digests": { "md5": "cca22b027d23e674d20e6cf2d97c719f", "sha256": "287690c0f33cd7393521f7326851fa74cf642299bc4b1de123d49fababfacc8b" }, "downloads": -1, "filename": "pyicap-1.0a7.tar.gz", "has_sig": false, "md5_digest": "cca22b027d23e674d20e6cf2d97c719f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13516, "upload_time": "2013-06-04T08:41:53", "url": "https://files.pythonhosted.org/packages/be/ad/0f5af1322f1bf6093ad5978debc75262f8415ac1734dca6fdfa4534cbc72/pyicap-1.0a7.tar.gz" } ], "1.0a8": [ { "comment_text": "", "digests": { "md5": "05eff7114eb245e973a865c8fe3fd096", "sha256": "aa66328618023a6cce8edb6899cfcbf347bffe003d8bed981eb71450dbcae7bf" }, "downloads": -1, "filename": "pyicap-1.0a8.tar.gz", "has_sig": false, "md5_digest": "05eff7114eb245e973a865c8fe3fd096", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7359, "upload_time": "2013-07-08T07:38:11", "url": "https://files.pythonhosted.org/packages/de/09/eb8c1777b4bebdeacd02fdb6ee06fba64268ec5f65d3c5b1f851fe71bfc7/pyicap-1.0a8.tar.gz" } ], "1.0b": [ { "comment_text": "", "digests": { "md5": "0b61b2cbc1843ed488a156fa1c8d68cb", "sha256": "1dab54f202d29ab9b61b98f7894eb8fc7fbadbd38c9140614c3d4a0c52ab7d19" }, "downloads": -1, "filename": "pyicap-1.0b.tar.gz", "has_sig": false, "md5_digest": "0b61b2cbc1843ed488a156fa1c8d68cb", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 14449, "upload_time": "2017-03-01T10:03:01", "url": "https://files.pythonhosted.org/packages/b3/e0/37981b3028fb774f5cd47884acd1b902fbc674c362d75ccad3257f7972fb/pyicap-1.0b.tar.gz" } ], "1.0b1": [ { "comment_text": "", "digests": { "md5": "f1549e07f2ebd57e0ca4fc4d5cc041e7", "sha256": "ad3eeb90085d56fc96dac68d57d8b02fc25671bd9de52e86e415855be70cbd73" }, "downloads": -1, "filename": "pyicap-1.0b1.tar.gz", "has_sig": false, "md5_digest": "f1549e07f2ebd57e0ca4fc4d5cc041e7", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 15334, "upload_time": "2017-04-05T19:06:22", "url": "https://files.pythonhosted.org/packages/c1/e2/cc5c71e6e20de872ce81e41e95c4a2ecca9aa8a8d4947f7a1a806f6a6880/pyicap-1.0b1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "f1549e07f2ebd57e0ca4fc4d5cc041e7", "sha256": "ad3eeb90085d56fc96dac68d57d8b02fc25671bd9de52e86e415855be70cbd73" }, "downloads": -1, "filename": "pyicap-1.0b1.tar.gz", "has_sig": false, "md5_digest": "f1549e07f2ebd57e0ca4fc4d5cc041e7", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 15334, "upload_time": "2017-04-05T19:06:22", "url": "https://files.pythonhosted.org/packages/c1/e2/cc5c71e6e20de872ce81e41e95c4a2ecca9aa8a8d4947f7a1a806f6a6880/pyicap-1.0b1.tar.gz" } ] }