feat: Add new gcloud commands, API clients, and third-party libraries across various services.

This commit is contained in:
2026-01-01 20:26:35 +01:00
parent 5e23cbece0
commit a19e592eb7
25221 changed files with 8324611 additions and 0 deletions

View File

@@ -0,0 +1,122 @@
name: publish
on:
# on pull request, run build step to catch errors earlier, but do not publish
pull_request:
# on push to master without a version tag, publish to test PyPI registry
# ... with version tag, publish to production PyPI registry.
push:
branches: [master]
tags: ["v[0-9]*"]
jobs:
build:
# https://github.community/t/duplicate-checks-on-push-and-pull-request-simultaneous-event/18012/5
if: ${{ github.event_name == 'push' || github.event.pull_request.head.repo.full_name != 'httplib2/httplib2' }}
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v2
- name: cache pip
uses: actions/cache@v2
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-publish
restore-keys: |
${{ runner.os }}-pip-
${{ runner.os }}-
- name: setup python
uses: actions/setup-python@v2
with:
python-version: 3.x
- name: install tools
run: pip install --upgrade build check-manifest setuptools twine wheel
- name: build package
run: python -m build
- name: check manifest
run: check-manifest
- name: twine check
run: twine check dist/*
- uses: actions/upload-artifact@v2
with:
name: dist
path: dist/
if-no-files-found: error
retention-days: 1
publish-prod:
if: ${{ github.repository == 'httplib2/httplib2' && startsWith(github.ref, 'refs/tags/') }}
needs: [build]
environment: pypi-public
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: cache pip
uses: actions/cache@v2
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-publish
restore-keys: |
${{ runner.os }}-pip-
- name: setup python
uses: actions/setup-python@v2
with:
python-version: 3.x
- name: install tools
run: pip install twine
- uses: actions/download-artifact@v2
with:
name: dist
path: dist/
- name: twine check
run: twine check dist/*
- name: twine upload (prod)
if: startsWith(github.ref, 'refs/tags/')
env:
TWINE_USERNAME: "__token__"
TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
run: twine upload --non-interactive --verbose dist/*
publish-test:
if: ${{ github.repository == 'httplib2/httplib2' && github.ref == 'refs/heads/master' }}
needs: [build]
environment: pypi-test
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: cache pip
uses: actions/cache@v2
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-publish
restore-keys: |
${{ runner.os }}-pip-
- name: setup python
uses: actions/setup-python@v2
with:
python-version: 3.x
- name: install tools
run: pip install twine
- uses: actions/download-artifact@v2
with:
name: dist
path: dist/
- name: twine upload (test)
if: github.ref == 'refs/heads/master'
env:
TWINE_USERNAME: "__token__"
TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
TWINE_REPOSITORY: "testpypi"
run: echo twine upload --non-interactive --skip-existing --verbose dist/*

View File

@@ -0,0 +1,37 @@
name: style
on:
push:
pull_request:
jobs:
style:
runs-on: ubuntu-latest
# https://github.community/t/duplicate-checks-on-push-and-pull-request-simultaneous-event/18012/5
if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != 'httplib2/httplib2'
timeout-minutes: 5
steps:
- uses: actions/checkout@v2
- name: cache pip
uses: actions/cache@v2
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('.github/workflows/style.yaml', 'pyproject.toml', 'requirements.txt', 'requirements-test.txt', 'setup.py') }}
restore-keys: |
${{ runner.os }}-pip-
${{ runner.os }}-
- name: setup python
uses: actions/setup-python@v2
with:
python-version: 3.x
- name: pip install
run: pip install black isort -r requirements-test.txt
- name: isort
run: isort --check python2/ python3/ tests/ || echo FIXME
- name: black
run: black --check --diff python2/ python3/ tests/ || echo FIXME
- name: flake8 python2/
run: flake8 python2/
- name: flake8 python3/ tests/
run: flake8 python3/ tests/

View File

@@ -0,0 +1,75 @@
name: test
on:
push:
pull_request:
schedule:
- cron: "34 4 */7 * *" # every week, time chosen by RNG
jobs:
test:
name: "test ${{ matrix.py }}"
continue-on-error: ${{ matrix.ignore-error }}
runs-on: ubuntu-latest
# https://github.community/t/duplicate-checks-on-push-and-pull-request-simultaneous-event/18012/5
if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != 'httplib2/httplib2'
timeout-minutes: 10
strategy:
fail-fast: false
matrix:
include:
- { py: 2.7, ignore-error: false }
- { py: 3.5, ignore-error: false }
- { py: 3.6, ignore-error: false }
- { py: 3.7, ignore-error: false }
- { py: 3.8, ignore-error: false }
- { py: 3.9, ignore-error: false }
- { py: 3.x, ignore-error: true }
- { py: pypy2, ignore-error: false }
- { py: pypy3, ignore-error: false }
steps:
- uses: actions/checkout@v2
- name: cache pip
uses: actions/cache@v2
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ matrix.py }}-${{ hashFiles('.github/workflows/test.yaml', 'pyproject.toml', 'requirements.txt', 'requirements-test.txt', 'setup.py') }}
restore-keys: |
${{ runner.os }}-pip-${{ matrix.py }}-
${{ runner.os }}-pip-
${{ runner.os }}-
- name: setup python ${{ matrix.py }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.py }}
- run: pip install tox-gh
if: startsWith(matrix.py, '3.') && matrix.py >= '3.6'
- run: pip install 'codecov>=2.0.15' -r requirements-test.txt
- run: script/test -sv
- run: codecov --flags=$(echo ${{ matrix.py }} |tr -d -- '-.')
test_py37_openssl11:
name: "TODO FIXME test py37-openssl11"
runs-on: ubuntu-latest
# https://github.community/t/duplicate-checks-on-push-and-pull-request-simultaneous-event/18012/5
# FIXME Permission denied /usr/local/lib/python3.8/dist-packages/
if: false && (github.event_name == 'push' || github.event.pull_request.head.repo.full_name != 'httplib2/httplib2')
timeout-minutes: 10
steps:
- uses: actions/checkout@v2
- name: cache pip
uses: actions/cache@v2
with:
path: ~/.cache
key: ${{ runner.os }}-py37_openssl11-${{ hashFiles('.github/workflows/test.yaml', 'pyproject.toml', 'requirements.txt', 'requirements-test.txt', 'setup.py') }}
restore-keys: |
${{ runner.os }}-py37_openssl11-
${{ runner.os }}-
- name: build custom python
run: source script/compile-py3-openssl11.sh # source to alter PATH
- run: pip install 'codecov>=2.0.15' tox-gh -r requirements-test.txt
- run: script/test -sv
- run: codecov --flags=py37_openssl11

View File

@@ -0,0 +1,31 @@
*.egg
*.egg-info
*.mo
*.py[cod]
*.so
.DS_Store
.cache/
.coverage
.hg
.installed.cfg
.mr.developer.cfg
.project
.pydevproject
.pytest_cache/*
.tags*
.tox
_httplib2_test_cache/*
bin
build
default.profraw
develop-eggs
dist
eggs
lib
lib64
nosetests.xml
parts
pip-log.txt
sdist
var
venv*/

View File

@@ -0,0 +1,470 @@
0.20.4
proxy: support proxy urls with ipv6 address
https://github.com/httplib2/httplib2/pull/217
0.20.3
No changes in library. Tests compatible with Python3.10 and recent pytest.
0.20.2
auth: support pyparsing v3 (AttributeError downcaseTokens)
https://github.com/httplib2/httplib2/issues/207
proxy: correct extraction of errno from pysocks ProxyConnectionError
https://github.com/httplib2/httplib2/pull/202
0.20.1
No changes from 0.20.0, re-upload of broken py2 wheel.
0.20.0
IMPORTANT cacerts: remove expired DST Root CA X3, add ISRG Root X1, X2
https://github.com/httplib2/httplib2/pull/200
https://github.com/httplib2/httplib2/issues/203
tls: accept min/max ssl.TLSVersion enum values
https://github.com/httplib2/httplib2/pull/191
setup(python_requires=...) may need setuptools update
https://github.com/httplib2/httplib2/pull/195
0.19.1
auth header parsing performance optimizations; Thanks to Paul McGuire
Use mock from the standard library on Python>=3.3
0.19.0
auth: parse headers using pyparsing instead of regexp
https://github.com/httplib2/httplib2/pull/182
auth: WSSE token needs to be string not bytes
https://github.com/httplib2/httplib2/pull/179
0.18.1
explicit build-backend workaround for pip build isolation bug
"AttributeError: 'module' object has no attribute '__legacy__'" on pip install
https://github.com/httplib2/httplib2/issues/169
0.18.0
IMPORTANT security vulnerability CWE-93 CRLF injection
Force %xx quote of space, CR, LF characters in uri.
Special thanks to Recar https://github.com/Ciyfly for discrete notification.
https://cwe.mitre.org/data/definitions/93.html
0.17.4
Ship test suite in source dist
https://github.com/httplib2/httplib2/pull/168
0.17.3
IronPython2.7: relative import iri2uri fixes ImportError
https://github.com/httplib2/httplib2/pull/163
0.17.2
python3 + debug + IPv6 disabled: https raised
"IndexError: Replacement index 1 out of range for positional args tuple"
https://github.com/httplib2/httplib2/issues/161
0.17.1
python3: no_proxy was not checked with https
https://github.com/httplib2/httplib2/issues/160
0.17.0
feature: Http().redirect_codes set, works after follow(_all)_redirects check
This allows one line workaround for old gcloud library that uses 308
response without redirect semantics.
https://github.com/httplib2/httplib2/issues/156
0.16.0
IMPORTANT cache invalidation change, fix 307 keep method, add 308 Redirects
https://github.com/httplib2/httplib2/issues/151
proxy: username/password as str compatible with pysocks
https://github.com/httplib2/httplib2/issues/154
0.15.0
python2: regression in connect() error handling
https://github.com/httplib2/httplib2/pull/150
add support for password protected certificate files
https://github.com/httplib2/httplib2/pull/143
feature: Http.close() to clean persistent connections and sensitive data
https://github.com/httplib2/httplib2/pull/149
0.14.0
Python3: PROXY_TYPE_SOCKS5 with str user/pass raised TypeError
https://github.com/httplib2/httplib2/pull/145
0.13.1
Python3: Use no_proxy
https://github.com/httplib2/httplib2/pull/140
0.13.0
Allow setting TLS max/min versions
https://github.com/httplib2/httplib2/pull/138
0.12.3
No changes to library. Distribute py3 wheels.
0.12.1
Catch socket timeouts and clear dead connection
https://github.com/httplib2/httplib2/issues/18
https://github.com/httplib2/httplib2/pull/111
Officially support Python 3.7 (package metadata)
https://github.com/httplib2/httplib2/issues/123
0.12.0
Drop support for Python 3.3
ca_certs from environment HTTPLIB2_CA_CERTS or certifi
https://github.com/httplib2/httplib2/pull/117
PROXY_TYPE_HTTP with non-empty user/pass raised TypeError: bytes required
https://github.com/httplib2/httplib2/pull/115
Revert http:443->https workaround
https://github.com/httplib2/httplib2/issues/112
eliminate connection pool read race
https://github.com/httplib2/httplib2/pull/110
cache: stronger safename
https://github.com/httplib2/httplib2/pull/101
0.11.3
No changes, just reupload of 0.11.2 after fixing automatic release conditions in Travis.
0.11.2
proxy: py3 NameError basestring
https://github.com/httplib2/httplib2/pull/100
0.11.1
Fix HTTP(S)ConnectionWithTimeout AttributeError proxy_info
https://github.com/httplib2/httplib2/pull/97
0.11.0
Add DigiCert Global Root G2 serial 033af1e6a711a9a0bb2864b11d09fae5
https://github.com/httplib2/httplib2/pull/91
python3 proxy support
https://github.com/httplib2/httplib2/pull/90
If no_proxy environment value ends with comma then proxy is not used
https://github.com/httplib2/httplib2/issues/11
fix UnicodeDecodeError using socks5 proxy
https://github.com/httplib2/httplib2/pull/64
Respect NO_PROXY env var in proxy_info_from_url
https://github.com/httplib2/httplib2/pull/58
NO_PROXY=bar was matching foobar (suffix without dot delimiter)
New behavior matches curl/wget:
- no_proxy=foo.bar will only skip proxy for exact hostname match
- no_proxy=.wild.card will skip proxy for any.subdomains.wild.card
https://github.com/httplib2/httplib2/issues/94
Bugfix for Content-Encoding: deflate
https://stackoverflow.com/a/22311297
0.10.3
Fix certificate validation on Python<=2.7.8 without ssl.CertificateError
https://github.com/httplib2/httplib2/issues/45
0.10.2
Just a reupload of 0.10.1, which was broken for Python3
because wheel distribution doesn't play well with our 2/3 split code base.
https://github.com/httplib2/httplib2/issues/43
0.10.1
This is the first release by new httplib2 team. See post by Joe
https://bitworking.org/news/2016/03/an_update_on_httplib2
Remove VeriSign Class 3 CA from trusted certs
https://googleonlinesecurity.blogspot.com/2015/12/proactive-measures-in-digital.html
Add IdenTrust DST Root CA X3
https://github.com/httplib2/httplib2/pull/26
Support for specifying the SSL protocol version (Python v2)
https://github.com/jcgregorio/httplib2/issues/329
On App Engine use urlfetch's default deadline if None is passed.
Fix TypeError on AppEngine “__init__() got an unexpected keyword argument 'ssl_version
https://github.com/httplib2/httplib2/pull/12
Send SNI data for SSL connections on Python 2.7.9+
Verify the server hostname if certificate validation is enabled
https://github.com/httplib2/httplib2/pull/13
Add proxy_headers argument to ProxyInfo constructor
https://github.com/httplib2/httplib2/pull/21
Make disable_ssl_certificate_validation work with Python 3.5.
https://github.com/httplib2/httplib2/pull/15
Fix socket error handling
https://github.com/httplib2/httplib2/commit/eb7468561714a5b700d5a3d8fa1a8794de02b9ef
https://github.com/httplib2/httplib2/commit/e7f6e622047107e701ee70e7ec586717d97b0cbb
0.9.2
Fixes in this release:
https://github.com/jcgregorio/httplib2/pull/313
Fix incorrect ResponseNotReady exceptions, retry on transient errors.
0.9.1
Fixes in this release:
https://github.com/jcgregorio/httplib2/pull/296
There was a problem with headers when a binary string is passed (like
b'Authorization').
https://github.com/jcgregorio/httplib2/pull/276
Default to doing DNS resolution through a proxy server if present.
0.9
Heartbleed
0.8
More fixes for the App Engine support.
Added a new feature that allows you to supply your own provider for the
CA_CERTS file. Just create a module named ca_certs_locater that has a method
get() that returns the file location of the CA_CERTS file.
Lots of clean up of the code formatting to make it more consistent.
0.7.7
More fixes for App Engine, now less likely to swallow important exceptions.
Adding proxy_info_from_* methods to Python3. Reviewed in https://codereview.appspot.com/6588078/.
Added GeoTrust cert
Make httplib2.Http() instances pickleable. Reviewed in https://codereview.appspot.com/6506074/
The following issues have been fixed:
229 python3 httplib2 clobbers multiple headers of same key
230 Expose meaningful exception for App Engine URLFetch ResponseTooLargeError
231 Expose App Engine URLFetch DeadlineExceededError for debugging purposes
0.7.6
Fixes for App Engine 2.7.
0.7.5
Keys are lowercase in a Response object, regardless of how Response object is constructed.
Add control so that Authorization: headers aren't forwarded on a 3xx response by default.
Set the reason correctly when running on App Engine. Patch from Alain Vongsouvanh. Reviewed in http://codereview.appspot.com/6422051/
Fix proxy socks for SSL connections. Fixes issue #199.
You can now set httplib2.RETRIES to the number of retries before a request
is considered to fail It is set to a default of 2 to mimic the traditional
behavior of httplib2.
The following issues have been addressed:
223 HEAD requests fail calling the close() method of ResponseDict instance.
222 Can't disable cert validation in appengine
204 Credentials can leak in HTTP redirects
210 Different API between Python 2 and Python 3 version breaks wsgi_intercept
214 ValueError on malformated cache entries
204 Credentials can leak in HTTP redirects
0.7.3
ProxyInfo objects now can construct themselves from environment
variables commonly-used in Unix environments. By default, the Http
class will construct a ProxyInfo instance based on these environment
variables. To achieve the previous behavior, where environment
variables are ignored, pass proxy_info=None to Http().
The following issues have been addressed:
Issue 159: automatic detection of proxy configuration.
Issue 179: Allow unicode in proxy hostname.
Issue 194: Added support for setuptools.
Fixes for HTTP CONNECT proxies.
0.7.1
Fix failure to install cacerts.txt for 2.x installs.
0.7.0
The two major changes in this release are SSL Certificate
checking and App Engine support. By default the certificates
of an HTTPS connection are checked, but that can be disabled
via disable_ssl_certificate_validation. The second change
is that on App Engine there is a new connection object
that utilizes the urlfetch capabilities on App Engine, including
setting timeouts and validating certificates.
The following issues have been addressed:
Fixes issue 72. Always lowercase authorization header.
Fix issue 47. Redirects that become a GET should not have a body.
Fixes issue 19. Set Content-location on redirected HEAD requests
Fixes issue 139. Redirect with a GET on 302 regardless of the originating method.
Fixes issue 138. Handle unicode in headers when writing and retrieving cache entries. Who says headers have to be ASCII!
Add certificate validation. Work initially started by Christoph Kern.
Set a version number. Fixes issue # 135.
Sync to latest version of socks.py
Add gzip to the user-agent, in case we are making a request to an app engine project: http://code.google.com/appengine/kb/general.html#compression
Uses a custom httplib shim on App Engine to wrap urlfetch, as opposed
Add default support for optimistic concurrency on PATCH requests
Fixes issue 126. IPv6 under various conditions would fail.
Fixes issue 131. Handle socket.timeout's that occur during send.
proxy support: degrade gracefully when socket.socket is unavailable
0.6.0
The following issues have been addressed:
#51 - Failure to handle server legitimately closing connection before request body is fully sent
#77 - Duplicated caching test
#65 - Transform _normalize_headers into a method of Http class
#45 - Vary header
#73 - All files in Mercurial are executable
#81 - Have a useful .hgignore
#78 - Add release tags to the Mercurial repository
#67 - HEAD requests cause next request to be retried
Mostly bug fixes, the big enhancement is the addition of proper Vary: header
handling. Thanks to Chris Dent for that change.
The other big change is the build process for distributions so that both python2 and python3
are included in the same .tar.gz/.zip file.
0.5.0
Added Python 3 support
Fixed the following bugs:
#12 - Cache-Control: only-if-cached incorrectly does request if item not in cache
#39 - Deprecation warnings in Python 2.6
#54 - Http.request fails accessing Google account via http proxy
#56 - Block on response.read() for HEAD requests.
#57 - Timeout ignore for Python 2.6
#58 - Fixed parsing of Cache-Control: header to make it more robust
Also fixed a deprecation warning that appeared between Python 3.0 and 3.1.
0.4.0
Added support for proxies if the Socksipy module is installed.
Fixed bug with some HEAD responses having content-length set to
zero incorrectly.
Fixed most except's to catch a specific exception.
Added 'connection_type' parameter to Http.request().
The default for 'force_exception_to_status_code' was changed to False. Defaulting
to True was causing quite a bit of confusion.
0.3.0
Calling Http.request() with a relative URI, as opposed to an absolute URI,
will now throw a specific exception.
Http() now has an additional optional parameter for the socket timeout.
Exceptions can now be forced into responses. That is, instead of
throwing an exception, a good httlib2.Response object is returned
that describe the error with an appropriate status code.
Many improvements to the file cache:
1. The names in the cache are now much less
opaque, which should help with debugging.
2. The disk cache is now Apache mod_asis compatible.
3. A Content-Location: header is supplied and stored in the
cache which points to the original requested URI.
User supplied If-* headers now override httplib2 supplied
versions.
IRIs are now fully supported. Note that they MUST be passed in
as unicode objects.
Http.add_credentials() now takes an optional domain to restrict
the credentials to being only used on that domain.
Added Http.add_certificate() which allows setting
a key and cert for SSL connections.
Many other bugs fixed.
0.2.0
Added support for Google Auth.
Added experimental support for HMACDigest.
Added support for a pluggable caching system. Now supports
the old system of using the file system and now memcached.
Added httplib2.debuglevel which turns on debugging.
Change Response._previous to Response.previous.
Added Http.follow_all_redirects which forces
httplib2 to follow all redirects, as opposed to
following only the safe redirects. This makes the
GData protocol easier to use.
All known bugs fixed to date.
0.1.1
Fixed several bugs raised by James Antill:
1. HEAD didn't get an Accept: header added like GET.
2. HEAD requests did not use the cache.
3. GET requests with Range: headers would erroneously return a full cached response.
4. Subsequent requests to resources that had timed out would raise an exception.
And one feature request for 'method' to default to GET.
Xavier Verges Farrero supplied what I needed to make the
library work with Python 2.3.
I added distutils based setup.py.
0.1 Rev 86
Initial Release

View File

@@ -0,0 +1,23 @@
Httplib2 Software License
Copyright (c) 2006 by Joe Gregorio
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,12 @@
recursive-include python2 *.py *.txt
recursive-include python3 *.py *.txt README
graft doc
graft tests
include *.md
include CHANGELOG
include LICENSE
include requirements*.txt
exclude codecov.yml
prune ref
global-exclude __pycache__
global-exclude *.py[cod]

View File

@@ -0,0 +1,113 @@
Introduction
============
httplib2 is a comprehensive HTTP client library, httplib2.py supports many
features left out of other HTTP libraries.
### HTTP and HTTPS
HTTPS support is only available if the socket module was
compiled with SSL support.
### Keep-Alive
Supports HTTP 1.1 Keep-Alive, keeping the socket open and
performing multiple requests over the same connection if
possible.
### Authentication
The following three types of HTTP Authentication are
supported. These can be used over both HTTP and HTTPS.
* Digest
* Basic
* WSSE
### Caching
The module can optionally operate with a private cache that
understands the Cache-Control: header and uses both the ETag
and Last-Modified cache validators.
### All Methods
The module can handle any HTTP request method, not just GET
and POST.
### Redirects
Automatically follows 3XX redirects on GETs.
### Compression
Handles both 'deflate' and 'gzip' types of compression.
### Lost update support
Automatically adds back ETags into PUT requests to resources
we have already cached. This implements Section 3.2 of
Detecting the Lost Update Problem Using Unreserved Checkout.
### Unit Tested
A large and growing set of unit tests.
Installation
============
$ pip install httplib2
Usage
=====
A simple retrieval:
```python
import httplib2
h = httplib2.Http(".cache")
(resp_headers, content) = h.request("http://example.org/", "GET")
```
The 'content' is the content retrieved from the URL. The content
is already decompressed or unzipped if necessary.
To PUT some content to a server that uses SSL and Basic authentication:
```python
import httplib2
h = httplib2.Http(".cache")
h.add_credentials('name', 'password')
(resp, content) = h.request("https://example.org/chapter/2",
"PUT", body="This is text",
headers={'content-type':'text/plain'} )
```
Use the Cache-Control: header to control how the caching operates.
```python
import httplib2
h = httplib2.Http(".cache")
(resp, content) = h.request("http://bitworking.org/", "GET")
...
(resp, content) = h.request("http://bitworking.org/", "GET",
headers={'cache-control':'no-cache'})
```
The first request will be cached and since this is a request
to bitworking.org it will be set to be cached for two hours,
because that is how I have my server configured. Any subsequent
GET to that URI will return the value from the on-disk cache
and no request will be made to the server. You can use the
Cache-Control: header to change the caches behavior and in
this example the second request adds the Cache-Control:
header with a value of 'no-cache' which tells the library
that the cached copy must not be used when handling this request.
More example usage can be found at:
* https://github.com/httplib2/httplib2/wiki/Examples
* https://github.com/httplib2/httplib2/wiki/Examples-Python3

View File

@@ -0,0 +1,19 @@
# Security Policy
## Supported Versions
master branch and latest release get priority support. You should expect all known problems fixed in master.
All other released versions receive security updates per request.
If you use some old version and can not upgrade for any or no reason, ask for security update release, most likely you will get it.
## Reporting a Vulnerability
Contact current maintainers. At 2020-05: temotor@gmail.com or https://t.me/temotor
If that doesn't work, open Github issue just asking for private communication channel.
This is volunteer maintained project, all issues are processed on best effort basis, no deadlines promised. Of course, security vulnerabilities get priority over regular issues.
You can expect fame in history or maybe you prefer anonymity - say what you prefer.
Thank you for responsible handling of security problems. Your attention and effort are appreciated.

View File

@@ -0,0 +1,12 @@
comment:
layout: "files"
require_changes: yes
coverage:
precision: 0
round: down
status:
project:
default:
target: auto
threshold: 2%

View File

@@ -0,0 +1,454 @@
% Template for a library manual section.
% PLEASE REMOVE THE COMMENTS AFTER USING THE TEMPLATE
%
% Complete documentation on the extended LaTeX markup used for Python
% documentation is available in ``Documenting Python'', which is part
% of the standard documentation for Python. It may be found online
% at:
%
% http://www.python.org/doc/current/doc/doc.html
% ==== 0. ====
% Copy this file to <mydir>/lib<mymodule>.tex, and edit that file
% according to the instructions below.
% ==== 1. ====
% The section prologue. Give the section a title and provide some
% meta-information. References to the module should use
% \refbimodindex, \refstmodindex, \refexmodindex or \refmodindex, as
% appropriate.
\section{\module{httplib2}
A comprehensive HTTP client library. }
% Choose one of these to specify the module module name. If there's
% an underscore in the name, use
% \declaremodule[modname]{...}{mod_name} instead.
%
\declaremodule{}{httplib2} % not standard, in Python
% Portability statement: Uncomment and fill in the parameter to specify the
% availability of the module. The parameter can be Unix, IRIX, SunOS, Mac,
% Windows, or lots of other stuff. When ``Mac'' is specified, the availability
% statement will say ``Macintosh'' and the Module Index may say ``Mac''.
% Please use a name that has already been used whenever applicable. If this
% is omitted, no availability statement is produced or implied.
%
% \platform{Unix}
% These apply to all modules, and may be given more than once:
\moduleauthor{Joe Gregorio}{joe@bitworking.org} % Author of the module code;
% omit if not known.
\sectionauthor{Joe Gregorio}{joe@bitworking.org} % Author of the documentation,
% even if not a module section.
% Leave at least one blank line after this, to simplify ad-hoc tools
% that are sometimes used to massage these files.
\modulesynopsis{A comprehensive HTTP client library, \module{httplib2} supports many features left out of other HTTP libraries.}
% ==== 2. ====
% Give a short overview of what the module does.
% If it is platform specific, mention this.
% Mention other important restrictions or general operating principles.
% For example:
The \module{httplib2} module is a comprehensive HTTP client library with the following features:
\begin{description}
\item[HTTP and HTTPS] HTTPS support is only available if the socket module was compiled with SSL support.
\item[Keep-Alive] Supports HTTP 1.1 Keep-Alive, keeping the socket open and performing multiple requests over the same connection if possible.
\item[Authentication] The following three types of HTTP Authentication are supported. These can be used over both HTTP and HTTPS.
\begin{itemize}
\item Digest
\item Basic
\item WSSE
\end{itemize}
\item[Caching]
The module can optionally operate with a private cache that understands the Cache-Control: header and uses both the ETag and Last-Modified cache validators.
\item[All Methods]
The module can handle any HTTP request method, not just GET and POST.
\item[Redirects]
Automatically follows 3XX redirects on GETs.
\item[Compression]
Handles both 'deflate' and 'gzip' types of compression.
\item[Proxies]
If the Socksipy module is installed then httplib2 can handle sock4, sock5 and http proxies.
\item[Lost update support]
Automatically adds back ETags into PUT requests to resources we have already cached. This implements Section 3.2 of Detecting the Lost Update Problem Using Unreserved Checkout
\end{description}
% ==== 3. ====
% List the public functions defined by the module. Begin with a
% standard phrase. You may also list the exceptions and other data
% items defined in the module, insofar as they are important for the
% user.
The \module{httplib2} module defines the following variables:
% ---- 3.2. ----
% Data items are described using a ``datadesc'' block. This has only
% one parameter: the item's name.
\begin{datadesc}{debuglevel}
The amount of debugging information to print. The default is 0.
\end{datadesc}
\begin{datadesc}{RETRIES}
A request will be tried 'RETRIES' times if it fails at the socket/connection level.
The default is 2.
\end{datadesc}
% --- 3.3. ---
% Exceptions are described using a ``excdesc'' block. This has only
% one parameter: the exception name. Exceptions defined as classes in
% the source code should be documented using this environment, but
% constructor parameters must be omitted.
The \module{httplib2} module may raise the following Exceptions. Note that
there is an option that turns exceptions into
normal responses with an HTTP status code indicating
an error occured. See \member{Http.force_exception_to_status_code}
\begin{excdesc}{HttpLib2Error}
The Base Exception for all exceptions raised by httplib2.
\end{excdesc}
\begin{excdesc}{RedirectMissingLocation}
A 3xx redirect response code was provided but no Location: header
was provided to point to the new location.
\end{excdesc}
\begin{excdesc}{RedirectLimit}
The maximum number of redirections was reached without coming to a final URI.
\end{excdesc}
\begin{excdesc}{ServerNotFoundError}
Unable to resolve the host name given.
\end{excdesc}
\begin{excdesc}{RelativeURIError}
A relative, as opposed to an absolute URI, was passed into request().
\end{excdesc}
\begin{excdesc}{FailedToDecompressContent}
The headers claimed that the content of the response was compressed but the
decompression algorithm applied to the content failed.
\end{excdesc}
\begin{excdesc}{UnimplementedDigestAuthOptionError}
The server requested a type of Digest authentication that we
are unfamiliar with.
\end{excdesc}
\begin{excdesc}{UnimplementedHmacDigestAuthOptionError}
The server requested a type of HMACDigest authentication that we
are unfamiliar with.
\end{excdesc}
% ---- 3.4. ----
% Other standard environments:
%
% classdesc - Python classes; same arguments are funcdesc
% methoddesc - methods, like funcdesc but has an optional parameter
% to give the type name: \begin{methoddesc}[mytype]{name}{args}
% By default, the type name will be the name of the
% last class defined using classdesc. The type name
% is required if the type is implemented in C (because
% there's no classdesc) or if the class isn't directly
% documented (if it's private).
% memberdesc - data members, like datadesc, but with an optional
% type name like methoddesc.
\begin{classdesc}{Http}{\optional{cache=None}, \optional{timeout=None}, \optional{proxy_info=None}}
The class that represents a client HTTP interface.
The \var{cache} parameter is either the name of a directory
to be used as a flat file cache, or it must an object that
implements the required caching interface.
The \var{timeout} parameter is the socket level timeout.
The \var{proxy_info} is an instance of \class{ProxyInfo} and is supplied
if a proxy is to be used. Note that the Socksipy module must be
installed for proxy support to work.
\end{classdesc}
\begin{classdesc}{Response}{info}
Response is a subclass of \class{dict} and instances of this
class are returned from calls
to Http.request. The \var{info} parameter is either
an \class{rfc822.Message} or an \class{httplib.HTTPResponse} object.
\end{classdesc}
\begin{classdesc}{FileCache}{dir_name, \optional{safe=safename}}
FileCache implements a Cache as a directory of files.
The \var{dir_name} parameter is
the name of the directory to use. If the directory does
not exist then FileCache attempts to create the directory.
The optional \var{safe} parameter is a funtion which generates
the cache filename for each URI. A FileCache object is
constructed and used for caching when you pass a directory name
into the constructor of \class{Http}.
\end{classdesc}
\begin{classdesc}{ProxyInfo}{proxy_type, proxy_host, proxy_port, \optional{proxy_rdns=None}, \optional{proxy_user=None}, \optional{proxy_pass=None}}
The parameter \var{proxy_type} must be set to one of socks.PROXY_TYPE_XXX
constants. The \var{proxy_host} and \var{proxy_port} must be set to the location
of the proxy. The optional \var{proxy_rdns} should be set to True if
the DNS server on the proxy should be used. The \var{proxy_user} and
\var{proxy_pass} are supplied when the proxy is protected by authentication.
\end{classdesc}
% If your module defines new object types (for a built-in module) or
% classes (for a module written in Python), you should list the
% methods and instance variables (if any) of each type or class in a
% separate subsection.
\subsection{Http Objects}
\label{http-objects}
% This label is generally useful for referencing this section, but is
% also used to give a filename when generating HTML.
Http objects have the following methods:
\begin{methoddesc}[Http]{request}{uri, \optional{method="GET", body=None, headers=None, redirections=DEFAULT_MAX_REDIRECTS, connection_type=None}}
Performs a single HTTP request.
The \var{uri} is the URI of the HTTP resource and can begin with either \code{http} or \code{https}. The value of \var{uri} must be an absolute URI.
The \var{method} is the HTTP method to perform, such as \code{GET}, \code{POST}, \code{DELETE}, etc. There is no restriction
on the methods allowed.
The \var{body} is the entity body to be sent with the request. It is a string
object.
Any extra headers that are to be sent with the request should be provided in the
\var{headers} dictionary.
The maximum number of redirect to follow before raising an exception is \var{redirections}. The default is 5.
The \var{connection_type} is the type of connection object to use. The supplied class
should implement the interface of httplib.HTTPConnection.
The return value is a tuple of (response, content), the first being and instance of the
\class{Response} class, the second being a string that contains the response entity body.
\end{methoddesc}
\begin{methoddesc}[Http]{add_credentials}{name, password, \optional{domain=None}}
Adds a name and password that will be used when a request
requires authentication. Supplying the optional \var{domain} name will
restrict these credentials to only be sent to the specified
domain. If \var{domain} is not specified then the given credentials will
be used to try to satisfy every HTTP 401 challenge.
\end{methoddesc}
\begin{methoddesc}[Http]{add_certificate}{key, cert, domain}
Add a \var{key} and \var{cert} that will be used for an SSL connection
to the specified domain. \var{keyfile} is the name of a PEM formatted
file that contains your private key. \var{certfile} is a PEM formatted certificate chain file.
\end{methoddesc}
\begin{methoddesc}[Http]{clear_credentials}{}
Remove all the names and passwords used for authentication.
\end{methoddesc}
\begin{memberdesc}[Http]{follow_redirects}
If \code{True}, which is the default, safe redirects are followed, where
safe means that the client is only doing a \code{GET} or \code{HEAD} on the
URI to which it is being redirected. If \code{False} then no redirects are followed.
Note that a False 'follow_redirects' takes precedence over a True 'follow_all_redirects'.
Another way of saying that is for 'follow_all_redirects' to have any affect, 'follow_redirects'
must be True.
\end{memberdesc}
\begin{memberdesc}[Http]{forward_authorization_headers}
If \code{False}, which is the default, then Authorization: headers are
stripped from redirects. If \code{True} then Authorization: headers are left
in place when following redirects. This parameter only applies if following
redirects is turned on. Note that turning this on could cause your credentials
to leak, so carefully consider the consequences.
\end{memberdesc}
\begin{memberdesc}[Http]{follow_all_redirects}
If \code{False}, which is the default, only safe redirects are followed, where
safe means that the client is only doing a \code{GET} or \code{HEAD} on the
URI to which it is being redirected. If \code{True} then all redirects are followed.
Note that a False 'follow_redirects' takes precedence over a True 'follow_all_redirects'.
Another way of saying that is for 'follow_all_redirects' to have any affect, 'follow_redirects'
must be True.
\end{memberdesc}
\begin{memberdesc}[Http]{force_exception_to_status_code}
If \code{True}, which is the default, then no \module{httplib2} exceptions will be thrown. Instead,
those error conditions will be turned into \class{Response} objects
that will be returned normally.
If \code{False}, then exceptions will be thrown.
\end{memberdesc}
\begin{memberdesc}[Http]{ignore_etag}
Defaults to \code{False}. If \code{True}, then any etags present in the cached response
are ignored when processing the current request, i.e. httplib2 does \strong{not} use
'if-match' for PUT or 'if-none-match' when GET or HEAD requests are made. This
is mainly to deal with broken servers which supply an etag, but change it capriciously.
\end{memberdesc}
\subsection{Cache Objects}
\label{cache-objects}
% This label is generally useful for referencing this section, but is
% also used to give a filename when generating HTML.
If you wish to supply your own caching implementation
then you will need to pass in an object that supports the
following methods. Note that the \module{memcache} module
supports this interface natively.
\begin{methoddesc}[Cache]{get}{key}
Takes a string \var{key} and returns the value as a string.
\end{methoddesc}
\begin{methoddesc}[Cache]{set}{key, value}
Takes a string \var{key} and \var{value} and stores it in the cache.
\end{methoddesc}
\begin{methoddesc}[Cache]{delete}{key}
Deletes the cached value stored at \var{key}. The value
of \var{key} is a string.
\end{methoddesc}
\subsection{Response Objects}
\label{response-objects}
% This label is generally useful for referencing this section, but is
% also used to give a filename when generating HTML.
Response objects are derived from \class{dict} and map
header names (lower case with the trailing colon removed)
to header values. In addition to the dict methods
a Response object also has:
\begin{memberdesc}[Response]{fromcache}
If \code{true} the the response was returned from the cache.
\end{memberdesc}
\begin{memberdesc}[Response]{version}
The version of HTTP that the server supports. A value
of 11 means '1.1'.
\end{memberdesc}
\begin{memberdesc}[Response]{status}
The numerical HTTP status code returned in the response.
\end{memberdesc}
\begin{memberdesc}[Response]{reason}
The human readable component of the HTTP response status code.
\end{memberdesc}
\begin{memberdesc}[Response]{previous}
If redirects are followed then the \class{Response} object returned
is just for the very last HTTP request and \var{previous} points to
the previous \class{Response} object. In this manner they form a chain
going back through the responses to the very first response.
Will be \code{None} if there are no previous respones.
\end{memberdesc}
The Response object also populates the header \code{content-location}, that
contains the URI that was ultimately requested. This is useful if
redirects were encountered, you can determine the ultimate URI that
the request was sent to. All Response objects contain this key value,
including \code{previous} responses so you can determine the entire
chain of redirects. If \member{Http.force_exception_to_status_code} is \code{True}
and the number of redirects has exceeded the number of allowed number
of redirects then the \class{Response} object will report the error
in the status code, but the complete chain of previous responses will
still be in tact.
% ==== 4. ====
% Now is probably a good time for a complete example. (Alternatively,
% an example giving the flavor of the module may be given before the
% detailed list of functions.)
\subsection{Examples \label{httplib2-example}}
To do a simple \code{GET} request just supply the absolute URI
of the resource:
\begin{verbatim}
import httplib2
h = httplib2.Http()
resp, content = h.request("http://bitworking.org/")
assert resp.status == 200
assert resp['content-type'] == 'text/html'
\end{verbatim}
Here is more complex example that does a PUT
of some text to a resource that requires authentication.
The Http instance also uses a file cache
in the directory \code{.cache}.
\begin{verbatim}
import httplib2
h = httplib2.Http(".cache")
h.add_credentials('name', 'password')
resp, content = h.request("https://example.org/chap/2",
"PUT", body="This is text",
headers={'content-type':'text/plain'} )
\end{verbatim}
Here is an example that connects to a server that
supports the Atom Publishing Protocol.
\begin{verbatim}
import httplib2
h = httplib2.Http()
h.add_credentials(myname, mypasswd)
h.follow_all_redirects = True
headers = {'Content-Type': 'application/atom+xml'}
body = """<?xml version="1.0" ?>
<entry xmlns="http://www.w3.org/2005/Atom">
<title>Atom-Powered Robots Run Amok</title>
<id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
<updated>2003-12-13T18:30:02Z</updated>
<author><name>John Doe</name></author>
<content>Some text.</content>
</entry>
"""
uri = "http://www.example.com/collection/"
resp, content = h.request(uri, "POST", body=body, headers=headers)
\end{verbatim}
% Note that there is no trailing ">>> " prompt shown.
Here is an example of providing data to an HTML form processor.
In this case we presume this is a POST form. We need to take our
data and format it as "application/x-www-form-urlencoded" data and use that as a
body for a POST request.
\begin{verbatim}
>>> import httplib2
>>> import urllib
>>> data = {'name': 'fred', 'address': '123 shady lane'}
>>> body = urllib.urlencode(data)
>>> body
'name=fred&address=123+shady+lane'
>>> h = httplib2.Http()
>>> resp, content = h.request("http://example.com", method="POST", body=body)
\end{verbatim}
% Note that there is no trailing ">>> " prompt shown.
Here is an example of using a proxy server:
\begin{verbatim}
import httplib2
import socks
httplib2.debuglevel=4
h = httplib2.Http(proxy_info = httplib2.ProxyInfo(socks.PROXY_TYPE_HTTP, 'localhost', 8000))
r,c = h.request("http://bitworking.org/news/")
\end{verbatim}

View File

@@ -0,0 +1,9 @@
[build-system]
requires = ["setuptools >= 40.8.0", "wheel"]
build-backend = "setuptools.build_meta"
[tool.black]
line-length = 121
[tool.check-manifest]
ignore = [".github/*", "script/*", "*.tex"]

View File

@@ -0,0 +1,63 @@
import base64
import re
import pyparsing as pp
from .error import *
UNQUOTE_PAIRS = re.compile(r"\\(.)")
unquote = lambda s, l, t: UNQUOTE_PAIRS.sub(r"\1", t[0][1:-1])
# https://tools.ietf.org/html/rfc7235#section-1.2
# https://tools.ietf.org/html/rfc7235#appendix-B
tchar = "!#$%&'*+-.^_`|~" + pp.nums + pp.alphas
token = pp.Word(tchar).setName("token")
token68 = pp.Combine(pp.Word("-._~+/" + pp.nums + pp.alphas) + pp.Optional(pp.Word("=").leaveWhitespace())).setName(
"token68"
)
quoted_string = pp.dblQuotedString.copy().setName("quoted-string").setParseAction(unquote)
auth_param_name = token.copy().setName("auth-param-name").addParseAction(pp.downcaseTokens)
auth_param = auth_param_name + pp.Suppress("=") + (quoted_string | token)
params = pp.Dict(pp.delimitedList(pp.Group(auth_param)))
scheme = token("scheme")
challenge = scheme + (params("params") | token68("token"))
authentication_info = params.copy()
www_authenticate = pp.delimitedList(pp.Group(challenge))
def _parse_authentication_info(headers, headername="authentication-info"):
"""https://tools.ietf.org/html/rfc7615
"""
header = headers.get(headername, "").strip()
if not header:
return {}
try:
parsed = authentication_info.parseString(header)
except pp.ParseException as ex:
# print(ex.explain(ex))
raise MalformedHeader(headername)
return parsed.asDict()
def _parse_www_authenticate(headers, headername="www-authenticate"):
"""Returns a dictionary of dictionaries, one dict per auth_scheme."""
header = headers.get(headername, "").strip()
if not header:
return {}
try:
parsed = www_authenticate.parseString(header)
except pp.ParseException as ex:
# print(ex.explain(ex))
raise MalformedHeader(headername)
retval = {
challenge["scheme"].lower(): challenge["params"].asDict()
if "params" in challenge
else {"token": challenge.get("token")}
for challenge in parsed
}
return retval

View File

@@ -0,0 +1,42 @@
"""Utilities for certificate management."""
import os
certifi_available = False
certifi_where = None
try:
from certifi import where as certifi_where
certifi_available = True
except ImportError:
pass
custom_ca_locater_available = False
custom_ca_locater_where = None
try:
from ca_certs_locater import get as custom_ca_locater_where
custom_ca_locater_available = True
except ImportError:
pass
BUILTIN_CA_CERTS = os.path.join(
os.path.dirname(os.path.abspath(__file__)), "cacerts.txt"
)
def where():
env = os.environ.get("HTTPLIB2_CA_CERTS")
if env is not None:
if os.path.isfile(env):
return env
else:
raise RuntimeError("Environment variable HTTPLIB2_CA_CERTS not a valid file")
if custom_ca_locater_available:
return custom_ca_locater_where()
if certifi_available:
return certifi_where()
return BUILTIN_CA_CERTS
if __name__ == "__main__":
print(where())

View File

@@ -0,0 +1,48 @@
# All exceptions raised here derive from HttpLib2Error
class HttpLib2Error(Exception):
pass
# Some exceptions can be caught and optionally
# be turned back into responses.
class HttpLib2ErrorWithResponse(HttpLib2Error):
def __init__(self, desc, response, content):
self.response = response
self.content = content
HttpLib2Error.__init__(self, desc)
class RedirectMissingLocation(HttpLib2ErrorWithResponse):
pass
class RedirectLimit(HttpLib2ErrorWithResponse):
pass
class FailedToDecompressContent(HttpLib2ErrorWithResponse):
pass
class UnimplementedDigestAuthOptionError(HttpLib2ErrorWithResponse):
pass
class UnimplementedHmacDigestAuthOptionError(HttpLib2ErrorWithResponse):
pass
class MalformedHeader(HttpLib2Error):
pass
class RelativeURIError(HttpLib2Error):
pass
class ServerNotFoundError(HttpLib2Error):
pass
class ProxiesUnavailableError(HttpLib2Error):
pass

View File

@@ -0,0 +1,123 @@
"""Converts an IRI to a URI."""
__author__ = "Joe Gregorio (joe@bitworking.org)"
__copyright__ = "Copyright 2006, Joe Gregorio"
__contributors__ = []
__version__ = "1.0.0"
__license__ = "MIT"
import urlparse
# Convert an IRI to a URI following the rules in RFC 3987
#
# The characters we need to enocde and escape are defined in the spec:
#
# iprivate = %xE000-F8FF / %xF0000-FFFFD / %x100000-10FFFD
# ucschar = %xA0-D7FF / %xF900-FDCF / %xFDF0-FFEF
# / %x10000-1FFFD / %x20000-2FFFD / %x30000-3FFFD
# / %x40000-4FFFD / %x50000-5FFFD / %x60000-6FFFD
# / %x70000-7FFFD / %x80000-8FFFD / %x90000-9FFFD
# / %xA0000-AFFFD / %xB0000-BFFFD / %xC0000-CFFFD
# / %xD0000-DFFFD / %xE1000-EFFFD
escape_range = [
(0xA0, 0xD7FF),
(0xE000, 0xF8FF),
(0xF900, 0xFDCF),
(0xFDF0, 0xFFEF),
(0x10000, 0x1FFFD),
(0x20000, 0x2FFFD),
(0x30000, 0x3FFFD),
(0x40000, 0x4FFFD),
(0x50000, 0x5FFFD),
(0x60000, 0x6FFFD),
(0x70000, 0x7FFFD),
(0x80000, 0x8FFFD),
(0x90000, 0x9FFFD),
(0xA0000, 0xAFFFD),
(0xB0000, 0xBFFFD),
(0xC0000, 0xCFFFD),
(0xD0000, 0xDFFFD),
(0xE1000, 0xEFFFD),
(0xF0000, 0xFFFFD),
(0x100000, 0x10FFFD),
]
def encode(c):
retval = c
i = ord(c)
for low, high in escape_range:
if i < low:
break
if i >= low and i <= high:
retval = "".join(["%%%2X" % ord(o) for o in c.encode("utf-8")])
break
return retval
def iri2uri(uri):
"""Convert an IRI to a URI. Note that IRIs must be
passed in a unicode strings. That is, do not utf-8 encode
the IRI before passing it into the function."""
if isinstance(uri, unicode):
(scheme, authority, path, query, fragment) = urlparse.urlsplit(uri)
authority = authority.encode("idna")
# For each character in 'ucschar' or 'iprivate'
# 1. encode as utf-8
# 2. then %-encode each octet of that utf-8
uri = urlparse.urlunsplit((scheme, authority, path, query, fragment))
uri = "".join([encode(c) for c in uri])
return uri
if __name__ == "__main__":
import unittest
class Test(unittest.TestCase):
def test_uris(self):
"""Test that URIs are invariant under the transformation."""
invariant = [
u"ftp://ftp.is.co.za/rfc/rfc1808.txt",
u"http://www.ietf.org/rfc/rfc2396.txt",
u"ldap://[2001:db8::7]/c=GB?objectClass?one",
u"mailto:John.Doe@example.com",
u"news:comp.infosystems.www.servers.unix",
u"tel:+1-816-555-1212",
u"telnet://192.0.2.16:80/",
u"urn:oasis:names:specification:docbook:dtd:xml:4.1.2",
]
for uri in invariant:
self.assertEqual(uri, iri2uri(uri))
def test_iri(self):
"""Test that the right type of escaping is done for each part of the URI."""
self.assertEqual(
"http://xn--o3h.com/%E2%98%84",
iri2uri(u"http://\N{COMET}.com/\N{COMET}"),
)
self.assertEqual(
"http://bitworking.org/?fred=%E2%98%84",
iri2uri(u"http://bitworking.org/?fred=\N{COMET}"),
)
self.assertEqual(
"http://bitworking.org/#%E2%98%84",
iri2uri(u"http://bitworking.org/#\N{COMET}"),
)
self.assertEqual("#%E2%98%84", iri2uri(u"#\N{COMET}"))
self.assertEqual(
"/fred?bar=%E2%98%9A#%E2%98%84",
iri2uri(u"/fred?bar=\N{BLACK LEFT POINTING INDEX}#\N{COMET}"),
)
self.assertEqual(
"/fred?bar=%E2%98%9A#%E2%98%84",
iri2uri(iri2uri(u"/fred?bar=\N{BLACK LEFT POINTING INDEX}#\N{COMET}")),
)
self.assertNotEqual(
"/fred?bar=%E2%98%9A#%E2%98%84",
iri2uri(
u"/fred?bar=\N{BLACK LEFT POINTING INDEX}#\N{COMET}".encode("utf-8")
),
)
unittest.main()

View File

@@ -0,0 +1,518 @@
"""SocksiPy - Python SOCKS module.
Version 1.00
Copyright 2006 Dan-Haim. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of Dan Haim nor the names of his contributors may be used
to endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY DAN HAIM "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
EVENT SHALL DAN HAIM OR HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMANGE.
This module provides a standard socket-like interface for Python
for tunneling connections through SOCKS proxies.
Minor modifications made by Christopher Gilbert (http://motomastyle.com/) for
use in PyLoris (http://pyloris.sourceforge.net/).
Minor modifications made by Mario Vilas (http://breakingcode.wordpress.com/)
mainly to merge bug fixes found in Sourceforge.
"""
import base64
import socket
import struct
import sys
if getattr(socket, "socket", None) is None:
raise ImportError("socket.socket missing, proxy support unusable")
PROXY_TYPE_SOCKS4 = 1
PROXY_TYPE_SOCKS5 = 2
PROXY_TYPE_HTTP = 3
PROXY_TYPE_HTTP_NO_TUNNEL = 4
_defaultproxy = None
_orgsocket = socket.socket
class ProxyError(Exception):
pass
class GeneralProxyError(ProxyError):
pass
class Socks5AuthError(ProxyError):
pass
class Socks5Error(ProxyError):
pass
class Socks4Error(ProxyError):
pass
class HTTPError(ProxyError):
pass
_generalerrors = (
"success",
"invalid data",
"not connected",
"not available",
"bad proxy type",
"bad input",
)
_socks5errors = (
"succeeded",
"general SOCKS server failure",
"connection not allowed by ruleset",
"Network unreachable",
"Host unreachable",
"Connection refused",
"TTL expired",
"Command not supported",
"Address type not supported",
"Unknown error",
)
_socks5autherrors = (
"succeeded",
"authentication is required",
"all offered authentication methods were rejected",
"unknown username or invalid password",
"unknown error",
)
_socks4errors = (
"request granted",
"request rejected or failed",
"request rejected because SOCKS server cannot connect to identd on the client",
"request rejected because the client program and identd report different "
"user-ids",
"unknown error",
)
def setdefaultproxy(
proxytype=None, addr=None, port=None, rdns=True, username=None, password=None
):
"""setdefaultproxy(proxytype, addr[, port[, rdns[, username[, password]]]])
Sets a default proxy which all further socksocket objects will use,
unless explicitly changed.
"""
global _defaultproxy
_defaultproxy = (proxytype, addr, port, rdns, username, password)
def wrapmodule(module):
"""wrapmodule(module)
Attempts to replace a module's socket library with a SOCKS socket. Must set
a default proxy using setdefaultproxy(...) first.
This will only work on modules that import socket directly into the
namespace;
most of the Python Standard Library falls into this category.
"""
if _defaultproxy != None:
module.socket.socket = socksocket
else:
raise GeneralProxyError((4, "no proxy specified"))
class socksocket(socket.socket):
"""socksocket([family[, type[, proto]]]) -> socket object
Open a SOCKS enabled socket. The parameters are the same as
those of the standard socket init. In order for SOCKS to work,
you must specify family=AF_INET, type=SOCK_STREAM and proto=0.
"""
def __init__(
self, family=socket.AF_INET, type=socket.SOCK_STREAM, proto=0, _sock=None
):
_orgsocket.__init__(self, family, type, proto, _sock)
if _defaultproxy != None:
self.__proxy = _defaultproxy
else:
self.__proxy = (None, None, None, None, None, None)
self.__proxysockname = None
self.__proxypeername = None
self.__httptunnel = True
def __recvall(self, count):
"""__recvall(count) -> data
Receive EXACTLY the number of bytes requested from the socket.
Blocks until the required number of bytes have been received.
"""
data = self.recv(count)
while len(data) < count:
d = self.recv(count - len(data))
if not d:
raise GeneralProxyError((0, "connection closed unexpectedly"))
data = data + d
return data
def sendall(self, content, *args):
""" override socket.socket.sendall method to rewrite the header
for non-tunneling proxies if needed
"""
if not self.__httptunnel:
content = self.__rewriteproxy(content)
return super(socksocket, self).sendall(content, *args)
def __rewriteproxy(self, header):
""" rewrite HTTP request headers to support non-tunneling proxies
(i.e. those which do not support the CONNECT method).
This only works for HTTP (not HTTPS) since HTTPS requires tunneling.
"""
host, endpt = None, None
hdrs = header.split("\r\n")
for hdr in hdrs:
if hdr.lower().startswith("host:"):
host = hdr
elif hdr.lower().startswith("get") or hdr.lower().startswith("post"):
endpt = hdr
if host and endpt:
hdrs.remove(host)
hdrs.remove(endpt)
host = host.split(" ")[1]
endpt = endpt.split(" ")
if self.__proxy[4] != None and self.__proxy[5] != None:
hdrs.insert(0, self.__getauthheader())
hdrs.insert(0, "Host: %s" % host)
hdrs.insert(0, "%s http://%s%s %s" % (endpt[0], host, endpt[1], endpt[2]))
return "\r\n".join(hdrs)
def __getauthheader(self):
auth = self.__proxy[4] + ":" + self.__proxy[5]
return "Proxy-Authorization: Basic " + base64.b64encode(auth)
def setproxy(
self,
proxytype=None,
addr=None,
port=None,
rdns=True,
username=None,
password=None,
headers=None,
):
"""setproxy(proxytype, addr[, port[, rdns[, username[, password]]]])
Sets the proxy to be used.
proxytype - The type of the proxy to be used. Three types
are supported: PROXY_TYPE_SOCKS4 (including socks4a),
PROXY_TYPE_SOCKS5 and PROXY_TYPE_HTTP
addr - The address of the server (IP or DNS).
port - The port of the server. Defaults to 1080 for SOCKS
servers and 8080 for HTTP proxy servers.
rdns - Should DNS queries be preformed on the remote side
(rather than the local side). The default is True.
Note: This has no effect with SOCKS4 servers.
username - Username to authenticate with to the server.
The default is no authentication.
password - Password to authenticate with to the server.
Only relevant when username is also provided.
headers - Additional or modified headers for the proxy connect
request.
"""
self.__proxy = (
proxytype,
addr,
port,
rdns,
username.encode() if username else None,
password.encode() if password else None,
headers,
)
def __negotiatesocks5(self, destaddr, destport):
"""__negotiatesocks5(self,destaddr,destport)
Negotiates a connection through a SOCKS5 server.
"""
# First we'll send the authentication packages we support.
if (self.__proxy[4] != None) and (self.__proxy[5] != None):
# The username/password details were supplied to the
# setproxy method so we support the USERNAME/PASSWORD
# authentication (in addition to the standard none).
self.sendall(struct.pack("BBBB", 0x05, 0x02, 0x00, 0x02))
else:
# No username/password were entered, therefore we
# only support connections with no authentication.
self.sendall(struct.pack("BBB", 0x05, 0x01, 0x00))
# We'll receive the server's response to determine which
# method was selected
chosenauth = self.__recvall(2)
if chosenauth[0:1] != chr(0x05).encode():
self.close()
raise GeneralProxyError((1, _generalerrors[1]))
# Check the chosen authentication method
if chosenauth[1:2] == chr(0x00).encode():
# No authentication is required
pass
elif chosenauth[1:2] == chr(0x02).encode():
# Okay, we need to perform a basic username/password
# authentication.
self.sendall(
chr(0x01).encode()
+ chr(len(self.__proxy[4]))
+ self.__proxy[4]
+ chr(len(self.__proxy[5]))
+ self.__proxy[5]
)
authstat = self.__recvall(2)
if authstat[0:1] != chr(0x01).encode():
# Bad response
self.close()
raise GeneralProxyError((1, _generalerrors[1]))
if authstat[1:2] != chr(0x00).encode():
# Authentication failed
self.close()
raise Socks5AuthError((3, _socks5autherrors[3]))
# Authentication succeeded
else:
# Reaching here is always bad
self.close()
if chosenauth[1] == chr(0xFF).encode():
raise Socks5AuthError((2, _socks5autherrors[2]))
else:
raise GeneralProxyError((1, _generalerrors[1]))
# Now we can request the actual connection
req = struct.pack("BBB", 0x05, 0x01, 0x00)
# If the given destination address is an IP address, we'll
# use the IPv4 address request even if remote resolving was specified.
try:
ipaddr = socket.inet_aton(destaddr)
req = req + chr(0x01).encode() + ipaddr
except socket.error:
# Well it's not an IP number, so it's probably a DNS name.
if self.__proxy[3]:
# Resolve remotely
ipaddr = None
req = (
req
+ chr(0x03).encode()
+ chr(len(destaddr)).encode()
+ destaddr.encode()
)
else:
# Resolve locally
ipaddr = socket.inet_aton(socket.gethostbyname(destaddr))
req = req + chr(0x01).encode() + ipaddr
req = req + struct.pack(">H", destport)
self.sendall(req)
# Get the response
resp = self.__recvall(4)
if resp[0:1] != chr(0x05).encode():
self.close()
raise GeneralProxyError((1, _generalerrors[1]))
elif resp[1:2] != chr(0x00).encode():
# Connection failed
self.close()
if ord(resp[1:2]) <= 8:
raise Socks5Error((ord(resp[1:2]), _socks5errors[ord(resp[1:2])]))
else:
raise Socks5Error((9, _socks5errors[9]))
# Get the bound address/port
elif resp[3:4] == chr(0x01).encode():
boundaddr = self.__recvall(4)
elif resp[3:4] == chr(0x03).encode():
resp = resp + self.recv(1)
boundaddr = self.__recvall(ord(resp[4:5]))
else:
self.close()
raise GeneralProxyError((1, _generalerrors[1]))
boundport = struct.unpack(">H", self.__recvall(2))[0]
self.__proxysockname = (boundaddr, boundport)
if ipaddr != None:
self.__proxypeername = (socket.inet_ntoa(ipaddr), destport)
else:
self.__proxypeername = (destaddr, destport)
def getproxysockname(self):
"""getsockname() -> address info
Returns the bound IP address and port number at the proxy.
"""
return self.__proxysockname
def getproxypeername(self):
"""getproxypeername() -> address info
Returns the IP and port number of the proxy.
"""
return _orgsocket.getpeername(self)
def getpeername(self):
"""getpeername() -> address info
Returns the IP address and port number of the destination
machine (note: getproxypeername returns the proxy)
"""
return self.__proxypeername
def __negotiatesocks4(self, destaddr, destport):
"""__negotiatesocks4(self,destaddr,destport)
Negotiates a connection through a SOCKS4 server.
"""
# Check if the destination address provided is an IP address
rmtrslv = False
try:
ipaddr = socket.inet_aton(destaddr)
except socket.error:
# It's a DNS name. Check where it should be resolved.
if self.__proxy[3]:
ipaddr = struct.pack("BBBB", 0x00, 0x00, 0x00, 0x01)
rmtrslv = True
else:
ipaddr = socket.inet_aton(socket.gethostbyname(destaddr))
# Construct the request packet
req = struct.pack(">BBH", 0x04, 0x01, destport) + ipaddr
# The username parameter is considered userid for SOCKS4
if self.__proxy[4] != None:
req = req + self.__proxy[4]
req = req + chr(0x00).encode()
# DNS name if remote resolving is required
# NOTE: This is actually an extension to the SOCKS4 protocol
# called SOCKS4A and may not be supported in all cases.
if rmtrslv:
req = req + destaddr + chr(0x00).encode()
self.sendall(req)
# Get the response from the server
resp = self.__recvall(8)
if resp[0:1] != chr(0x00).encode():
# Bad data
self.close()
raise GeneralProxyError((1, _generalerrors[1]))
if resp[1:2] != chr(0x5A).encode():
# Server returned an error
self.close()
if ord(resp[1:2]) in (91, 92, 93):
self.close()
raise Socks4Error((ord(resp[1:2]), _socks4errors[ord(resp[1:2]) - 90]))
else:
raise Socks4Error((94, _socks4errors[4]))
# Get the bound address/port
self.__proxysockname = (
socket.inet_ntoa(resp[4:]),
struct.unpack(">H", resp[2:4])[0],
)
if rmtrslv != None:
self.__proxypeername = (socket.inet_ntoa(ipaddr), destport)
else:
self.__proxypeername = (destaddr, destport)
def __negotiatehttp(self, destaddr, destport):
"""__negotiatehttp(self,destaddr,destport)
Negotiates a connection through an HTTP server.
"""
# If we need to resolve locally, we do this now
if not self.__proxy[3]:
addr = socket.gethostbyname(destaddr)
else:
addr = destaddr
headers = ["CONNECT ", addr, ":", str(destport), " HTTP/1.1\r\n"]
wrote_host_header = False
wrote_auth_header = False
if self.__proxy[6] != None:
for key, val in self.__proxy[6].iteritems():
headers += [key, ": ", val, "\r\n"]
wrote_host_header = key.lower() == "host"
wrote_auth_header = key.lower() == "proxy-authorization"
if not wrote_host_header:
headers += ["Host: ", destaddr, "\r\n"]
if not wrote_auth_header:
if self.__proxy[4] != None and self.__proxy[5] != None:
headers += [self.__getauthheader(), "\r\n"]
headers.append("\r\n")
self.sendall("".join(headers).encode())
# We read the response until we get the string "\r\n\r\n"
resp = self.recv(1)
while resp.find("\r\n\r\n".encode()) == -1:
resp = resp + self.recv(1)
# We just need the first line to check if the connection
# was successful
statusline = resp.splitlines()[0].split(" ".encode(), 2)
if statusline[0] not in ("HTTP/1.0".encode(), "HTTP/1.1".encode()):
self.close()
raise GeneralProxyError((1, _generalerrors[1]))
try:
statuscode = int(statusline[1])
except ValueError:
self.close()
raise GeneralProxyError((1, _generalerrors[1]))
if statuscode != 200:
self.close()
raise HTTPError((statuscode, statusline[2]))
self.__proxysockname = ("0.0.0.0", 0)
self.__proxypeername = (addr, destport)
def connect(self, destpair):
"""connect(self, despair)
Connects to the specified destination through a proxy.
destpar - A tuple of the IP/DNS address and the port number.
(identical to socket's connect).
To select the proxy server use setproxy().
"""
# Do a minimal input check first
if (
(not type(destpair) in (list, tuple))
or (len(destpair) < 2)
or (not isinstance(destpair[0], basestring))
or (type(destpair[1]) != int)
):
raise GeneralProxyError((5, _generalerrors[5]))
if self.__proxy[0] == PROXY_TYPE_SOCKS5:
if self.__proxy[2] != None:
portnum = self.__proxy[2]
else:
portnum = 1080
_orgsocket.connect(self, (self.__proxy[1], portnum))
self.__negotiatesocks5(destpair[0], destpair[1])
elif self.__proxy[0] == PROXY_TYPE_SOCKS4:
if self.__proxy[2] != None:
portnum = self.__proxy[2]
else:
portnum = 1080
_orgsocket.connect(self, (self.__proxy[1], portnum))
self.__negotiatesocks4(destpair[0], destpair[1])
elif self.__proxy[0] == PROXY_TYPE_HTTP:
if self.__proxy[2] != None:
portnum = self.__proxy[2]
else:
portnum = 8080
_orgsocket.connect(self, (self.__proxy[1], portnum))
self.__negotiatehttp(destpair[0], destpair[1])
elif self.__proxy[0] == PROXY_TYPE_HTTP_NO_TUNNEL:
if self.__proxy[2] != None:
portnum = self.__proxy[2]
else:
portnum = 8080
_orgsocket.connect(self, (self.__proxy[1], portnum))
if destpair[1] == 443:
self.__negotiatehttp(destpair[0], destpair[1])
else:
self.__httptunnel = False
elif self.__proxy[0] == None:
_orgsocket.connect(self, (destpair[0], destpair[1]))
else:
raise GeneralProxyError((4, _generalerrors[4]))

View File

@@ -0,0 +1,68 @@
httplib2 for Python 3
This directory contains a port of httplib2 to Python 3. As you may
know, Python 3 is not backward-compatible with Python 2. The biggest
change in Python 3 (that affects httplib2) is the distinction between
bytes and strings.
To successfully use http2lib for Python 3, you absolutely must
understand the following sentence:
** THE RESPONSE HEADERS ARE STRINGS, BUT THE CONTENT BODY IS BYTES **
Example:
>>> import httplib2, pprint
>>> h = httplib2.Http(".cache")
>>> (resp_headers, content) = h.request("http://example.org/", "GET")
>>> pprint.pprint(resp_headers)
{'accept-ranges': 'bytes',
'connection': 'close',
'content-length': '438',
'content-location': 'http://example.org/',
'content-type': 'text/html; charset=UTF-8',
'date': 'Fri, 29 May 2009 03:57:29 GMT',
'etag': '"b80f4-1b6-80bfd280"',
'last-modified': 'Tue, 15 Nov 2005 13:24:10 GMT',
'server': 'Apache/2.2.3 (CentOS)',
'status': '200'}
>>> type(content)
<class 'bytes'>
>>> content[:49]
b'<HTML>\r\n<HEAD>\r\n <TITLE>Example Web Page</TITLE>'
Further reading:
* http://diveintopython3.org/strings.html
* http://docs.python.org/3.0/whatsnew/3.0.html#text-vs-data-instead-of-unicode-vs-8-bit
* http://docs.python.org/3.0/howto/unicode.html
--------------------------------------------------------------------
Httplib2 Software License
Copyright (c) 2006 by Joe Gregorio
Copyright (c) 2009 by Mark Pilgrim
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,69 @@
import base64
import re
import pyparsing as pp
from .error import *
try: # pyparsing>=3.0.0
downcaseTokens = pp.common.downcaseTokens
except AttributeError:
downcaseTokens = pp.downcaseTokens
UNQUOTE_PAIRS = re.compile(r"\\(.)")
unquote = lambda s, l, t: UNQUOTE_PAIRS.sub(r"\1", t[0][1:-1])
# https://tools.ietf.org/html/rfc7235#section-1.2
# https://tools.ietf.org/html/rfc7235#appendix-B
tchar = "!#$%&'*+-.^_`|~" + pp.nums + pp.alphas
token = pp.Word(tchar).setName("token")
token68 = pp.Combine(pp.Word("-._~+/" + pp.nums + pp.alphas) + pp.Optional(pp.Word("=").leaveWhitespace())).setName(
"token68"
)
quoted_string = pp.dblQuotedString.copy().setName("quoted-string").setParseAction(unquote)
auth_param_name = token.copy().setName("auth-param-name").addParseAction(downcaseTokens)
auth_param = auth_param_name + pp.Suppress("=") + (quoted_string | token)
params = pp.Dict(pp.delimitedList(pp.Group(auth_param)))
scheme = token("scheme")
challenge = scheme + (params("params") | token68("token"))
authentication_info = params.copy()
www_authenticate = pp.delimitedList(pp.Group(challenge))
def _parse_authentication_info(headers, headername="authentication-info"):
"""https://tools.ietf.org/html/rfc7615
"""
header = headers.get(headername, "").strip()
if not header:
return {}
try:
parsed = authentication_info.parseString(header)
except pp.ParseException as ex:
# print(ex.explain(ex))
raise MalformedHeader(headername)
return parsed.asDict()
def _parse_www_authenticate(headers, headername="www-authenticate"):
"""Returns a dictionary of dictionaries, one dict per auth_scheme."""
header = headers.get(headername, "").strip()
if not header:
return {}
try:
parsed = www_authenticate.parseString(header)
except pp.ParseException as ex:
# print(ex.explain(ex))
raise MalformedHeader(headername)
retval = {
challenge["scheme"].lower(): challenge["params"].asDict()
if "params" in challenge
else {"token": challenge.get("token")}
for challenge in parsed
}
return retval

View File

@@ -0,0 +1,42 @@
"""Utilities for certificate management."""
import os
certifi_available = False
certifi_where = None
try:
from certifi import where as certifi_where
certifi_available = True
except ImportError:
pass
custom_ca_locater_available = False
custom_ca_locater_where = None
try:
from ca_certs_locater import get as custom_ca_locater_where
custom_ca_locater_available = True
except ImportError:
pass
BUILTIN_CA_CERTS = os.path.join(
os.path.dirname(os.path.abspath(__file__)), "cacerts.txt"
)
def where():
env = os.environ.get("HTTPLIB2_CA_CERTS")
if env is not None:
if os.path.isfile(env):
return env
else:
raise RuntimeError("Environment variable HTTPLIB2_CA_CERTS not a valid file")
if custom_ca_locater_available:
return custom_ca_locater_where()
if certifi_available:
return certifi_where()
return BUILTIN_CA_CERTS
if __name__ == "__main__":
print(where())

View File

@@ -0,0 +1,48 @@
# All exceptions raised here derive from HttpLib2Error
class HttpLib2Error(Exception):
pass
# Some exceptions can be caught and optionally
# be turned back into responses.
class HttpLib2ErrorWithResponse(HttpLib2Error):
def __init__(self, desc, response, content):
self.response = response
self.content = content
HttpLib2Error.__init__(self, desc)
class RedirectMissingLocation(HttpLib2ErrorWithResponse):
pass
class RedirectLimit(HttpLib2ErrorWithResponse):
pass
class FailedToDecompressContent(HttpLib2ErrorWithResponse):
pass
class UnimplementedDigestAuthOptionError(HttpLib2ErrorWithResponse):
pass
class UnimplementedHmacDigestAuthOptionError(HttpLib2ErrorWithResponse):
pass
class MalformedHeader(HttpLib2Error):
pass
class RelativeURIError(HttpLib2Error):
pass
class ServerNotFoundError(HttpLib2Error):
pass
class ProxiesUnavailableError(HttpLib2Error):
pass

View File

@@ -0,0 +1,124 @@
# -*- coding: utf-8 -*-
"""Converts an IRI to a URI."""
__author__ = "Joe Gregorio (joe@bitworking.org)"
__copyright__ = "Copyright 2006, Joe Gregorio"
__contributors__ = []
__version__ = "1.0.0"
__license__ = "MIT"
import urllib.parse
# Convert an IRI to a URI following the rules in RFC 3987
#
# The characters we need to enocde and escape are defined in the spec:
#
# iprivate = %xE000-F8FF / %xF0000-FFFFD / %x100000-10FFFD
# ucschar = %xA0-D7FF / %xF900-FDCF / %xFDF0-FFEF
# / %x10000-1FFFD / %x20000-2FFFD / %x30000-3FFFD
# / %x40000-4FFFD / %x50000-5FFFD / %x60000-6FFFD
# / %x70000-7FFFD / %x80000-8FFFD / %x90000-9FFFD
# / %xA0000-AFFFD / %xB0000-BFFFD / %xC0000-CFFFD
# / %xD0000-DFFFD / %xE1000-EFFFD
escape_range = [
(0xA0, 0xD7FF),
(0xE000, 0xF8FF),
(0xF900, 0xFDCF),
(0xFDF0, 0xFFEF),
(0x10000, 0x1FFFD),
(0x20000, 0x2FFFD),
(0x30000, 0x3FFFD),
(0x40000, 0x4FFFD),
(0x50000, 0x5FFFD),
(0x60000, 0x6FFFD),
(0x70000, 0x7FFFD),
(0x80000, 0x8FFFD),
(0x90000, 0x9FFFD),
(0xA0000, 0xAFFFD),
(0xB0000, 0xBFFFD),
(0xC0000, 0xCFFFD),
(0xD0000, 0xDFFFD),
(0xE1000, 0xEFFFD),
(0xF0000, 0xFFFFD),
(0x100000, 0x10FFFD),
]
def encode(c):
retval = c
i = ord(c)
for low, high in escape_range:
if i < low:
break
if i >= low and i <= high:
retval = "".join(["%%%2X" % o for o in c.encode("utf-8")])
break
return retval
def iri2uri(uri):
"""Convert an IRI to a URI. Note that IRIs must be
passed in a unicode strings. That is, do not utf-8 encode
the IRI before passing it into the function."""
if isinstance(uri, str):
(scheme, authority, path, query, fragment) = urllib.parse.urlsplit(uri)
authority = authority.encode("idna").decode("utf-8")
# For each character in 'ucschar' or 'iprivate'
# 1. encode as utf-8
# 2. then %-encode each octet of that utf-8
uri = urllib.parse.urlunsplit((scheme, authority, path, query, fragment))
uri = "".join([encode(c) for c in uri])
return uri
if __name__ == "__main__":
import unittest
class Test(unittest.TestCase):
def test_uris(self):
"""Test that URIs are invariant under the transformation."""
invariant = [
"ftp://ftp.is.co.za/rfc/rfc1808.txt",
"http://www.ietf.org/rfc/rfc2396.txt",
"ldap://[2001:db8::7]/c=GB?objectClass?one",
"mailto:John.Doe@example.com",
"news:comp.infosystems.www.servers.unix",
"tel:+1-816-555-1212",
"telnet://192.0.2.16:80/",
"urn:oasis:names:specification:docbook:dtd:xml:4.1.2",
]
for uri in invariant:
self.assertEqual(uri, iri2uri(uri))
def test_iri(self):
"""Test that the right type of escaping is done for each part of the URI."""
self.assertEqual(
"http://xn--o3h.com/%E2%98%84",
iri2uri("http://\N{COMET}.com/\N{COMET}"),
)
self.assertEqual(
"http://bitworking.org/?fred=%E2%98%84",
iri2uri("http://bitworking.org/?fred=\N{COMET}"),
)
self.assertEqual(
"http://bitworking.org/#%E2%98%84",
iri2uri("http://bitworking.org/#\N{COMET}"),
)
self.assertEqual("#%E2%98%84", iri2uri("#\N{COMET}"))
self.assertEqual(
"/fred?bar=%E2%98%9A#%E2%98%84",
iri2uri("/fred?bar=\N{BLACK LEFT POINTING INDEX}#\N{COMET}"),
)
self.assertEqual(
"/fred?bar=%E2%98%9A#%E2%98%84",
iri2uri(iri2uri("/fred?bar=\N{BLACK LEFT POINTING INDEX}#\N{COMET}")),
)
self.assertNotEqual(
"/fred?bar=%E2%98%9A#%E2%98%84",
iri2uri(
"/fred?bar=\N{BLACK LEFT POINTING INDEX}#\N{COMET}".encode("utf-8")
),
)
unittest.main()

View File

@@ -0,0 +1,518 @@
"""SocksiPy - Python SOCKS module.
Version 1.00
Copyright 2006 Dan-Haim. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of Dan Haim nor the names of his contributors may be used
to endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY DAN HAIM "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
EVENT SHALL DAN HAIM OR HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMANGE.
This module provides a standard socket-like interface for Python
for tunneling connections through SOCKS proxies.
Minor modifications made by Christopher Gilbert (http://motomastyle.com/) for
use in PyLoris (http://pyloris.sourceforge.net/).
Minor modifications made by Mario Vilas (http://breakingcode.wordpress.com/)
mainly to merge bug fixes found in Sourceforge.
"""
import base64
import socket
import struct
import sys
if getattr(socket, "socket", None) is None:
raise ImportError("socket.socket missing, proxy support unusable")
PROXY_TYPE_SOCKS4 = 1
PROXY_TYPE_SOCKS5 = 2
PROXY_TYPE_HTTP = 3
PROXY_TYPE_HTTP_NO_TUNNEL = 4
_defaultproxy = None
_orgsocket = socket.socket
class ProxyError(Exception):
pass
class GeneralProxyError(ProxyError):
pass
class Socks5AuthError(ProxyError):
pass
class Socks5Error(ProxyError):
pass
class Socks4Error(ProxyError):
pass
class HTTPError(ProxyError):
pass
_generalerrors = (
"success",
"invalid data",
"not connected",
"not available",
"bad proxy type",
"bad input",
)
_socks5errors = (
"succeeded",
"general SOCKS server failure",
"connection not allowed by ruleset",
"Network unreachable",
"Host unreachable",
"Connection refused",
"TTL expired",
"Command not supported",
"Address type not supported",
"Unknown error",
)
_socks5autherrors = (
"succeeded",
"authentication is required",
"all offered authentication methods were rejected",
"unknown username or invalid password",
"unknown error",
)
_socks4errors = (
"request granted",
"request rejected or failed",
"request rejected because SOCKS server cannot connect to identd on the client",
"request rejected because the client program and identd report different "
"user-ids",
"unknown error",
)
def setdefaultproxy(
proxytype=None, addr=None, port=None, rdns=True, username=None, password=None
):
"""setdefaultproxy(proxytype, addr[, port[, rdns[, username[, password]]]])
Sets a default proxy which all further socksocket objects will use,
unless explicitly changed.
"""
global _defaultproxy
_defaultproxy = (proxytype, addr, port, rdns, username, password)
def wrapmodule(module):
"""wrapmodule(module)
Attempts to replace a module's socket library with a SOCKS socket. Must set
a default proxy using setdefaultproxy(...) first.
This will only work on modules that import socket directly into the
namespace;
most of the Python Standard Library falls into this category.
"""
if _defaultproxy != None:
module.socket.socket = socksocket
else:
raise GeneralProxyError((4, "no proxy specified"))
class socksocket(socket.socket):
"""socksocket([family[, type[, proto]]]) -> socket object
Open a SOCKS enabled socket. The parameters are the same as
those of the standard socket init. In order for SOCKS to work,
you must specify family=AF_INET, type=SOCK_STREAM and proto=0.
"""
def __init__(
self, family=socket.AF_INET, type=socket.SOCK_STREAM, proto=0, _sock=None
):
_orgsocket.__init__(self, family, type, proto, _sock)
if _defaultproxy != None:
self.__proxy = _defaultproxy
else:
self.__proxy = (None, None, None, None, None, None)
self.__proxysockname = None
self.__proxypeername = None
self.__httptunnel = True
def __recvall(self, count):
"""__recvall(count) -> data
Receive EXACTLY the number of bytes requested from the socket.
Blocks until the required number of bytes have been received.
"""
data = self.recv(count)
while len(data) < count:
d = self.recv(count - len(data))
if not d:
raise GeneralProxyError((0, "connection closed unexpectedly"))
data = data + d
return data
def sendall(self, content, *args):
""" override socket.socket.sendall method to rewrite the header
for non-tunneling proxies if needed
"""
if not self.__httptunnel:
content = self.__rewriteproxy(content)
return super(socksocket, self).sendall(content, *args)
def __rewriteproxy(self, header):
""" rewrite HTTP request headers to support non-tunneling proxies
(i.e. those which do not support the CONNECT method).
This only works for HTTP (not HTTPS) since HTTPS requires tunneling.
"""
host, endpt = None, None
hdrs = header.split("\r\n")
for hdr in hdrs:
if hdr.lower().startswith("host:"):
host = hdr
elif hdr.lower().startswith("get") or hdr.lower().startswith("post"):
endpt = hdr
if host and endpt:
hdrs.remove(host)
hdrs.remove(endpt)
host = host.split(" ")[1]
endpt = endpt.split(" ")
if self.__proxy[4] != None and self.__proxy[5] != None:
hdrs.insert(0, self.__getauthheader())
hdrs.insert(0, "Host: %s" % host)
hdrs.insert(0, "%s http://%s%s %s" % (endpt[0], host, endpt[1], endpt[2]))
return "\r\n".join(hdrs)
def __getauthheader(self):
auth = self.__proxy[4] + b":" + self.__proxy[5]
return "Proxy-Authorization: Basic " + base64.b64encode(auth).decode()
def setproxy(
self,
proxytype=None,
addr=None,
port=None,
rdns=True,
username=None,
password=None,
headers=None,
):
"""setproxy(proxytype, addr[, port[, rdns[, username[, password]]]])
Sets the proxy to be used.
proxytype - The type of the proxy to be used. Three types
are supported: PROXY_TYPE_SOCKS4 (including socks4a),
PROXY_TYPE_SOCKS5 and PROXY_TYPE_HTTP
addr - The address of the server (IP or DNS).
port - The port of the server. Defaults to 1080 for SOCKS
servers and 8080 for HTTP proxy servers.
rdns - Should DNS queries be preformed on the remote side
(rather than the local side). The default is True.
Note: This has no effect with SOCKS4 servers.
username - Username to authenticate with to the server.
The default is no authentication.
password - Password to authenticate with to the server.
Only relevant when username is also provided.
headers - Additional or modified headers for the proxy connect
request.
"""
self.__proxy = (
proxytype,
addr,
port,
rdns,
username.encode() if username else None,
password.encode() if password else None,
headers,
)
def __negotiatesocks5(self, destaddr, destport):
"""__negotiatesocks5(self,destaddr,destport)
Negotiates a connection through a SOCKS5 server.
"""
# First we'll send the authentication packages we support.
if (self.__proxy[4] != None) and (self.__proxy[5] != None):
# The username/password details were supplied to the
# setproxy method so we support the USERNAME/PASSWORD
# authentication (in addition to the standard none).
self.sendall(struct.pack("BBBB", 0x05, 0x02, 0x00, 0x02))
else:
# No username/password were entered, therefore we
# only support connections with no authentication.
self.sendall(struct.pack("BBB", 0x05, 0x01, 0x00))
# We'll receive the server's response to determine which
# method was selected
chosenauth = self.__recvall(2)
if chosenauth[0:1] != chr(0x05).encode():
self.close()
raise GeneralProxyError((1, _generalerrors[1]))
# Check the chosen authentication method
if chosenauth[1:2] == chr(0x00).encode():
# No authentication is required
pass
elif chosenauth[1:2] == chr(0x02).encode():
# Okay, we need to perform a basic username/password
# authentication.
packet = bytearray()
packet.append(0x01)
packet.append(len(self.__proxy[4]))
packet.extend(self.__proxy[4])
packet.append(len(self.__proxy[5]))
packet.extend(self.__proxy[5])
self.sendall(packet)
authstat = self.__recvall(2)
if authstat[0:1] != chr(0x01).encode():
# Bad response
self.close()
raise GeneralProxyError((1, _generalerrors[1]))
if authstat[1:2] != chr(0x00).encode():
# Authentication failed
self.close()
raise Socks5AuthError((3, _socks5autherrors[3]))
# Authentication succeeded
else:
# Reaching here is always bad
self.close()
if chosenauth[1] == chr(0xFF).encode():
raise Socks5AuthError((2, _socks5autherrors[2]))
else:
raise GeneralProxyError((1, _generalerrors[1]))
# Now we can request the actual connection
req = struct.pack("BBB", 0x05, 0x01, 0x00)
# If the given destination address is an IP address, we'll
# use the IPv4 address request even if remote resolving was specified.
try:
ipaddr = socket.inet_aton(destaddr)
req = req + chr(0x01).encode() + ipaddr
except socket.error:
# Well it's not an IP number, so it's probably a DNS name.
if self.__proxy[3]:
# Resolve remotely
ipaddr = None
req = (
req
+ chr(0x03).encode()
+ chr(len(destaddr)).encode()
+ destaddr.encode()
)
else:
# Resolve locally
ipaddr = socket.inet_aton(socket.gethostbyname(destaddr))
req = req + chr(0x01).encode() + ipaddr
req = req + struct.pack(">H", destport)
self.sendall(req)
# Get the response
resp = self.__recvall(4)
if resp[0:1] != chr(0x05).encode():
self.close()
raise GeneralProxyError((1, _generalerrors[1]))
elif resp[1:2] != chr(0x00).encode():
# Connection failed
self.close()
if ord(resp[1:2]) <= 8:
raise Socks5Error((ord(resp[1:2]), _socks5errors[ord(resp[1:2])]))
else:
raise Socks5Error((9, _socks5errors[9]))
# Get the bound address/port
elif resp[3:4] == chr(0x01).encode():
boundaddr = self.__recvall(4)
elif resp[3:4] == chr(0x03).encode():
resp = resp + self.recv(1)
boundaddr = self.__recvall(ord(resp[4:5]))
else:
self.close()
raise GeneralProxyError((1, _generalerrors[1]))
boundport = struct.unpack(">H", self.__recvall(2))[0]
self.__proxysockname = (boundaddr, boundport)
if ipaddr != None:
self.__proxypeername = (socket.inet_ntoa(ipaddr), destport)
else:
self.__proxypeername = (destaddr, destport)
def getproxysockname(self):
"""getsockname() -> address info
Returns the bound IP address and port number at the proxy.
"""
return self.__proxysockname
def getproxypeername(self):
"""getproxypeername() -> address info
Returns the IP and port number of the proxy.
"""
return _orgsocket.getpeername(self)
def getpeername(self):
"""getpeername() -> address info
Returns the IP address and port number of the destination
machine (note: getproxypeername returns the proxy)
"""
return self.__proxypeername
def __negotiatesocks4(self, destaddr, destport):
"""__negotiatesocks4(self,destaddr,destport)
Negotiates a connection through a SOCKS4 server.
"""
# Check if the destination address provided is an IP address
rmtrslv = False
try:
ipaddr = socket.inet_aton(destaddr)
except socket.error:
# It's a DNS name. Check where it should be resolved.
if self.__proxy[3]:
ipaddr = struct.pack("BBBB", 0x00, 0x00, 0x00, 0x01)
rmtrslv = True
else:
ipaddr = socket.inet_aton(socket.gethostbyname(destaddr))
# Construct the request packet
req = struct.pack(">BBH", 0x04, 0x01, destport) + ipaddr
# The username parameter is considered userid for SOCKS4
if self.__proxy[4] != None:
req = req + self.__proxy[4]
req = req + chr(0x00).encode()
# DNS name if remote resolving is required
# NOTE: This is actually an extension to the SOCKS4 protocol
# called SOCKS4A and may not be supported in all cases.
if rmtrslv:
req = req + destaddr + chr(0x00).encode()
self.sendall(req)
# Get the response from the server
resp = self.__recvall(8)
if resp[0:1] != chr(0x00).encode():
# Bad data
self.close()
raise GeneralProxyError((1, _generalerrors[1]))
if resp[1:2] != chr(0x5A).encode():
# Server returned an error
self.close()
if ord(resp[1:2]) in (91, 92, 93):
self.close()
raise Socks4Error((ord(resp[1:2]), _socks4errors[ord(resp[1:2]) - 90]))
else:
raise Socks4Error((94, _socks4errors[4]))
# Get the bound address/port
self.__proxysockname = (
socket.inet_ntoa(resp[4:]),
struct.unpack(">H", resp[2:4])[0],
)
if rmtrslv != None:
self.__proxypeername = (socket.inet_ntoa(ipaddr), destport)
else:
self.__proxypeername = (destaddr, destport)
def __negotiatehttp(self, destaddr, destport):
"""__negotiatehttp(self,destaddr,destport)
Negotiates a connection through an HTTP server.
"""
# If we need to resolve locally, we do this now
if not self.__proxy[3]:
addr = socket.gethostbyname(destaddr)
else:
addr = destaddr
headers = ["CONNECT ", addr, ":", str(destport), " HTTP/1.1\r\n"]
wrote_host_header = False
wrote_auth_header = False
if self.__proxy[6] != None:
for key, val in self.__proxy[6].iteritems():
headers += [key, ": ", val, "\r\n"]
wrote_host_header = key.lower() == "host"
wrote_auth_header = key.lower() == "proxy-authorization"
if not wrote_host_header:
headers += ["Host: ", destaddr, "\r\n"]
if not wrote_auth_header:
if self.__proxy[4] != None and self.__proxy[5] != None:
headers += [self.__getauthheader(), "\r\n"]
headers.append("\r\n")
self.sendall("".join(headers).encode())
# We read the response until we get the string "\r\n\r\n"
resp = self.recv(1)
while resp.find("\r\n\r\n".encode()) == -1:
resp = resp + self.recv(1)
# We just need the first line to check if the connection
# was successful
statusline = resp.splitlines()[0].split(" ".encode(), 2)
if statusline[0] not in ("HTTP/1.0".encode(), "HTTP/1.1".encode()):
self.close()
raise GeneralProxyError((1, _generalerrors[1]))
try:
statuscode = int(statusline[1])
except ValueError:
self.close()
raise GeneralProxyError((1, _generalerrors[1]))
if statuscode != 200:
self.close()
raise HTTPError((statuscode, statusline[2]))
self.__proxysockname = ("0.0.0.0", 0)
self.__proxypeername = (addr, destport)
def connect(self, destpair):
"""connect(self, despair)
Connects to the specified destination through a proxy.
destpar - A tuple of the IP/DNS address and the port number.
(identical to socket's connect).
To select the proxy server use setproxy().
"""
# Do a minimal input check first
if (
(not type(destpair) in (list, tuple))
or (len(destpair) < 2)
or (not isinstance(destpair[0], (str, bytes)))
or (type(destpair[1]) != int)
):
raise GeneralProxyError((5, _generalerrors[5]))
if self.__proxy[0] == PROXY_TYPE_SOCKS5:
if self.__proxy[2] != None:
portnum = self.__proxy[2]
else:
portnum = 1080
_orgsocket.connect(self, (self.__proxy[1], portnum))
self.__negotiatesocks5(destpair[0], destpair[1])
elif self.__proxy[0] == PROXY_TYPE_SOCKS4:
if self.__proxy[2] != None:
portnum = self.__proxy[2]
else:
portnum = 1080
_orgsocket.connect(self, (self.__proxy[1], portnum))
self.__negotiatesocks4(destpair[0], destpair[1])
elif self.__proxy[0] == PROXY_TYPE_HTTP:
if self.__proxy[2] != None:
portnum = self.__proxy[2]
else:
portnum = 8080
_orgsocket.connect(self, (self.__proxy[1], portnum))
self.__negotiatehttp(destpair[0], destpair[1])
elif self.__proxy[0] == PROXY_TYPE_HTTP_NO_TUNNEL:
if self.__proxy[2] != None:
portnum = self.__proxy[2]
else:
portnum = 8080
_orgsocket.connect(self, (self.__proxy[1], portnum))
if destpair[1] == 443:
self.__negotiatehttp(destpair[0], destpair[1])
else:
self.__httptunnel = False
elif self.__proxy[0] == None:
_orgsocket.connect(self, (destpair[0], destpair[1]))
else:
raise GeneralProxyError((4, _generalerrors[4]))

View File

@@ -0,0 +1,91 @@
% Complete documentation on the extended LaTeX markup used for Python
% documentation is available in ``Documenting Python'', which is part
% of the standard documentation for Python. It may be found online
% at:
%
% http://www.python.org/doc/current/doc/doc.html
\documentclass{manual}
\title{The httplib2 Library}
\author{Joe Gregorio}
% Please at least include a long-lived email address;
% the rest is at your discretion.
\authoraddress{
% Organization name, if applicable \\
% Street address, if you want to use it \\
Email: \email{joe@bitworking.org}
}
\date{Mar 8, 2007} % update before release!
\release{0.3} % release version; this is used to define the
% \version macro
\makeindex % tell \index to actually write the .idx file
\makemodindex % If this contains a lot of module sections.
\begin{document}
\maketitle
% This makes the contents more accessible from the front page of the HTML.
%\ifhtml
%\chapter*{Front Matter\label{front}}
%\fi
%\input{copyright}
\begin{abstract}
\noindent
The \module{httplib2} module is a comprehensive HTTP client library
that handles caching, keep-alive, compression, redirects and
many kinds of authentication.
\end{abstract}
\tableofcontents
\chapter{Reference}
\input{libhttplib2.tex}
%\appendix
%\chapter{...}
%My appendix.
%The \code{\e appendix} markup need not be repeated for additional
%appendices.
%
% The ugly "%begin{latexonly}" pseudo-environments are really just to
% keep LaTeX2HTML quiet during the \renewcommand{} macros; they're
% not really valuable.
%
% If you don't want the Module Index, you can remove all of this up
% until the second \input line.
%
%begin{latexonly}
\renewcommand{\indexname}{Module Index}
%end{latexonly}
\input{mod\jobname.ind} % Module Index
%begin{latexonly}
\renewcommand{\indexname}{Index}
%end{latexonly}
\input{\jobname.ind} % Index
\end{document}

View File

@@ -0,0 +1,112 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="ref.css" type='text/css' />
<link rel="first" href="ref.html" title='The httplib2 Library' />
<link rel='contents' href='contents.html' title="Contents" />
<link rel='last' href='about.html' title='About this document...' />
<link rel='help' href='about.html' title='About this document...' />
<link rel="prev" href="node2.html" />
<link rel="parent" href="ref.html" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name='aesop' content='information' />
<title>About this document ...</title>
</head>
<body>
<div class="navigation">
<div id='top-navigation-panel' xml:id='top-navigation-panel'>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><a rel="prev" title="1.1.4 Examples"
href="httplib2-example.html"><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></a></td>
<td class='online-navigation'><a rel="parent" title="The httplib2 Library"
href="ref.html"><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></a></td>
<td class='online-navigation'><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></td>
<td align="center" width="100%">The httplib2 Library</td>
<td class='online-navigation'><a rel="contents" title="Table of Contents"
href="contents.html"><img src='contents.png'
border='0' height='32' alt='Contents' width='32' /></a></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Previous:</b>
<a class="sectref" rel="prev" href="httplib2-example.html">1.1.4 Examples</a>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="ref.html">The httplib2 Library</a>
</div>
<hr /></div>
</div>
<!--End of Navigation Panel-->
<h1><a name="SECTION003000000000000000000">
About this document ...</a>
</h1>
<strong>The httplib2 Library</strong>,
Mar 8, 2007, Release 0.3
<p> This document was generated using the <a
href="http://saftsack.fs.uni-bayreuth.de/~latex2ht/">
<strong>LaTeX</strong>2<tt>HTML</tt></a> translator.
</p>
<p> <a
href="http://saftsack.fs.uni-bayreuth.de/~latex2ht/">
<strong>LaTeX</strong>2<tt>HTML</tt></a> is Copyright &copy;
1993, 1994, 1995, 1996, 1997, <a
href="http://cbl.leeds.ac.uk/nikos/personal.html">Nikos
Drakos</a>, Computer Based Learning Unit, University of
Leeds, and Copyright &copy; 1997, 1998, <a
href="http://www.maths.mq.edu.au/~ross/">Ross
Moore</a>, Mathematics Department, Macquarie University,
Sydney.
</p>
<p> The application of <a
href="http://saftsack.fs.uni-bayreuth.de/~latex2ht/">
<strong>LaTeX</strong>2<tt>HTML</tt></a> to the Python
documentation has been heavily tailored by Fred L. Drake,
Jr. Original navigation icons were contributed by Christopher
Petrilli.
</p>
<div class="navigation">
<div class='online-navigation'>
<p></p><hr />
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><a rel="prev" title="1.1.4 Examples"
href="httplib2-example.html"><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></a></td>
<td class='online-navigation'><a rel="parent" title="The httplib2 Library"
href="ref.html"><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></a></td>
<td class='online-navigation'><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></td>
<td align="center" width="100%">The httplib2 Library</td>
<td class='online-navigation'><a rel="contents" title="Table of Contents"
href="contents.html"><img src='contents.png'
border='0' height='32' alt='Contents' width='32' /></a></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Previous:</b>
<a class="sectref" rel="prev" href="httplib2-example.html">1.1.4 Examples</a>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="ref.html">The httplib2 Library</a>
</div>
</div>
<hr />
<span class="release-info">Release 0.3, documentation updated on Mar 8, 2007.</span>
</div>
<!--End of Navigation Panel-->
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -0,0 +1,129 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="ref.css" type='text/css' />
<link rel="first" href="ref.html" title='The httplib2 Library' />
<link rel='contents' href='contents.html' title="Contents" />
<link rel='last' href='about.html' title='About this document...' />
<link rel='help' href='about.html' title='About this document...' />
<link rel="next" href="response-objects.html" />
<link rel="prev" href="http-objects.html" />
<link rel="parent" href="module-httplib2.html" />
<link rel="next" href="response-objects.html" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name='aesop' content='information' />
<title>1.1.2 Cache Objects</title>
</head>
<body>
<div class="navigation">
<div id='top-navigation-panel' xml:id='top-navigation-panel'>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><a rel="prev" title="1.1.1 http Objects"
href="http-objects.html"><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></a></td>
<td class='online-navigation'><a rel="parent" title="1.1 httplib2 A comprehensive"
href="module-httplib2.html"><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></a></td>
<td class='online-navigation'><a rel="next" title="1.1.3 response Objects"
href="response-objects.html"><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></a></td>
<td align="center" width="100%">The httplib2 Library</td>
<td class='online-navigation'><a rel="contents" title="Table of Contents"
href="contents.html"><img src='contents.png'
border='0' height='32' alt='Contents' width='32' /></a></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Previous:</b>
<a class="sectref" rel="prev" href="http-objects.html">1.1.1 Http Objects</a>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="module-httplib2.html">1.1 httplib2 A comprehensive</a>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="response-objects.html">1.1.3 Response Objects</a>
</div>
<hr /></div>
</div>
<!--End of Navigation Panel-->
<h2><a name="SECTION002120000000000000000"></a>
<a name="cache-objects"></a>
<br>
1.1.2 Cache Objects
</h2>
<p>
If you wish to supply your own caching implementation
then you will need to pass in an object that supports the
following methods. Note that the <tt class="module">memcache</tt> module
supports this interface natively.
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-23' xml:id='l2h-23' class="method">get</tt></b>(</nobr></td>
<td><var>key</var>)</td></tr></table></dt>
<dd>
Takes a string <var>key</var> and returns the value as a string.
</dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-24' xml:id='l2h-24' class="method">set</tt></b>(</nobr></td>
<td><var>key, value</var>)</td></tr></table></dt>
<dd>
Takes a string <var>key</var> and <var>value</var> and stores it in the cache.
</dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-25' xml:id='l2h-25' class="method">delete</tt></b>(</nobr></td>
<td><var>key</var>)</td></tr></table></dt>
<dd>
Deletes the cached value stored at <var>key</var>. The value
of <var>key</var> is a string.
</dl>
<p>
<div class="navigation">
<div class='online-navigation'>
<p></p><hr />
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><a rel="prev" title="1.1.1 http Objects"
href="http-objects.html"><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></a></td>
<td class='online-navigation'><a rel="parent" title="1.1 httplib2 A comprehensive"
href="module-httplib2.html"><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></a></td>
<td class='online-navigation'><a rel="next" title="1.1.3 response Objects"
href="response-objects.html"><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></a></td>
<td align="center" width="100%">The httplib2 Library</td>
<td class='online-navigation'><a rel="contents" title="Table of Contents"
href="contents.html"><img src='contents.png'
border='0' height='32' alt='Contents' width='32' /></a></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Previous:</b>
<a class="sectref" rel="prev" href="http-objects.html">1.1.1 Http Objects</a>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="module-httplib2.html">1.1 httplib2 A comprehensive</a>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="response-objects.html">1.1.3 Response Objects</a>
</div>
</div>
<hr />
<span class="release-info">Release 0.3, documentation updated on Mar 8, 2007.</span>
</div>
<!--End of Navigation Panel-->
</body>
</html>

View File

@@ -0,0 +1,105 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="ref.css" type='text/css' />
<link rel="first" href="ref.html" title='The httplib2 Library' />
<link rel='contents' href='contents.html' title="Contents" />
<link rel='last' href='about.html' title='About this document...' />
<link rel='help' href='about.html' title='About this document...' />
<link rel="next" href="node2.html" />
<link rel="prev" href="ref.html" />
<link rel="parent" href="ref.html" />
<link rel="next" href="node2.html" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name='aesop' content='information' />
<title>Contents</title>
</head>
<body>
<div class="navigation">
<div id='top-navigation-panel' xml:id='top-navigation-panel'>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><a rel="prev" title="The httplib2 Library"
href="ref.html"><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></a></td>
<td class='online-navigation'><a rel="parent" title="The httplib2 Library"
href="ref.html"><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></a></td>
<td class='online-navigation'><a rel="next" title="1. Reference"
href="node2.html"><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></a></td>
<td align="center" width="100%">The httplib2 Library</td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Previous:</b>
<a class="sectref" rel="prev" href="ref.html">The httplib2 Library</a>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="ref.html">The httplib2 Library</a>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="node2.html">1. Reference</a>
</div>
<hr /></div>
</div>
<!--End of Navigation Panel-->
<br><h2><a name="SECTION001000000000000000000">
Contents</a>
</h2>
<!--Table of Contents-->
<ul class="TofC">
<li><a href="node2.html">1. Reference</a>
<ul>
<li><a href="module-httplib2.html">1.1 httplib2 A comprehensive HTTP client library.</a>
<ul>
<li><a href="http-objects.html">1.1.1 Http Objects</a>
<li><a href="cache-objects.html">1.1.2 Cache Objects</a>
<li><a href="response-objects.html">1.1.3 Response Objects</a>
<li><a href="httplib2-example.html">1.1.4 Examples</a>
</ul></ul></ul>
<!--End of Table of Contents-->
<p>
<div class="navigation">
<div class='online-navigation'>
<p></p><hr />
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><a rel="prev" title="The httplib2 Library"
href="ref.html"><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></a></td>
<td class='online-navigation'><a rel="parent" title="The httplib2 Library"
href="ref.html"><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></a></td>
<td class='online-navigation'><a rel="next" title="1. Reference"
href="node2.html"><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></a></td>
<td align="center" width="100%">The httplib2 Library</td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Previous:</b>
<a class="sectref" rel="prev" href="ref.html">The httplib2 Library</a>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="ref.html">The httplib2 Library</a>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="node2.html">1. Reference</a>
</div>
</div>
<hr />
<span class="release-info">Release 0.3, documentation updated on Mar 8, 2007.</span>
</div>
<!--End of Navigation Panel-->
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 649 B

View File

@@ -0,0 +1,205 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="ref.css" type='text/css' />
<link rel="first" href="ref.html" title='The httplib2 Library' />
<link rel='contents' href='contents.html' title="Contents" />
<link rel='last' href='about.html' title='About this document...' />
<link rel='help' href='about.html' title='About this document...' />
<link rel="next" href="cache-objects.html" />
<link rel="prev" href="module-httplib2.html" />
<link rel="parent" href="module-httplib2.html" />
<link rel="next" href="cache-objects.html" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name='aesop' content='information' />
<title>1.1.1 Http Objects</title>
</head>
<body>
<div class="navigation">
<div id='top-navigation-panel' xml:id='top-navigation-panel'>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><a rel="prev" title="1.1 httplib2 A comprehensive"
href="module-httplib2.html"><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></a></td>
<td class='online-navigation'><a rel="parent" title="1.1 httplib2 A comprehensive"
href="module-httplib2.html"><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></a></td>
<td class='online-navigation'><a rel="next" title="1.1.2 cache Objects"
href="cache-objects.html"><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></a></td>
<td align="center" width="100%">The httplib2 Library</td>
<td class='online-navigation'><a rel="contents" title="Table of Contents"
href="contents.html"><img src='contents.png'
border='0' height='32' alt='Contents' width='32' /></a></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Previous:</b>
<a class="sectref" rel="prev" href="module-httplib2.html">1.1 httplib2 A comprehensive</a>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="module-httplib2.html">1.1 httplib2 A comprehensive</a>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="cache-objects.html">1.1.2 Cache Objects</a>
</div>
<hr /></div>
</div>
<!--End of Navigation Panel-->
<h2><a name="SECTION002110000000000000000"></a>
<a name="http-objects"></a>
<br>
1.1.1 Http Objects
</h2>
<p>
Http objects have the following methods:
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-15' xml:id='l2h-15' class="method">request</tt></b>(</nobr></td>
<td><var>uri, </var><big>[</big><var>method="GET", body=None, headers=None, redirections=DEFAULT_MAX_REDIRECTS, connection_type=None</var><big>]</big><var></var>)</td></tr></table></dt>
<dd>
Performs a single HTTP request.
The <var>uri</var> is the URI of the HTTP resource and can begin with either <code>http</code> or <code>https</code>. The value of <var>uri</var> must be an absolute URI.
<p>
The <var>method</var> is the HTTP method to perform, such as <code>GET</code>, <code>POST</code>, <code>DELETE</code>, etc. There is no restriction
on the methods allowed.
<p>
The <var>body</var> is the entity body to be sent with the request. It is a string
object.
<p>
Any extra headers that are to be sent with the request should be provided in the
<var>headers</var> dictionary.
<p>
The maximum number of redirect to follow before raising an exception is <var>redirections</var>. The default is 5.
<p>
The <var>connection_type</var> is the type of connection object to use. The supplied class
should implement the interface of httplib.HTTPConnection.
<p>
The return value is a tuple of (response, content), the first being and instance of the
<tt class="class">Response</tt> class, the second being a string that contains the response entity body.
</dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-16' xml:id='l2h-16' class="method">add_credentials</tt></b>(</nobr></td>
<td><var>name, password, </var><big>[</big><var>domain=None</var><big>]</big><var></var>)</td></tr></table></dt>
<dd>
Adds a name and password that will be used when a request
requires authentication. Supplying the optional <var>domain</var> name will
restrict these credentials to only be sent to the specified
domain. If <var>domain</var> is not specified then the given credentials will
be used to try to satisfy every HTTP 401 challenge.
</dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-17' xml:id='l2h-17' class="method">add_certificate</tt></b>(</nobr></td>
<td><var>key, cert, domain</var>)</td></tr></table></dt>
<dd>
Add a <var>key</var> and <var>cert</var> that will be used for an SSL connection
to the specified domain. <var>keyfile</var> is the name of a PEM formatted
file that contains your private key. <var>certfile</var> is a PEM formatted certificate chain file.
</dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><tt id='l2h-18' xml:id='l2h-18' class="method">clear_credentials</tt></b>(</nobr></td>
<td><var></var>)</td></tr></table></dt>
<dd>
Remove all the names and passwords used for authentication.
</dl>
<p>
<dl><dt><b><tt id='l2h-19' xml:id='l2h-19' class="member">follow_redirects</tt></b></dt>
<dd>
If <code>True</code>, which is the default, safe redirects are followed, where
safe means that the client is only doing a <code>GET</code> or <code>HEAD</code> on the
URI to which it is being redirected. If <code>False</code> then no redirects are followed.
Note that a False 'follow_redirects' takes precedence over a True 'follow_all_redirects'.
Another way of saying that is for 'follow_all_redirects' to have any affect, 'follow_redirects'
must be True.
</dl>
<p>
<dl><dt><b><tt id='l2h-20' xml:id='l2h-20' class="member">follow_all_redirects</tt></b></dt>
<dd>
If <code>False</code>, which is the default, only safe redirects are followed, where
safe means that the client is only doing a <code>GET</code> or <code>HEAD</code> on the
URI to which it is being redirected. If <code>True</code> then all redirects are followed.
Note that a False 'follow_redirects' takes precedence over a True 'follow_all_redirects'.
Another way of saying that is for 'follow_all_redirects' to have any affect, 'follow_redirects'
must be True.
</dl>
<p>
<dl><dt><b><tt id='l2h-21' xml:id='l2h-21' class="member">force_exception_to_status_code</tt></b></dt>
<dd>
If <code>True</code>, which is the default, then no <tt class="module">httplib2</tt> exceptions will be thrown. Instead,
those error conditions will be turned into <tt class="class">Response</tt> objects
that will be returned normally.
<p>
If <code>False</code>, then exceptions will be thrown.
</dl>
<p>
<dl><dt><b><tt id='l2h-22' xml:id='l2h-22' class="member">ignore_etag</tt></b></dt>
<dd>
Defaults to <code>False</code>. If <code>True</code>, then any etags present in the cached response
are ignored when processing the current request, i.e. httplib2 does <strong>not</strong> use
'if-match' for PUT or 'if-none-match' when GET or HEAD requests are made. This
is mainly to deal with broken servers which supply an etag, but change it capriciously.
</dl>
<p>
<div class="navigation">
<div class='online-navigation'>
<p></p><hr />
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><a rel="prev" title="1.1 httplib2 A comprehensive"
href="module-httplib2.html"><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></a></td>
<td class='online-navigation'><a rel="parent" title="1.1 httplib2 A comprehensive"
href="module-httplib2.html"><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></a></td>
<td class='online-navigation'><a rel="next" title="1.1.2 cache Objects"
href="cache-objects.html"><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></a></td>
<td align="center" width="100%">The httplib2 Library</td>
<td class='online-navigation'><a rel="contents" title="Table of Contents"
href="contents.html"><img src='contents.png'
border='0' height='32' alt='Contents' width='32' /></a></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Previous:</b>
<a class="sectref" rel="prev" href="module-httplib2.html">1.1 httplib2 A comprehensive</a>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="module-httplib2.html">1.1 httplib2 A comprehensive</a>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="cache-objects.html">1.1.2 Cache Objects</a>
</div>
</div>
<hr />
<span class="release-info">Release 0.3, documentation updated on Mar 8, 2007.</span>
</div>
<!--End of Navigation Panel-->
</body>
</html>

View File

@@ -0,0 +1,188 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="ref.css" type='text/css' />
<link rel="first" href="ref.html" title='The httplib2 Library' />
<link rel='contents' href='contents.html' title="Contents" />
<link rel='last' href='about.html' title='About this document...' />
<link rel='help' href='about.html' title='About this document...' />
<link rel="prev" href="response-objects.html" />
<link rel="parent" href="module-httplib2.html" />
<link rel="next" href="about.html" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name='aesop' content='information' />
<title>1.1.4 Examples </title>
</head>
<body>
<div class="navigation">
<div id='top-navigation-panel' xml:id='top-navigation-panel'>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><a rel="prev" title="1.1.3 response Objects"
href="response-objects.html"><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></a></td>
<td class='online-navigation'><a rel="parent" title="1.1 httplib2 A comprehensive"
href="module-httplib2.html"><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></a></td>
<td class='online-navigation'><a rel="next" title="About this document ..."
href="about.html"><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></a></td>
<td align="center" width="100%">The httplib2 Library</td>
<td class='online-navigation'><a rel="contents" title="Table of Contents"
href="contents.html"><img src='contents.png'
border='0' height='32' alt='Contents' width='32' /></a></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Previous:</b>
<a class="sectref" rel="prev" href="response-objects.html">1.1.3 Response Objects</a>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="module-httplib2.html">1.1 httplib2 A comprehensive</a>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="about.html">About this document ...</a>
</div>
<hr /></div>
</div>
<!--End of Navigation Panel-->
<h2><a name="SECTION002140000000000000000"></a><a name="httplib2-example"></a>
<br>
1.1.4 Examples
</h2>
<p>
To do a simple <code>GET</code> request just supply the absolute URI
of the resource:
<p>
<div class="verbatim"><pre>
import httplib2
h = httplib2.Http()
resp, content = h.request("http://bitworking.org/")
assert resp.status == 200
assert resp['content-type'] == 'text/html'
</pre></div>
<p>
Here is more complex example that does a PUT
of some text to a resource that requires authentication.
The Http instance also uses a file cache
in the directory <code>.cache</code>.
<p>
<div class="verbatim"><pre>
import httplib2
h = httplib2.Http(".cache")
h.add_credentials('name', 'password')
resp, content = h.request("https://example.org/chap/2",
"PUT", body="This is text",
headers={'content-type':'text/plain'} )
</pre></div>
<p>
Here is an example that connects to a server that
supports the Atom Publishing Protocol.
<p>
<div class="verbatim"><pre>
import httplib2
h = httplib2.Http()
h.add_credentials(myname, mypasswd)
h.follow_all_redirects = True
headers = {'Content-Type': 'application/atom+xml'}
body = """&lt;?xml version="1.0" ?&gt;
&lt;entry xmlns="http://www.w3.org/2005/Atom"&gt;
&lt;title&gt;Atom-Powered Robots Run Amok&lt;/title&gt;
&lt;id&gt;urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a&lt;/id&gt;
&lt;updated&gt;2003-12-13T18:30:02Z&lt;/updated&gt;
&lt;author&gt;&lt;name&gt;John Doe&lt;/name&gt;&lt;/author&gt;
&lt;content&gt;Some text.&lt;/content&gt;
&lt;/entry&gt;
"""
uri = "http://www.example.com/collection/"
resp, content = h.request(uri, "POST", body=body, headers=headers)
</pre></div>
<p>
Here is an example of providing data to an HTML form processor.
In this case we presume this is a POST form. We need to take our
data and format it as "application/x-www-form-urlencoded" data and use that as a
body for a POST request.
<p>
<div class="verbatim"><pre>
&gt;&gt;&gt; import httplib2
&gt;&gt;&gt; import urllib
&gt;&gt;&gt; data = {'name': 'fred', 'address': '123 shady lane'}
&gt;&gt;&gt; body = urllib.urlencode(data)
&gt;&gt;&gt; body
'name=fred&amp;address=123+shady+lane'
&gt;&gt;&gt; h = httplib2.Http()
&gt;&gt;&gt; resp, content = h.request("http://example.com", method="POST", body=body)
</pre></div>
<p>
Here is an example of using a proxy server:
<div class="verbatim"><pre>
import httplib2
import socks
httplib2.debuglevel=4
h = httplib2.Http(proxy_info = httplib2.ProxyInfo(socks.PROXY_TYPE_HTTP, 'localhost', 8000))
r,c = h.request("http://bitworking.org/news/")
</pre></div>
<p>
<p>
<IMG
WIDTH="556" HEIGHT="20" ALIGN="BOTTOM" BORDER="0"
SRC="img1.png"
ALT="\begin{center}\vbox{\input{modref.ind}
}\end{center}">
<p>
<p>
<div class="navigation">
<div class='online-navigation'>
<p></p><hr />
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><a rel="prev" title="1.1.3 response Objects"
href="response-objects.html"><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></a></td>
<td class='online-navigation'><a rel="parent" title="1.1 httplib2 A comprehensive"
href="module-httplib2.html"><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></a></td>
<td class='online-navigation'><a rel="next" title="About this document ..."
href="about.html"><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></a></td>
<td align="center" width="100%">The httplib2 Library</td>
<td class='online-navigation'><a rel="contents" title="Table of Contents"
href="contents.html"><img src='contents.png'
border='0' height='32' alt='Contents' width='32' /></a></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Previous:</b>
<a class="sectref" rel="prev" href="response-objects.html">1.1.3 Response Objects</a>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="module-httplib2.html">1.1 httplib2 A comprehensive</a>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="about.html">About this document ...</a>
</div>
</div>
<hr />
<span class="release-info">Release 0.3, documentation updated on Mar 8, 2007.</span>
</div>
<!--End of Navigation Panel-->
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 B

View File

@@ -0,0 +1,129 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="ref.css" type='text/css' />
<link rel="first" href="ref.html" title='The httplib2 Library' />
<link rel='contents' href='contents.html' title="Contents" />
<link rel='last' href='about.html' title='About this document...' />
<link rel='help' href='about.html' title='About this document...' />
<link rel="next" href="contents.html" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name='aesop' content='information' />
<title>The httplib2 Library</title>
</head>
<body>
<div class="navigation">
<div id='top-navigation-panel' xml:id='top-navigation-panel'>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></td>
<td class='online-navigation'><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></td>
<td class='online-navigation'><a rel="next" title="Contents"
href="contents.html"><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></a></td>
<td align="center" width="100%">The httplib2 Library</td>
<td class='online-navigation'><a rel="contents" title="Table of Contents"
href="contents.html"><img src='contents.png'
border='0' height='32' alt='Contents' width='32' /></a></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="contents.html">Contents</a>
</div>
<hr /></div>
</div>
<!--End of Navigation Panel-->
<p>
<div class="titlepage">
<div class='center'>
<h1>The httplib2 Library</h1>
<p><b><font size="+2">Joe Gregorio</font></b></p>
<p>
Email: <span class="email">joe@bitworking.org</span>
</p>
<p><strong>Release 0.3</strong><br />
<strong>Mar 8, 2007</strong></p>
<p></p>
</div>
</div>
<p>
<h3>Abstract:</h3>
<div class="ABSTRACT">
<p>
The <tt class="module">httplib2</tt> module is a comprehensive HTTP client library
that handles caching, keep-alive, compression, redirects and
many kinds of authentication.
<p>
</div>
<p>
<p>
<p><br /></p><hr class='online-navigation' />
<div class='online-navigation'>
<!--Table of Child-Links-->
<a name="CHILD_LINKS"></a>
<ul class="ChildLinks">
<li><a href="contents.html">Contents</a>
<li><a href="node2.html">1. Reference</a>
<ul>
<li><a href="module-httplib2.html">1.1 <tt class="module">httplib2</tt>
A comprehensive HTTP client library.</a>
<ul>
<li><a href="http-objects.html">1.1.1 Http Objects</a>
<li><a href="cache-objects.html">1.1.2 Cache Objects</a>
<li><a href="response-objects.html">1.1.3 Response Objects</a>
<li><a href="httplib2-example.html">1.1.4 Examples</a>
</ul>
</ul>
<li><a href="about.html">About this document ...</a>
</ul>
<!--End of Table of Child-Links-->
</div>
<div class="navigation">
<div class='online-navigation'>
<p></p><hr />
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></td>
<td class='online-navigation'><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></td>
<td class='online-navigation'><a rel="next" title="Contents"
href="contents.html"><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></a></td>
<td align="center" width="100%">The httplib2 Library</td>
<td class='online-navigation'><a rel="contents" title="Table of Contents"
href="contents.html"><img src='contents.png'
border='0' height='32' alt='Contents' width='32' /></a></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="contents.html">Contents</a>
</div>
</div>
<hr />
<span class="release-info">Release 0.3, documentation updated on Mar 8, 2007.</span>
</div>
<!--End of Navigation Panel-->
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 529 B

View File

@@ -0,0 +1,280 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="ref.css" type='text/css' />
<link rel="first" href="ref.html" title='The httplib2 Library' />
<link rel='contents' href='contents.html' title="Contents" />
<link rel='last' href='about.html' title='About this document...' />
<link rel='help' href='about.html' title='About this document...' />
<link rel="prev" href="node2.html" />
<link rel="parent" href="node2.html" />
<link rel="next" href="http-objects.html" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name='aesop' content='information' />
<title>1.1 httplib2 A comprehensive HTTP client library. </title>
</head>
<body>
<div class="navigation">
<div id='top-navigation-panel' xml:id='top-navigation-panel'>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><a rel="prev" title="1. Reference"
href="node2.html"><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></a></td>
<td class='online-navigation'><a rel="parent" title="1. Reference"
href="node2.html"><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></a></td>
<td class='online-navigation'><a rel="next" title="1.1.1 http Objects"
href="http-objects.html"><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></a></td>
<td align="center" width="100%">The httplib2 Library</td>
<td class='online-navigation'><a rel="contents" title="Table of Contents"
href="contents.html"><img src='contents.png'
border='0' height='32' alt='Contents' width='32' /></a></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Previous:</b>
<a class="sectref" rel="prev" href="node2.html">1. Reference</a>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="node2.html">1. Reference</a>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="http-objects.html">1.1.1 Http Objects</a>
</div>
<hr /></div>
</div>
<!--End of Navigation Panel-->
<h1><a name="SECTION002100000000000000000">
1.1 <tt class="module">httplib2</tt>
A comprehensive HTTP client library. </a>
</h1>
<p>
<a name="module-httplib2"></a>
<p>
<p>
<p>
The <tt class="module">httplib2</tt> module is a comprehensive HTTP client library with the following features:
<p>
<dl>
<dt><strong>HTTP and HTTPS</strong></dt>
<dd>HTTPS support is only available if the socket module was compiled with SSL support.
</dd>
<dt><strong>Keep-Alive</strong></dt>
<dd>Supports HTTP 1.1 Keep-Alive, keeping the socket open and performing multiple requests over the same connection if possible.
</dd>
<dt><strong>Authentication</strong></dt>
<dd>The following three types of HTTP Authentication are supported. These can be used over both HTTP and HTTPS.
<ul>
<li>Digest
</li>
<li>Basic
</li>
<li>WSSE
</li>
</ul>
</dd>
<dt><strong>Caching</strong></dt>
<dd>The module can optionally operate with a private cache that understands the Cache-Control: header and uses both the ETag and Last-Modified cache validators.
</dd>
<dt><strong>All Methods</strong></dt>
<dd>The module can handle any HTTP request method, not just GET and POST.
</dd>
<dt><strong>Redirects</strong></dt>
<dd>Automatically follows 3XX redirects on GETs.
</dd>
<dt><strong>Compression</strong></dt>
<dd>Handles both 'deflate' and 'gzip' types of compression.
</dd>
<dt><strong>Proxies</strong></dt>
<dd>If the Socksipy module is installed then httplib2 can handle sock4, sock5 and http proxies.
</dd>
<dt><strong>Lost update support</strong></dt>
<dd>Automatically adds back ETags into PUT requests to resources we have already cached. This implements Section 3.2 of Detecting the Lost Update Problem Using Unreserved Checkout
</dd>
</dl>
<p>
The <tt class="module">httplib2</tt> module defines the following variables:
<p>
<dl><dt><b><tt id='l2h-2' xml:id='l2h-2'>debuglevel</tt></b></dt>
<dd>
The amount of debugging information to print. The default is 0.
</dd></dl>
<p>
The <tt class="module">httplib2</tt> module may raise the following Exceptions. Note that
there is an option that turns exceptions into
normal responses with an HTTP status code indicating
an error occured. See <tt class="member">Http.force_exception_to_status_code</tt>
<p>
<dl><dt><b><span class="typelabel">exception</span>&nbsp;<tt id='l2h-3' xml:id='l2h-3' class="exception">HttpLib2Error</tt></b></dt>
<dd>
The Base Exception for all exceptions raised by httplib2.
</dd></dl>
<p>
<dl><dt><b><span class="typelabel">exception</span>&nbsp;<tt id='l2h-4' xml:id='l2h-4' class="exception">RedirectMissingLocation</tt></b></dt>
<dd>
A 3xx redirect response code was provided but no Location: header
was provided to point to the new location.
</dd></dl>
<p>
<dl><dt><b><span class="typelabel">exception</span>&nbsp;<tt id='l2h-5' xml:id='l2h-5' class="exception">RedirectLimit</tt></b></dt>
<dd>
The maximum number of redirections was reached without coming to a final URI.
</dd></dl>
<p>
<dl><dt><b><span class="typelabel">exception</span>&nbsp;<tt id='l2h-6' xml:id='l2h-6' class="exception">ServerNotFoundError</tt></b></dt>
<dd>
Unable to resolve the host name given.
</dd></dl>
<p>
<dl><dt><b><span class="typelabel">exception</span>&nbsp;<tt id='l2h-7' xml:id='l2h-7' class="exception">RelativeURIError</tt></b></dt>
<dd>
A relative, as opposed to an absolute URI, was passed into request().
</dd></dl>
<p>
<dl><dt><b><span class="typelabel">exception</span>&nbsp;<tt id='l2h-8' xml:id='l2h-8' class="exception">FailedToDecompressContent</tt></b></dt>
<dd>
The headers claimed that the content of the response was compressed but the
decompression algorithm applied to the content failed.
</dd></dl>
<p>
<dl><dt><b><span class="typelabel">exception</span>&nbsp;<tt id='l2h-9' xml:id='l2h-9' class="exception">UnimplementedDigestAuthOptionError</tt></b></dt>
<dd>
The server requested a type of Digest authentication that we
are unfamiliar with.
</dd></dl>
<p>
<dl><dt><b><span class="typelabel">exception</span>&nbsp;<tt id='l2h-10' xml:id='l2h-10' class="exception">UnimplementedHmacDigestAuthOptionError</tt></b></dt>
<dd>
The server requested a type of HMACDigest authentication that we
are unfamiliar with.
</dd></dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><span class="typelabel">class</span>&nbsp;<tt id='l2h-11' xml:id='l2h-11' class="class">Http</tt></b>(</nobr></td>
<td><var></var><big>[</big><var>cache=None</var><big>]</big><var>, </var><big>[</big><var>timeout=None</var><big>]</big><var>, </var><big>[</big><var>proxy_info=None</var><big>]</big><var></var>)</td></tr></table></dt>
<dd>
The class that represents a client HTTP interface.
The <var>cache</var> parameter is either the name of a directory
to be used as a flat file cache, or it must an object that
implements the required caching interface.
The <var>timeout</var> parameter is the socket level timeout.
The <var>proxy_info</var> is an instance of <tt class="class">ProxyInfo</tt> and is supplied
if a proxy is to be used. Note that the Socksipy module must be
installed for proxy support to work.
</dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><span class="typelabel">class</span>&nbsp;<tt id='l2h-12' xml:id='l2h-12' class="class">Response</tt></b>(</nobr></td>
<td><var>info</var>)</td></tr></table></dt>
<dd>
Response is a subclass of <tt class="class">dict</tt> and instances of this
class are returned from calls
to Http.request. The <var>info</var> parameter is either
an <tt class="class">rfc822.Message</tt> or an <tt class="class">httplib.HTTPResponse</tt> object.
</dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><span class="typelabel">class</span>&nbsp;<tt id='l2h-13' xml:id='l2h-13' class="class">FileCache</tt></b>(</nobr></td>
<td><var>dir_name, </var><big>[</big><var>safe=safename</var><big>]</big><var></var>)</td></tr></table></dt>
<dd>
FileCache implements a Cache as a directory of files.
The <var>dir_name</var> parameter is
the name of the directory to use. If the directory does
not exist then FileCache attempts to create the directory.
The optional <var>safe</var> parameter is a funtion which generates
the cache filename for each URI. A FileCache object is
constructed and used for caching when you pass a directory name
into the constructor of <tt class="class">Http</tt>.
</dl>
<p>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><span class="typelabel">class</span>&nbsp;<tt id='l2h-14' xml:id='l2h-14' class="class">ProxyInfo</tt></b>(</nobr></td>
<td><var>proxy_type, proxy_host, proxy_port, </var><big>[</big><var>proxy_rdns=None</var><big>]</big><var>, </var><big>[</big><var>proxy_user=None</var><big>]</big><var>, </var><big>[</big><var>proxy_pass=None</var><big>]</big><var></var>)</td></tr></table></dt>
<dd>
The parameter <var>proxy_type</var> must be set to one of socks.PROXY_TYPE_XXX
constants. The <var>proxy_host</var> and <var>proxy_port</var> must be set to the location
of the proxy. The optional <var>proxy_rdns</var> should be set to True if
the DNS server on the proxy should be used. The <var>proxy_user</var> and
<var>proxy_pass</var> are supplied when the proxy is protected by authentication.
</dl>
<p>
<p><br /></p><hr class='online-navigation' />
<div class='online-navigation'>
<!--Table of Child-Links-->
<a name="CHILD_LINKS"><strong>Subsections</strong></a>
<ul class="ChildLinks">
<li><a href="http-objects.html">1.1.1 Http Objects</a>
<li><a href="cache-objects.html">1.1.2 Cache Objects</a>
<li><a href="response-objects.html">1.1.3 Response Objects</a>
<li><a href="httplib2-example.html">1.1.4 Examples</a>
</ul>
<!--End of Table of Child-Links-->
</div>
<div class="navigation">
<div class='online-navigation'>
<p></p><hr />
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><a rel="prev" title="1. Reference"
href="node2.html"><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></a></td>
<td class='online-navigation'><a rel="parent" title="1. Reference"
href="node2.html"><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></a></td>
<td class='online-navigation'><a rel="next" title="1.1.1 http Objects"
href="http-objects.html"><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></a></td>
<td align="center" width="100%">The httplib2 Library</td>
<td class='online-navigation'><a rel="contents" title="Table of Contents"
href="contents.html"><img src='contents.png'
border='0' height='32' alt='Contents' width='32' /></a></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Previous:</b>
<a class="sectref" rel="prev" href="node2.html">1. Reference</a>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="node2.html">1. Reference</a>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="http-objects.html">1.1.1 Http Objects</a>
</div>
</div>
<hr />
<span class="release-info">Release 0.3, documentation updated on Mar 8, 2007.</span>
</div>
<!--End of Navigation Panel-->
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 598 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 511 B

View File

@@ -0,0 +1,115 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="ref.css" type='text/css' />
<link rel="first" href="ref.html" title='The httplib2 Library' />
<link rel='contents' href='contents.html' title="Contents" />
<link rel='last' href='about.html' title='About this document...' />
<link rel='help' href='about.html' title='About this document...' />
<link rel="next" href="about.html" />
<link rel="prev" href="contents.html" />
<link rel="parent" href="ref.html" />
<link rel="next" href="module-httplib2.html" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name='aesop' content='information' />
<title>1. Reference</title>
</head>
<body>
<div class="navigation">
<div id='top-navigation-panel' xml:id='top-navigation-panel'>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><a rel="prev" title="Contents"
href="contents.html"><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></a></td>
<td class='online-navigation'><a rel="parent" title="The httplib2 Library"
href="ref.html"><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></a></td>
<td class='online-navigation'><a rel="next" title="1.1 httplib2 A comprehensive"
href="module-httplib2.html"><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></a></td>
<td align="center" width="100%">The httplib2 Library</td>
<td class='online-navigation'><a rel="contents" title="Table of Contents"
href="contents.html"><img src='contents.png'
border='0' height='32' alt='Contents' width='32' /></a></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Previous:</b>
<a class="sectref" rel="prev" href="contents.html">Contents</a>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="ref.html">The httplib2 Library</a>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="module-httplib2.html">1.1 httplib2 A comprehensive</a>
</div>
<hr /></div>
</div>
<!--End of Navigation Panel-->
<h1><a name="SECTION002000000000000000000">
1. Reference</a>
</h1>
<p>
<p>
<p><br /></p><hr class='online-navigation' />
<div class='online-navigation'>
<!--Table of Child-Links-->
<a name="CHILD_LINKS"><strong>Subsections</strong></a>
<ul class="ChildLinks">
<li><a href="module-httplib2.html">1.1 <tt class="module">httplib2</tt>
A comprehensive HTTP client library.</a>
<ul>
<li><a href="http-objects.html">1.1.1 Http Objects</a>
<li><a href="cache-objects.html">1.1.2 Cache Objects</a>
<li><a href="response-objects.html">1.1.3 Response Objects</a>
<li><a href="httplib2-example.html">1.1.4 Examples</a>
</ul></ul>
<!--End of Table of Child-Links-->
</div>
<div class="navigation">
<div class='online-navigation'>
<p></p><hr />
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><a rel="prev" title="Contents"
href="contents.html"><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></a></td>
<td class='online-navigation'><a rel="parent" title="The httplib2 Library"
href="ref.html"><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></a></td>
<td class='online-navigation'><a rel="next" title="1.1 httplib2 A comprehensive"
href="module-httplib2.html"><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></a></td>
<td align="center" width="100%">The httplib2 Library</td>
<td class='online-navigation'><a rel="contents" title="Table of Contents"
href="contents.html"><img src='contents.png'
border='0' height='32' alt='Contents' width='32' /></a></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Previous:</b>
<a class="sectref" rel="prev" href="contents.html">Contents</a>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="ref.html">The httplib2 Library</a>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="module-httplib2.html">1.1 httplib2 A comprehensive</a>
</div>
</div>
<hr />
<span class="release-info">Release 0.3, documentation updated on Mar 8, 2007.</span>
</div>
<!--End of Navigation Panel-->
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 511 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 B

View File

@@ -0,0 +1,243 @@
/*
* The first part of this is the standard CSS generated by LaTeX2HTML,
* with the "empty" declarations removed.
*/
/* Century Schoolbook font is very similar to Computer Modern Math: cmmi */
.math { font-family: "Century Schoolbook", serif; }
.math i { font-family: "Century Schoolbook", serif;
font-weight: bold }
.boldmath { font-family: "Century Schoolbook", serif;
font-weight: bold }
/*
* Implement both fixed-size and relative sizes.
*
* I think these can be safely removed, as it doesn't appear that
* LaTeX2HTML ever generates these, even though these are carried
* over from the LaTeX2HTML stylesheet.
*/
small.xtiny { font-size : xx-small; }
small.tiny { font-size : x-small; }
small.scriptsize { font-size : smaller; }
small.footnotesize { font-size : small; }
big.xlarge { font-size : large; }
big.xxlarge { font-size : x-large; }
big.huge { font-size : larger; }
big.xhuge { font-size : xx-large; }
/*
* Document-specific styles come next;
* these are added for the Python documentation.
*
* Note that the size specifications for the H* elements are because
* Netscape on Solaris otherwise doesn't get it right; they all end up
* the normal text size.
*/
body { color: #000000;
background-color: #ffffff; }
a:link:active { color: #ff0000; }
a:link:hover { background-color: #bbeeff; }
a:visited:hover { background-color: #bbeeff; }
a:visited { color: #551a8b; }
a:link { color: #0000bb; }
h1, h2, h3, h4, h5, h6 { font-family: avantgarde, sans-serif;
font-weight: bold; }
h1 { font-size: 180%; }
h2 { font-size: 150%; }
h3, h4 { font-size: 120%; }
/* These are section titles used in navigation links, so make sure we
* match the section header font here, even it not the weight.
*/
.sectref { font-family: avantgarde, sans-serif; }
/* And the label before the titles in navigation: */
.navlabel { font-size: 85%; }
/* LaTeX2HTML insists on inserting <br> elements into headers which
* are marked with \label. This little bit of CSS magic ensures that
* these elements don't cause spurious whitespace to be added.
*/
h1>br, h2>br, h3>br,
h4>br, h5>br, h6>br { display: none; }
code, tt { font-family: "lucida typewriter", lucidatypewriter,
monospace; }
var { font-family: times, serif;
font-style: italic;
font-weight: normal; }
.Unix { font-variant: small-caps; }
.typelabel { font-family: lucida, sans-serif; }
.navigation td { background-color: #99ccff;
font-weight: bold;
font-family: avantgarde, sans-serif;
font-size: 110%; }
div.warning { background-color: #fffaf0;
border: thin solid black;
padding: 1em;
margin-left: 2em;
margin-right: 2em; }
div.warning .label { font-family: sans-serif;
font-size: 110%;
margin-right: 0.5em; }
div.note { background-color: #fffaf0;
border: thin solid black;
padding: 1em;
margin-left: 2em;
margin-right: 2em; }
div.note .label { margin-right: 0.5em;
font-family: sans-serif; }
address { font-size: 80%; }
.release-info { font-style: italic;
font-size: 80%; }
.titlegraphic { vertical-align: top; }
.verbatim pre { color: #00008b;
font-family: "lucida typewriter", lucidatypewriter,
monospace;
font-size: 90%; }
.verbatim { margin-left: 2em; }
.verbatim .footer { padding: 0.05in;
font-size: 85%;
background-color: #99ccff;
margin-right: 0.5in; }
.grammar { background-color: #99ccff;
margin-right: 0.5in;
padding: 0.05in; }
.grammar-footer { padding: 0.05in;
font-size: 85%; }
.grammartoken { font-family: "lucida typewriter", lucidatypewriter,
monospace; }
.productions { background-color: #bbeeff; }
.productions a:active { color: #ff0000; }
.productions a:link:hover { background-color: #99ccff; }
.productions a:visited:hover { background-color: #99ccff; }
.productions a:visited { color: #551a8b; }
.productions a:link { color: #0000bb; }
.productions table { vertical-align: baseline;
empty-cells: show; }
.productions > table td,
.productions > table th { padding: 2px; }
.productions > table td:first-child,
.productions > table td:last-child {
font-family: "lucida typewriter",
lucidatypewriter,
monospace;
}
/* same as the second selector above, but expressed differently for Opera */
.productions > table td:first-child + td + td {
font-family: "lucida typewriter",
lucidatypewriter,
monospace;
vertical-align: baseline;
}
.productions > table td:first-child + td {
padding-left: 1em;
padding-right: 1em;
}
.productions > table tr { vertical-align: baseline; }
.email { font-family: avantgarde, sans-serif; }
.mailheader { font-family: avantgarde, sans-serif; }
.mimetype { font-family: avantgarde, sans-serif; }
.newsgroup { font-family: avantgarde, sans-serif; }
.url { font-family: avantgarde, sans-serif; }
.file { font-family: avantgarde, sans-serif; }
.guilabel { font-family: avantgarde, sans-serif; }
.realtable { border-collapse: collapse;
border-color: black;
border-style: solid;
border-width: 0px 0px 2px 0px;
empty-cells: show;
margin-left: auto;
margin-right: auto;
padding-left: 0.4em;
padding-right: 0.4em;
}
.realtable tbody { vertical-align: baseline; }
.realtable tfoot { display: table-footer-group; }
.realtable thead { background-color: #99ccff;
border-width: 0px 0px 2px 1px;
display: table-header-group;
font-family: avantgarde, sans-serif;
font-weight: bold;
vertical-align: baseline;
}
.realtable thead :first-child {
border-width: 0px 0px 2px 0px;
}
.realtable thead th { border-width: 0px 0px 2px 1px }
.realtable td,
.realtable th { border-color: black;
border-style: solid;
border-width: 0px 0px 1px 1px;
padding-left: 0.4em;
padding-right: 0.4em;
}
.realtable td:first-child,
.realtable th:first-child {
border-left-width: 0px;
vertical-align: baseline;
}
.center { text-align: center; }
.left { text-align: left; }
.right { text-align: right; }
.refcount-info { font-style: italic; }
.refcount-info .value { font-weight: bold;
color: #006600; }
/*
* Some decoration for the "See also:" blocks, in part inspired by some of
* the styling on Lars Marius Garshol's XSA pages.
* (The blue in the navigation bars is #99CCFF.)
*/
.seealso { background-color: #fffaf0;
border: thin solid black;
padding: 0pt 1em 4pt 1em; }
.seealso > .heading { font-size: 110%;
font-weight: bold; }
/*
* Class 'availability' is used for module availability statements at
* the top of modules.
*/
.availability .platform { font-weight: bold; }
/*
* Additional styles for the distutils package.
*/
.du-command { font-family: monospace; }
.du-option { font-family: avantgarde, sans-serif; }
.du-filevar { font-family: avantgarde, sans-serif;
font-style: italic; }
.du-xxx:before { content: "** ";
font-weight: bold; }
.du-xxx:after { content: " **";
font-weight: bold; }
/*
* Some specialization for printed output.
*/
@media print {
.online-navigation { display: none; }
}

View File

@@ -0,0 +1,129 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="ref.css" type='text/css' />
<link rel="first" href="ref.html" title='The httplib2 Library' />
<link rel='contents' href='contents.html' title="Contents" />
<link rel='last' href='about.html' title='About this document...' />
<link rel='help' href='about.html' title='About this document...' />
<link rel="next" href="contents.html" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name='aesop' content='information' />
<title>The httplib2 Library</title>
</head>
<body>
<div class="navigation">
<div id='top-navigation-panel' xml:id='top-navigation-panel'>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></td>
<td class='online-navigation'><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></td>
<td class='online-navigation'><a rel="next" title="Contents"
href="contents.html"><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></a></td>
<td align="center" width="100%">The httplib2 Library</td>
<td class='online-navigation'><a rel="contents" title="Table of Contents"
href="contents.html"><img src='contents.png'
border='0' height='32' alt='Contents' width='32' /></a></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="contents.html">Contents</a>
</div>
<hr /></div>
</div>
<!--End of Navigation Panel-->
<p>
<div class="titlepage">
<div class='center'>
<h1>The httplib2 Library</h1>
<p><b><font size="+2">Joe Gregorio</font></b></p>
<p>
Email: <span class="email">joe@bitworking.org</span>
</p>
<p><strong>Release 0.3</strong><br />
<strong>Mar 8, 2007</strong></p>
<p></p>
</div>
</div>
<p>
<h3>Abstract:</h3>
<div class="ABSTRACT">
<p>
The <tt class="module">httplib2</tt> module is a comprehensive HTTP client library
that handles caching, keep-alive, compression, redirects and
many kinds of authentication.
<p>
</div>
<p>
<p>
<p><br /></p><hr class='online-navigation' />
<div class='online-navigation'>
<!--Table of Child-Links-->
<a name="CHILD_LINKS"></a>
<ul class="ChildLinks">
<li><a href="contents.html">Contents</a>
<li><a href="node2.html">1. Reference</a>
<ul>
<li><a href="module-httplib2.html">1.1 <tt class="module">httplib2</tt>
A comprehensive HTTP client library.</a>
<ul>
<li><a href="http-objects.html">1.1.1 Http Objects</a>
<li><a href="cache-objects.html">1.1.2 Cache Objects</a>
<li><a href="response-objects.html">1.1.3 Response Objects</a>
<li><a href="httplib2-example.html">1.1.4 Examples</a>
</ul>
</ul>
<li><a href="about.html">About this document ...</a>
</ul>
<!--End of Table of Child-Links-->
</div>
<div class="navigation">
<div class='online-navigation'>
<p></p><hr />
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></td>
<td class='online-navigation'><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></td>
<td class='online-navigation'><a rel="next" title="Contents"
href="contents.html"><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></a></td>
<td align="center" width="100%">The httplib2 Library</td>
<td class='online-navigation'><a rel="contents" title="Table of Contents"
href="contents.html"><img src='contents.png'
border='0' height='32' alt='Contents' width='32' /></a></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="contents.html">Contents</a>
</div>
</div>
<hr />
<span class="release-info">Release 0.3, documentation updated on Mar 8, 2007.</span>
</div>
<!--End of Navigation Panel-->
</body>
</html>

View File

@@ -0,0 +1,151 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="ref.css" type='text/css' />
<link rel="first" href="ref.html" title='The httplib2 Library' />
<link rel='contents' href='contents.html' title="Contents" />
<link rel='last' href='about.html' title='About this document...' />
<link rel='help' href='about.html' title='About this document...' />
<link rel="next" href="httplib2-example.html" />
<link rel="prev" href="cache-objects.html" />
<link rel="parent" href="module-httplib2.html" />
<link rel="next" href="httplib2-example.html" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name='aesop' content='information' />
<title>1.1.3 Response Objects</title>
</head>
<body>
<div class="navigation">
<div id='top-navigation-panel' xml:id='top-navigation-panel'>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><a rel="prev" title="1.1.2 cache Objects"
href="cache-objects.html"><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></a></td>
<td class='online-navigation'><a rel="parent" title="1.1 httplib2 A comprehensive"
href="module-httplib2.html"><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></a></td>
<td class='online-navigation'><a rel="next" title="1.1.4 Examples"
href="httplib2-example.html"><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></a></td>
<td align="center" width="100%">The httplib2 Library</td>
<td class='online-navigation'><a rel="contents" title="Table of Contents"
href="contents.html"><img src='contents.png'
border='0' height='32' alt='Contents' width='32' /></a></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Previous:</b>
<a class="sectref" rel="prev" href="cache-objects.html">1.1.2 Cache Objects</a>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="module-httplib2.html">1.1 httplib2 A comprehensive</a>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="httplib2-example.html">1.1.4 Examples</a>
</div>
<hr /></div>
</div>
<!--End of Navigation Panel-->
<h2><a name="SECTION002130000000000000000"></a>
<a name="response-objects"></a>
<br>
1.1.3 Response Objects
</h2>
<p>
Response objects are derived from <tt class="class">dict</tt> and map
header names (lower case with the trailing colon removed)
to header values. In addition to the dict methods
a Response object also has:
<p>
<dl><dt><b><tt id='l2h-26' xml:id='l2h-26' class="member">fromcache</tt></b></dt>
<dd>
If <code>true</code> the the response was returned from the cache.
</dl>
<p>
<dl><dt><b><tt id='l2h-27' xml:id='l2h-27' class="member">version</tt></b></dt>
<dd>
The version of HTTP that the server supports. A value
of 11 means '1.1'.
</dl>
<p>
<dl><dt><b><tt id='l2h-28' xml:id='l2h-28' class="member">status</tt></b></dt>
<dd>
The numerical HTTP status code returned in the response.
</dl>
<p>
<dl><dt><b><tt id='l2h-29' xml:id='l2h-29' class="member">reason</tt></b></dt>
<dd>
The human readable component of the HTTP response status code.
</dl>
<p>
<dl><dt><b><tt id='l2h-30' xml:id='l2h-30' class="member">previous</tt></b></dt>
<dd>
If redirects are followed then the <tt class="class">Response</tt> object returned
is just for the very last HTTP request and <var>previous</var> points to
the previous <tt class="class">Response</tt> object. In this manner they form a chain
going back through the responses to the very first response.
Will be <code>None</code> if there are no previous respones.
</dl>
<p>
The Response object also populates the header <code>content-location</code>, that
contains the URI that was ultimately requested. This is useful if
redirects were encountered, you can determine the ultimate URI that
the request was sent to. All Response objects contain this key value,
including <code>previous</code> responses so you can determine the entire
chain of redirects. If <tt class="member">Http.force_exception_to_status_code</tt> is <code>True</code>
and the number of redirects has exceeded the number of allowed number
of redirects then the <tt class="class">Response</tt> object will report the error
in the status code, but the complete chain of previous responses will
still be in tact.
<p>
<div class="navigation">
<div class='online-navigation'>
<p></p><hr />
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><a rel="prev" title="1.1.2 cache Objects"
href="cache-objects.html"><img src='previous.png'
border='0' height='32' alt='Previous Page' width='32' /></a></td>
<td class='online-navigation'><a rel="parent" title="1.1 httplib2 A comprehensive"
href="module-httplib2.html"><img src='up.png'
border='0' height='32' alt='Up one Level' width='32' /></a></td>
<td class='online-navigation'><a rel="next" title="1.1.4 Examples"
href="httplib2-example.html"><img src='next.png'
border='0' height='32' alt='Next Page' width='32' /></a></td>
<td align="center" width="100%">The httplib2 Library</td>
<td class='online-navigation'><a rel="contents" title="Table of Contents"
href="contents.html"><img src='contents.png'
border='0' height='32' alt='Contents' width='32' /></a></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
border='0' height='32' alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Previous:</b>
<a class="sectref" rel="prev" href="cache-objects.html">1.1.2 Cache Objects</a>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="module-httplib2.html">1.1 httplib2 A comprehensive</a>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="httplib2-example.html">1.1.4 Examples</a>
</div>
</div>
<hr />
<span class="release-info">Release 0.3, documentation updated on Mar 8, 2007.</span>
</div>
<!--End of Navigation Panel-->
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 577 B

View File

@@ -0,0 +1,13 @@
cryptography==35.0.0;python_version>="3.6"
flake8==3.9.2
future==0.16.0
mock==2.0.0;python_version<"3.3"
pytest-cov==2.12.1
pytest-forked==1.3.0
pytest-randomly==1.2.3
pytest-timeout==1.4.2
pytest-xdist==1.34.0
pytest==4.6.11;python_version<="3.4"
pytest==6.1.2;python_version>"3.4" and python_version<"3.10"
pytest==6.2.5;python_version>="3.10"
six==1.10.0

View File

@@ -0,0 +1,2 @@
pyparsing>=2.4.2,<3; python_version<'3.0' # TODO remove after dropping Python2 support
pyparsing>=2.4.2,<4, !=3.0.0, !=3.0.1, !=3.0.2, !=3.0.3; python_version>'3.0'

View File

@@ -0,0 +1,60 @@
#!not for running standalone, see .github/workflows/test.yaml
cache_dir=$HOME/.cache
install_dir=$cache_dir/py3-openssl11
python_version="3.7.3"
openssl_version="1.1.1f"
cpucount=$(nproc --all)
export PYTHONDONTWRITEBYTECODE=1
#rm -rf $cache_dir/* # uncomment to rebuild
if [[ ! -x "$install_dir/bin/python" ]] || [[ $($install_dir/bin/python -V) != "Python $python_version" ]] ; then
(
mkdir -p /tmp/source
cd /tmp/source
# Compile OpenSSL
curl -fLOsS "https://www.openssl.org/source/openssl-$openssl_version.tar.gz"
echo "Extracting OpenSSL..."
tar xf openssl-$openssl_version.tar.gz
cd ./openssl-$openssl_version
echo "Compiling OpenSSL $openssl_version..."
./config shared --prefix=$install_dir
echo "Running make for OpenSSL..."
make -j$cpucount -s
echo "Running make install for OpenSSL..."
make install_sw >/dev/null
export LD_LIBRARY_PATH=$install_dir/lib
cd /tmp/source
sudo apt install -qq --yes libffi-dev
# Compile latest Python
curl -fLOsS "https://www.python.org/ftp/python/$python_version/Python-$python_version.tar.xz"
echo "Extracting Python..."
tar xf Python-$python_version.tar.xz
cd ./Python-$python_version
echo "Compiling Python $python_version..."
# Note we are purposefully NOT using optimization flags as they increase compile time 10x
conf_flags="--with-openssl=$install_dir --prefix=$install_dir --with-ensurepip=upgrade"
CFLAGS=-O1 ./configure $conf_flags > /dev/null
make -j$cpucount -s
echo "Installing Python..."
make altinstall bininstall >/dev/null
ln -fs pip3.7 $install_dir/bin/pip3
ln -fs pip3 $install_dir/bin/pip
ln -fs python3 $install_dir/bin/python
# care for CI cache size
find $install_dir -type d -name __pycache__ -print0 |xargs -0 rm -rf
)
fi
export LD_LIBRARY_PATH=$install_dir/lib
export PATH=$install_dir/bin:$PATH
if [[ $(python -V) != "Python $python_version" ]] ; then
echo "Required Python version was not installed into PATH" >&2
exit 1
fi
if [[ $(python -c 'import ssl; print(ssl.OPENSSL_VERSION)') != OpenSSL\ ${openssl_version}* ]] ; then
echo "Required OpenSSL version was not installed into Python" >&2
exit 1
fi

View File

@@ -0,0 +1,61 @@
#!/bin/bash
set -eu
target_dir="${1:-.}"
days=7300
rsa_bits=2048
org="httplib2-test"
server_cn="localhost"
subj_prefix="/C=ZZ/ST=./L=./O=$org/OU=."
main() {
cd "$target_dir"
gen
check
}
check() {
echo "- check keys" >&2
openssl rsa -in ca.key -check -noout
openssl rsa -in client.key -check -noout
openssl rsa -in client_encrypted.key -check -noout -passin pass:12345
openssl rsa -in server.key -check -noout
echo "- check certs" >&2
for f in *.pem ; do
openssl x509 -in "$f" -checkend 3600 -noout
done
}
gen() {
echo "- generate keys, if absent" >&2
[[ -f ca.key ]] || openssl genrsa -out ca.key $rsa_bits
[[ -f client.key ]] || openssl genrsa -out client.key $rsa_bits
[[ -f client_encrypted.key ]] || openssl rsa -in client.key -out client_encrypted.key -aes128 -passout pass:12345
[[ -f server.key ]] || openssl genrsa -out server.key $rsa_bits
echo "- generate CA" >&2
openssl req -batch -new -nodes -x509 -days $days -subj "$subj_prefix/CN=$org-CA" -key ca.key -out ca.pem
openssl req -batch -new -nodes -x509 -days $days -subj "$subj_prefix/CN=$org-CA-unused" -key ca.key -out ca_unused.pem
echo "- generate client cert" >&2
openssl req -batch -new -nodes -out tmp.csr -key client.key -subj "$subj_prefix/CN=$org-client"
openssl x509 -req -in tmp.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out client.crt -days $days -serial -fingerprint
cat client.crt client.key >client.pem
cat client.crt ca.pem client.key >client_chain.pem
echo "- generate encrypted client cert" >&2
openssl req -batch -new -nodes -out tmp.csr -key client_encrypted.key -passin pass:12345 -subj "$subj_prefix/CN=$org-client-enc"
openssl x509 -req -in tmp.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out client_encrypted.crt -days $days -serial -fingerprint
cat client_encrypted.crt client_encrypted.key >client_encrypted.pem
echo "- generate server cert" >&2
openssl req -batch -new -nodes -out tmp.csr -key server.key -subj "$subj_prefix/CN=$server_cn"
openssl x509 -req -in tmp.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out server.crt -days $days -serial -fingerprint
cat server.crt server.key >server.pem
cat server.crt ca.pem server.key >server_chain.pem
rm tmp.csr
}
main

View File

@@ -0,0 +1,244 @@
#!/bin/bash
set -eu
cd "$( dirname "${BASH_SOURCE[0]}" )/.."
version=
version_next=
main() {
local opt_auto=0
while [[ $# -gt 0 ]] ; do
case $1 in
-auto)
opt_auto=1
;;
*)
echo "Usage: $0 [-auto]" >&2
exit 0
;;
esac
shift
done
if [[ "$opt_auto" -eq 1 ]] ; then
auto_prepare_release
else
interactive
fi
}
auto_prepare_release() {
echo 'script/release: auto mode for CI, will check or modify version based on tag' >&2
assert_tree_clean
local is_tag=0
local version_tag=
if version_tag=$(git describe --candidates=0 --tags HEAD 2>/dev/null) ; then
is_tag=1
version_tag=${version_tag##v}
version_check "$version_tag"
fi
local last_tag=
local version_replace=
if [[ "$is_tag" -eq 0 ]] ; then
last_tag=$(git tag --sort=-version:refname |head -n1)
last_tag=${last_tag##v}
version_replace="${last_tag}.post$(date -u +%y%m%d%H%M)"
update_version "setup.py" "s/VERSION =.+/VERSION = \"$version_replace\"/"
update_version "python2/httplib2/__init__.py" "s/__version__ =.+/__version__ = \"$version_replace\"/"
update_version "python3/httplib2/__init__.py" "s/__version__ =.+/__version__ = \"$version_replace\"/"
version_check "$version_replace"
fi
}
interactive() {
echo 'script/release: interactive mode for creating new tagged releases with human assistance' >&2
local branch="${1-$(git symbolic-ref --short HEAD)}"
version=$(python -Es -c "$(egrep '^__version__' python3/httplib2/__init__.py);print(__version__)")
printf "\nbranch: %s httplib2.__version__: '%s'\n" $branch $version >&2
if [[ "$branch" != "master" ]] ; then
echo "Must be on master" >&2
exit 1
fi
assert_tree_clean
last_commit_message=$(git show --format="%s" --no-patch HEAD)
expect_commit_message="v$version release"
if [[ "$last_commit_message" != "$expect_commit_message" ]] ; then
printf "Last commit message: '%s' expected: '%s'\n" "$last_commit_message" "$expect_commit_message" >&2
if confirm "Create release commit? [yN] " ; then
create_commit
elif ! confirm "Continue without proper release commit? [yN] " ; then
exit 1
fi
fi
confirm "Continue? [yN] " || exit 1
echo "Creating tag v$version" >&2
if ! git tag "v$version" ; then
echo "git tag failed " >&2
confirm "Continue still? [yN] " || exit 1
fi
echo "Building package" >&2
find . -name '*.pyc' -o -name '*.pyo' -o -name '*.orig' -delete
rm -rf python{2,3}/.cache
rm -rf build dist
local venv=./venv-release
if [[ ! -d "$venv" ]] ; then
virtualenv $venv
$venv/bin/pip install -U check-manifest pip 'setuptools>=43.0' wheel twine
fi
$venv/bin/python setup.py clean --all
$venv/bin/python setup.py sdist bdist_wheel
$venv/bin/check-manifest || echo "FIXME check-manifest" >&2
if confirm "Upload to PyPI? Use in special situation, normally CI/CD will upload to PyPI. [yN] " ; then
$venv/bin/twine upload dist/* || exit 1
fi
git push --tags
}
create_commit() {
echo "" >&2
echo "Plan:" >&2
echo "1. bump version" >&2
echo "2. update CHANGELOG" >&2
echo "3. commit" >&2
echo "4. run bin/release again" >&2
echo "" >&2
bump_version
edit_news
git diff
confirm "Ready to commit? [Yn] " || exit 1
git commit -a -m "v$version_next release"
echo "Re-exec $0 to continue" >&2
exec $0
}
bump_version() {
local current=$version
echo "Current version: '$current'" >&2
echo -n "Enter next version (empty to abort): " >&2
read version_next
if [[ -z "$version_next" ]] ; then
exit 1
fi
echo "Next version: '$version_next'" >&2
update_version "python3/httplib2/__init__.py" "s/__version__ =.+/__version__ = \"$version_next\"/"
update_version "python2/httplib2/__init__.py" "s/__version__ =.+/__version__ = \"$version_next\"/"
update_version "setup.py" "s/VERSION =.+/VERSION = \"$version_next\"/"
confirm "Confirm changes? [yN] " || exit 1
}
update_version() {
local path="$1"
local sed_expr="$2"
# sed -E --in-place='' -e "s/VERSION =.+/VERSION = \"$version_replace\"/" setup.py
# sed -E --in-place='' -e "s/__version__ =.+/__version__ = \"$version_replace\"/" python2/httplib2/__init__.py python3/httplib2/__init__.py
echo "Updating file '$path'" >&2
if ! sed -E --in-place='' -e "$sed_expr" "$path" ; then
echo "sed error $?" >&2
exit 1
fi
assert_modified "$path"
echo "" >&2
}
edit_news() {
echo "Changes since last release:" >&2
git log --format='%h %an %s' "v$version"^.. -- || exit 1
echo "" >&2
patch -p1 <<EOT
diff a/CHANGELOG b/CHANGELOG
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -0,0 +1,4 @@
+$version_next
+
+ EDIT HERE. Describe important changes and link to more information.
+
EOT
local editor=$(which edit 2>/dev/null)
[[ -z "$editor" ]] && editor="$EDITOR"
if [[ -n "$editor" ]] ; then
if confirm "Open default editor for CHANGELOG? [Yn] " ; then
$editor CHANGELOG
else
confirm "Edit CHANGELOG manually and press any key"
fi
else
echo "Unable to determine default text editor." >&2
confirm "Edit CHANGELOG manually and press any key"
fi
echo "" >&2
assert_modified CHANGELOG
echo "" >&2
confirm "Confirm changes? [yN] " || exit 1
}
assert_modified() {
local path="$1"
if git diff --exit-code "$path" ; then
echo "File '$path' is not modified" >&2
exit 1
fi
}
assert_tree_clean() {
if [[ -n "$(git status --short -uall)" ]] ; then
echo "Tree must be clean. git status:" >&2
echo "" >&2
git status --short -uall
echo "" >&2
exit 1
fi
}
version_check() {
local need=$1
local version_setup=$(python setup.py --version)
local version_py2=$(python -Es -c "$(egrep '^__version__' python2/httplib2/__init__.py);print(__version__)")
local version_py3=$(python -Es -c "$(egrep '^__version__' python3/httplib2/__init__.py);print(__version__)")
if [[ "$version_setup" != "$need" ]] ; then
echo "error: setup.py version=$version_setup expected=$need" >&1
exit 1
fi
if [[ "$version_py2" != "$need" ]] ; then
echo "error: python2/httplib2/__init__.py:__version__=$version_py2 expected=$need" >&1
exit 1
fi
if [[ "$version_py3" != "$need" ]] ; then
echo "error: python3/httplib2/__init__.py:__version__=$version_py3 expected=$need" >&1
exit 1
fi
}
confirm() {
local reply
local prompt="$1"
read -n1 -p "$prompt" reply >&2
echo "" >&2
rc=0
local default_y=" \[Yn\] $"
if [[ -z "$reply" ]] && [[ "$prompt" =~ $default_y ]] ; then
reply="y"
fi
[[ "$reply" != "y" ]] && rc=1
return $rc
}
main "$@"

View File

@@ -0,0 +1,69 @@
#!/bin/bash
set -eux
# By default, run tests with pytest-forked plugin,
# disable in terminal for debugging, you may add --forked
flag_forked="--forked"
if [[ -z "${CI:-}" ]] && [[ -t 1 ]] ; then
flag_forked=""
fi
test_flags=(
$@
$flag_forked
tests/
)
main() {
cd "$( dirname "${BASH_SOURCE[0]}" )/.."
if [[ -n "${CI:-}" ]] ; then
case "${test_group-}" in
package)
# TODO: sdist bdist_wheel
# but wheels don't roll well with our 2/3 split code base
python setup.py sdist
install_check_version "pip"
;;
*)
pip install -e .
httplib2_test_still_run_skipped=1 pytest --fulltrace -k test_303 $@ tests/ || true
httplib2_test_still_run_skipped=1 pytest --fulltrace -k test_head_301 $@ tests/ || true
pytest --fulltrace ${test_flags[@]}
;;
esac
else
if [[ ! -d ./venv-27 ]] ; then
virtualenv --python=python2.7 ./venv-27
fi
if [[ ! -d ./venv-36 ]] ; then
virtualenv --python=python3.6 ./venv-36
fi
./venv-27/bin/pip install -e . -r requirements-test.txt
./venv-27/bin/pytest ${test_flags[@]}
./venv-36/bin/pip install -e . -r requirements-test.txt
./venv-36/bin/pytest ${test_flags[@]}
# FIXME: too many errors
# ./venv-27/bin/flake8 python2/
# ./venv-36/bin/flake8 python3/ tests/
# TODO: sdist bdist_wheel
# but wheels don't roll well with our 2/3 split code base
./venv-36/bin/python setup.py sdist
install_check_version "./venv-27/bin/pip"
install_check_version "./venv-36/bin/pip"
fi
rm -rf ./_httplib2_test_cache
}
install_check_version() {
local pip="$1"
$pip install dist/httplib2*
version_source=$(python setup.py --version)
version_installed=$($pip show httplib2 |fgrep Version: |cut -d' ' -f2)
if [[ "$version_source" != "$version_installed" ]] ; then
echo "error: installed package version=$version_installed does not match source=$version_source" >&2
exit 1
fi
}
main "$@"

View File

@@ -0,0 +1,27 @@
# [bdist_wheel]
# universal = 1
# FIXME universal wheels don't roll well with our 2/3 split code base
# https://github.com/httplib2/httplib2/pull/29
[coverage:run]
[flake8]
exclude = *.egg*,.env,.git,.tox,_*,build*,dist*,venv*,python2/,python3/
ignore = E261,E731,W503
max-line-length = 121
[tool:pytest]
minversion = 3.2
addopts =
# --fulltrace
# -n auto
--cov-config=setup.cfg
--cov=httplib2
--ignore=tests/_TODO_legacy/
--noconftest
--showlocals
--strict-markers
--tb=short
--timeout=17
--verbose
-ra

View File

@@ -0,0 +1,112 @@
import os
import setuptools
import setuptools.command.test
import sys
pkgdir = {"": "python%s" % sys.version_info[0]}
VERSION = "0.20.4"
# `python setup.py test` uses existing Python environment, no virtualenv, no pip.
# Use case: Archlinux package. https://github.com/httplib2/httplib2/issues/103
# Otherwise, use `script/test`
class TestCommand(setuptools.command.test.test):
def run_tests(self):
# pytest may be not installed yet
import pytest
args = ["--forked", "--fulltrace", "--no-cov", "tests/"]
if self.test_suite:
args += ["-k", self.test_suite]
sys.stderr.write("setup.py:test run pytest {}\n".format(" ".join(args)))
errno = pytest.main(args)
sys.exit(errno)
def read_requirements(name):
project_root = os.path.dirname(os.path.abspath(__file__))
with open(os.path.join(project_root, name), "rb") as f:
# remove whitespace and comments
g = (line.decode("utf-8").lstrip().split("#", 1)[0].rstrip() for line in f)
return [l for l in g if l]
setuptools.setup(
name="httplib2",
version=VERSION,
author="Joe Gregorio",
author_email="joe@bitworking.org",
url="https://github.com/httplib2/httplib2",
description="A comprehensive HTTP client library.",
license="MIT",
long_description="""
A comprehensive HTTP client library, ``httplib2`` supports many features left out of other HTTP libraries.
**HTTP and HTTPS**
HTTPS support is only available if the socket module was compiled with SSL support.
**Keep-Alive**
Supports HTTP 1.1 Keep-Alive, keeping the socket open and performing multiple requests over the same connection if possible.
**Authentication**
The following three types of HTTP Authentication are supported. These can be used over both HTTP and HTTPS.
* Digest
* Basic
* WSSE
**Caching**
The module can optionally operate with a private cache that understands the Cache-Control:
header and uses both the ETag and Last-Modified cache validators. Both file system
and memcached based caches are supported.
**All Methods**
The module can handle any HTTP request method, not just GET and POST.
**Redirects**
Automatically follows 3XX redirects on GETs.
**Compression**
Handles both 'deflate' and 'gzip' types of compression.
**Lost update support**
Automatically adds back ETags into PUT requests to resources we have already cached. This implements Section 3.2 of Detecting the Lost Update Problem Using Unreserved Checkout
**Unit Tested**
A large and growing set of unit tests.
""",
package_dir=pkgdir,
packages=["httplib2"],
package_data={"httplib2": ["*.txt"]},
install_requires=read_requirements("requirements.txt"),
tests_require=read_requirements("requirements-test.txt"),
python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
cmdclass={"test": TestCommand},
classifiers=[
"Development Status :: 4 - Beta",
"Environment :: Web Environment",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 2",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.4",
"Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Topic :: Internet :: WWW/HTTP",
"Topic :: Software Development :: Libraries",
],
)