pytest-httpbin-2.0.0/000077500000000000000000000000001442625232000145075ustar00rootroot00000000000000pytest-httpbin-2.0.0/.github/000077500000000000000000000000001442625232000160475ustar00rootroot00000000000000pytest-httpbin-2.0.0/.github/workflows/000077500000000000000000000000001442625232000201045ustar00rootroot00000000000000pytest-httpbin-2.0.0/.github/workflows/main.yaml000066400000000000000000000033521442625232000217170ustar00rootroot00000000000000name: CI on: push: branches: - master tags: - v* pull_request: jobs: tox: runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: python-version: [3.7, 3.8, 3.9, "3.10", 3.11, 3.12-dev] os: [macOS-latest, ubuntu-latest, windows-latest] steps: - name: Checkout uses: actions/checkout@v2 - name: Set Up Python ${{ matrix.python-version }} uses: actions/setup-python@v2 with: python-version: ${{ matrix.python-version }} cache: pip cache-dependency-path: | pyproject.toml setup.cfg setup.py - name: Install run: | pip install tox - name: tox env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: tox -e py,release - name: upload dist uses: actions/upload-artifact@v2 with: name: ${{ matrix.os }}_${{ matrix.python-version}}_dist path: dist all-successful: # https://github.community/t/is-it-possible-to-require-all-github-actions-tasks-to-pass-without-enumerating-them/117957/4?u=graingert runs-on: ubuntu-latest needs: [tox] steps: - name: Download dists for PyPI uses: actions/download-artifact@v2 with: name: ubuntu-latest_3.11_dist path: dist - name: Display structure of donwloaded files run: ls -R - name: Publish package if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') uses: pypa/gh-action-pypi-publish@master with: user: __token__ password: ${{ secrets.pypi_password }} - name: note that all tests succeeded run: echo "🎉" pytest-httpbin-2.0.0/.pre-commit-config.yaml000066400000000000000000000023511442625232000207710ustar00rootroot00000000000000repos: - repo: https://github.com/asottile/pyupgrade rev: v3.4.0 hooks: - id: pyupgrade args: ["--py37-plus"] - repo: https://github.com/psf/black rev: 23.3.0 hooks: - id: black args: ["--target-version", "py37"] - repo: https://github.com/pycqa/isort rev: 5.12.0 hooks: - id: isort - repo: https://github.com/pre-commit/pygrep-hooks rev: v1.10.0 hooks: - id: python-check-blanket-noqa - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.4.0 hooks: - id: check-merge-conflict - id: check-toml - id: check-yaml - id: mixed-line-ending - repo: https://github.com/pre-commit/mirrors-prettier rev: v3.0.0-alpha.9-for-vscode hooks: - id: prettier args: [--prose-wrap=always, --print-width=88] - repo: https://github.com/myint/autoflake rev: v2.1.1 hooks: - id: autoflake args: - --in-place - --remove-all-unused-imports - --expand-star-imports - --remove-duplicate-keys - --remove-unused-variables - repo: https://github.com/pycqa/flake8 rev: 6.0.0 hooks: - id: flake8 additional_dependencies: [flake8-2020] pytest-httpbin-2.0.0/DESCRIPTION.rst000066400000000000000000000022221442625232000170220ustar00rootroot00000000000000pytest-httpbin ============== httpbin is an amazing web service for testing HTTP libraries. It has several great endpoints that can test pretty much everything you need in a HTTP library. The only problem is: maybe you don't want to wait for your tests to travel across the Internet and back to make assertions against a remote web service. Enter pytest-httpbin. Pytest-httpbin creates a pytest "fixture" that is dependency-injected into your tests. It automatically starts up a HTTP server in a separate thread running httpbin and provides your test with the URL in the fixture. Check out this example: .. code-block:: python def test_that_my_library_works_kinda_ok(httpbin): assert requests.get(httpbin.url + '/get/').status_code == 200 This replaces a test that might have looked like this before: .. code-block:: python def test_that_my_library_works_kinda_ok(): assert requests.get('http://httpbin.org/get').status_code == 200 pytest-httpbin also supports https and includes its own CA cert you can use. Check out `the full documentation`_ on the github page. .. _the full documentation: https://github.com/kevin1024/pytest-httpbin pytest-httpbin-2.0.0/MANIFEST.in000066400000000000000000000003061442625232000162440ustar00rootroot00000000000000# If using Python 2.6 or less, then have to include package data, even though # it's already declared in setup.py include pytest_httpbin/certs/* include DESCRIPTION.rst recursive-include tests *.py pytest-httpbin-2.0.0/README.md000066400000000000000000000226271442625232000157770ustar00rootroot00000000000000# pytest-httpbin [![Build Status](https://github.com/kevin1024/pytest-httpbin/actions/workflows/main.yaml/badge.svg)](https://github.com/kevin1024/pytest-httpbin/actions/workflows/main.yaml) [httpbin](https://httpbin.org/) is an amazing web service for testing HTTP libraries. It has several great endpoints that can test pretty much everything you need in a HTTP library. The only problem is: maybe you don't want to wait for your tests to travel across the Internet and back to make assertions against a remote web service (speed), and maybe you want to work offline (convenience). Enter **pytest-httpbin**. Pytest-httpbin creates a [pytest fixture](https://pytest.org/latest/fixture.html) that is dependency-injected into your tests. It automatically starts up a HTTP server in a separate thread running httpbin and provides your test with the URL in the fixture. Check out this example: ```python def test_that_my_library_works_kinda_ok(httpbin): assert requests.get(httpbin.url + '/get').status_code == 200 ``` This replaces a test that might have looked like this before: ```python def test_that_my_library_works_kinda_ok(): assert requests.get('http://httpbin.org/get').status_code == 200 ``` If you're making a lot of requests to httpbin, it can radically speed up your tests. ![demo](http://i.imgur.com/heNOQLP.gif) # HTTPS support pytest-httpbin also supports HTTPS: ```python def test_that_my_library_works_kinda_ok(httpbin_secure): assert requests.get(httpbin_secure.url + '/get/').status_code == 200 ``` It's actually starting 2 web servers in separate threads in the background: one HTTP and one HTTPS. The servers are started on a random port (see below for fixed port support), on the loopback interface on your machine. Pytest-httpbin includes a self-signed certificate. If your library verifies certificates against a CA (and it should), you'll have to add the CA from pytest-httpbin. The path to the pytest-httpbin CA bundle can by found like this `python -m pytest_httpbin.certs`. For example in requests, you can set the `REQUESTS_CA_BUNDLE` python path. You can run your tests like this: ```bash REQUESTS_CA_BUNDLE=`python -m pytest_httpbin.certs` py.test tests/ ``` # API of the injected object The injected object has the following attributes: - url - port - host and the following methods: - join(string): Returns the results of calling `urlparse.urljoin` with the url from the injected server automatically applied as the first argument. You supply the second argument Also, I defined `__add__` on the object to append to `httpbin.url`. This means you can do stuff like `httpbin + '/get'` instead of `httpbin.url + '/get'`. ## Testing both HTTP and HTTPS endpoints with one test If you ever find yourself needing to test both the http and https version of and endpoint, you can use the `httpbin_both` funcarg like this: ```python def test_that_my_library_works_kinda_ok(httpbin_both): assert requests.get(httpbin_both.url + '/get/').status_code == 200 ``` Through the magic of pytest parametrization, this function will actually execute twice: once with an http url and once with an https url. ## Using pytest-httpbin with unittest-style test cases I have provided 2 additional fixtures to make testing with class-based tests easier. I have also provided a couple decorators that provide some syntactic sugar around the pytest method of adding the fixtures to class-based tests. Just add the `use_class_based_httpbin` and/or `use_class_based_httpbin_secure` class decorators to your class, and then you can access httpbin using self.httpbin and self.httpbin_secure. ```python import pytest_httpbin @pytest_httpbin.use_class_based_httpbin @pytest_httpbin.use_class_based_httpbin_secure class TestClassBassedTests(unittest.TestCase): def test_http(self): assert requests.get(self.httpbin.url + '/get').response def test_http_secure(self): assert requests.get(self.httpbin_secure.url + '/get').response ``` ## Running the server on fixed port Sometimes a randomized port can be a problem. Worry not, you can fix the port number to a desired value with the `HTTPBIN_HTTP_PORT` and `HTTPBIN_HTTPS_PORT` environment variables. If those are defined during pytest plugins are loaded, `httbin` and `httpbin_secure` fixtures will run on given ports. You can run your tests like this: ```bash HTTPBIN_HTTP_PORT=8080 HTTPBIN_HTTPS_PORT=8443 py.test tests/ ``` ## Installation [![PyPI Version](https://img.shields.io/pypi/v/pytest-httpbin.svg)](https://pypi.org/project/pytest-httpbin/) [![Supported Versions](https://img.shields.io/pypi/pyversions/pytest-httpbin.svg)](https://pypi.org/project/pytest-httpbin/) To install from [PyPI](https://pypi.org/project/pytest-httpbin/), all you need to do is this: ```bash pip install pytest-httpbin ``` and your tests executed by pytest all will have access to the `httpbin` and `httpbin_secure` funcargs. Cool right? ## Support and dependencies pytest-httpbin supports Python 2.6, 2.7, 3.4-3.6, and pypy. It will automatically install httpbin and flask when you install it from PyPI. [httpbin](https://github.com/postmanlabs/httpbin) itself does not support python 2.6 as of version 0.6.0, when the Flask-common dependency was added. If you need python 2.6 support pin the httpbin version to 0.5.0 ## Running the pytest-httpbin test suite If you want to run pytest-httpbin's test suite, you'll need to install requests and pytest, and then use the ./runtests.sh script. ```bash pip install pytest ./runtests.sh ``` Also, you can use tox to run the tests on all supported python versions: ```bash pip install tox tox ``` ## Changelog - 2.0.0 - Drop support for Python 2.6, 2.7, 3.4, 3.5 and 3.6 (#68) - Add support for Python 3.7, 3.8, 3.9 and 3.10 (#68) - Avoid deprecation warnings and resource warnings (#71) - Add support for Python 3.11 and 3.12, drop dependency on six (#76) - 1.0.2 - Switch from travis to github actions - This will be the last release to support Python 2.6, 2.7 or 3.6 - 1.0.1 - httpbin_secure: fix redirect Location to have "https://" scheme (#62) - thanks @immerrr - Include regression tests in pypi tarball (#56) - thanks @kmosiejczuk - 1.0.0 - Update included self-signed cert to include IP address in SAN (See #52). Full version bump because this could be a breaking change for those depending on the certificate missing the IP address in the SAN (as it seems the requests test suite does) - Only use @pytest.fixture decorator once (thanks @hroncok) - Fix a few README typos (thanks @hemberger) - 0.3.0 - Allow to run httpbin on fixed port using environment variables (thanks @hroncok) - Allow server to be thread.join()ed (thanks @graingert) - Add support for Python 3.6 (thanks @graingert) - 0.2.3: - Another attempt to fix #32 (Rare bug, only happens on Travis) - 0.2.2: - Fix bug with python3 - 0.2.1: - Attempt to fix strange, impossible-to-reproduce bug with broken SSL certs that only happens on Travis (#32) [Bad release, breaks py3] - 0.2.0: - Remove threaded HTTP server. I built it for Requests, but they deleted their threaded test since it didn't really work very well. The threaded server seems to cause some strange problems with HTTP chunking, so I'll just remove it since nobody is using it (I hope) - 0.1.1: - Fix weird hang with SSL on pypy (again) - 0.1.0: - Update server to use multithreaded werkzeug server - 0.0.7: - Update the certificates (they expired) - 0.0.6: - Fix an issue where pypy was hanging when a request was made with an invalid certificate - 0.0.5: - Fix broken version parsing in 0.0.4 - 0.0.4: - **Bad release: Broken version parsing** - Fix `BadStatusLine` error that occurs when sending multiple requests in a single session (PR #16). Thanks @msabramo! - Fix #9 ("Can't be installed at the same time than pytest?") (PR #14). Thanks @msabramo! - Add `httpbin_ca_bundle` pytest fixture. With this fixture there is no need to specify the bundle on every request, as it will automatically set `REQUESTS_CA_BUNDLE` if using [requests](https://docs.python-requests.org/). And you don't have to care about where it is located (PR #8). Thanks @t-8ch! - 0.0.3: Add a couple test fixtures to make testing old class-based test suites easier - 0.0.2: Fixed a couple bugs with the wsgiref server to bring behavior in line with httpbin.org, thanks @jakubroztocil for the bug reports - 0.0.1: Initial release ## License The MIT License (MIT) Copyright (c) 2014-2019 Kevin McCarthy 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. pytest-httpbin-2.0.0/pyproject.toml000066400000000000000000000000001442625232000174110ustar00rootroot00000000000000pytest-httpbin-2.0.0/pytest_httpbin/000077500000000000000000000000001442625232000175675ustar00rootroot00000000000000pytest-httpbin-2.0.0/pytest_httpbin/__init__.py000066400000000000000000000005551442625232000217050ustar00rootroot00000000000000import os import pytest here = os.path.dirname(__file__) version_file = os.path.join(here, "version.py") with open(version_file) as f: code = compile(f.read(), version_file, "exec") exec(code) use_class_based_httpbin = pytest.mark.usefixtures("class_based_httpbin") use_class_based_httpbin_secure = pytest.mark.usefixtures("class_based_httpbin_secure") pytest-httpbin-2.0.0/pytest_httpbin/certs.py000066400000000000000000000010011442625232000212510ustar00rootroot00000000000000""" certs.py ~~~~~~~~ This module returns the preferred default CA certificate bundle. If you are packaging pytest-httpbin, e.g., for a Linux distribution or a managed environment, you can change the definition of where() to return a separately packaged CA bundle. """ import os.path def where(): """Return the preferred certificate bundle.""" # vendored bundle inside Requests return os.path.join(os.path.dirname(__file__), "certs", "cacert.pem") if __name__ == "__main__": print(where()) pytest-httpbin-2.0.0/pytest_httpbin/certs/000077500000000000000000000000001442625232000207075ustar00rootroot00000000000000pytest-httpbin-2.0.0/pytest_httpbin/certs/cacert.pem000066400000000000000000000035121442625232000226540ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIIFNjCCAx4CCQCxvkG1KFHCuzANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJV UzELMAkGA1UECAwCSEkxEjAQBgNVBAcMCWtldmluMTAyNDEtMCsGA1UECgwkcHl0 ZXN0LWh0dHBiaW4gQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTE5MDIxMTE1NDgz MFoXDTM5MDIwNjE1NDgzMFowXTELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkhJMRIw EAYDVQQHDAlrZXZpbjEwMjQxLTArBgNVBAoMJHB5dGVzdC1odHRwYmluIENlcnRp ZmljYXRlIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB ANbSc+N9CYgRPVMIQTEXqDeFG1GvHjgjhwN/nV/JGqmG8ZgD26WMRs9b6yHdD8Xx Wgq6IqOm+dzkfRCnELPtYn96l1SSfZBEAAo5137ZzaKLLvKp2cjUwLN3Y7ZlF8CV rZT7ObII9J0Xt67XrdPXeKIVzZjg9CtPFFE+OzrLl8UNH2N5zGxJ43G0v1f+5qYu /oIHRiN4Wdd53MJaFOXMzI43/vYztHpW4tsKhmR8cTgpdbM4yCWU5mYDz+SPsMvN 7OVcTW+ALifxIjr/J0l1uIFfq00UgPv1SaLGL1bfrQFVpPfRl6mNBRf1xszDXk4x xsv67EpWdQ2UIHvP9LMe+IeVqf+V+9u2VuijYeZo6T8lCLPRznqO24pkTkioSfpT tluxWaY2/hdlYBWVuK5pV49L6ls6ci03Q+LDzN29D+rfGraWDWWbkF/8qQZOKE85 /rW6hpsEgOVgtVVTm2wCH7v1VpEnfj9LBQgvrDpawwP9OQyueGnrMC6Oqsx7L8MM 2w+4qZ7/XlrrPlxMorNyQsFpDI0tui3qiggvlHUFjn9CDfulAZlrqExuAmrXzpJo sEfwmwqXijrtZqBm9nrTC2piUUcE7eqKPk/qsBDf+Y+WJxszyRrBron3FjI/IgLc efa8ncsdyFybvIJ3RIeI01Ah3iTmxSjxW/5zZEamhsdPAgMBAAEwDQYJKoZIhvcN AQELBQADggIBAEkLPQ/X29BWQus+uRqcpHnv3N82ymOfVTzlLzlddRXTJY2G6aMO lSRoTDIDplyCPuS+mapqXh3TjeUeDNHriAmS+CCACpsYy11CdLsc7TwonApa4ttL b9ubmZ+QpK+5aTXiglxqB/EMzT9SNOCxZb89+ONg6J/4AgW19OkKqwIsiBN7l7NO pi5tLE9YqR4KaQRs/3meAj7xjjzWkXW7w6KbTAc5IbrzejThizmWsJjWM5N/BkZH GN/MCQ2cWZ7U1YkwgBX2VUeR/xqgyBWBITj5SFoIMjN6+DFC/Cegu0OdmQ4lZAVh dFVgfQd5FSdIvAo4tnDiOWJzIoF/RwybgqHRYBg4RBLgBTBqYfgtc0R5us6E/QNa rGRHiq6JOeCoCvWvkWOa/DslmFD+12TWjSUIuYbse6lqiEwCpF16M6ZIJNpAJh80 sAQyY9UnPsBsqkptwgeGoXk+1t3NTteetMKApgC+OuxZi7ijbCArVFwpHp2M22nJ AShGgjxPNZV4AtR1HKAYW+C12IbuFMrS6uby8fj+dLJXqjq3kxuE1h8oQsME/wF9 FT8aFVhZJ+VbNNFtcdrjNnN++mBm9mBC79ANbLG2N5FZZJynicwRqWKDu52u6t20 buVa8cFuOSK2Prz/3RCYjPlszebE26KNCMHPG3U0ZIUJM2hmlBfRVwZW -----END CERTIFICATE----- pytest-httpbin-2.0.0/pytest_httpbin/certs/cert.pem000066400000000000000000000031061442625232000223470ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIIEdjCCAl6gAwIBAgIJAJZYfkBVjU9hMA0GCSqGSIb3DQEBCwUAMF0xCzAJBgNV BAYTAlVTMQswCQYDVQQIDAJISTESMBAGA1UEBwwJa2V2aW4xMDI0MS0wKwYDVQQK DCRweXRlc3QtaHR0cGJpbiBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMTkwMjEx MTY0OTM5WhcNMzkwMjA2MTY0OTM5WjB4MQswCQYDVQQGEwJISTESMBAGA1UECAwJ a2V2aW4xMDI0MQ8wDQYDVQQHDAZLYWlsdWExFzAVBgNVBAoMDlB5dGVzdC1odHRw YmluMRcwFQYDVQQLDA5QeXRlc3QtaHR0cGJpbjESMBAGA1UEAwwJMTI3LjAuMC4x MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvSQUs9vEg5m6GUeEK44o 2fZzTMMfiRCUqPTyh1LGen7A2CSPYMRst9mb9ygZjQGqoVKIAQC+RuEsMl8pjw/g vKoJPcKwONxnOwILbLsuGZ+szgx/q9IZ3BQR5pXenJP8A9hCeUzREU6OjFqQEB4g zjsBhUsf5cfn+YCKPhvWflSy6tgjjHK5ocNSoWvmeDbz1elgd7XR8tIYlgT8t8aA n66IRtONUJRuik/3mOdQUdC2E0dOVD2ivcSKLbudGGbVscEl0JZNfZhgqUCcEMSQ kHNxlXmWd67X6VzBKjq0GoYa5WPsZtT3kpdyiP0runb0z/ciDKLJ5CbeBaWeN3bW qwIDAQABox4wHDAaBgNVHREEEzARgglsb2NhbGhvc3SHBH8AAAEwDQYJKoZIhvcN AQELBQADggIBAFC2Ozs6U3Ia01Lzbm+aIwDRy5A4DSZ8q5OVQxmcE0vQ+yOHhQt4 bh5z3+q09Gycnsb7Ydwg6nNgT4Jbyq4eyjS73R4VHerdBdFyujEv6tVwho1mtLSc wwLbhp6YvbI7wsomc3FIIgOw2Oi6ZGQQneQikXm0yTe6+MZcPs9+4D2lwPFhxGnA +6lAsj+zvaZknvVr9lfhbP4RvCMnyNZsf4Z2bv0i0cdA4uaHRQD9KB6DyLGTLjHZ YDZS52UINsoPehERWf/I/z/n4K1WKzCY6By3pRSKOHNhdo7UHg659AHByf5kBLGX ByvVMZ4XzpoUYcT+93EsoU0jU/i4zKbY2z27ny9Erb1JzwYIXtUoAO1tkqZrtGFs LG+l8T4PazRDe0redwb3XkNRzS54J/ocrUBeNhFDQJjmLOMflsnLDRPxnZzEkGjm +svpq0UChPSiEkaCdF1gL5euoPIuQ6KpSMbf+WLjuFhwnMZyvbh1xEd7MnLg7qU8 karqmiEiyYzmhn7ygcTCn7Hgo98tIzydo0+9fk5pmyzE5PjI1uVJJ76JXK74aJPy iUK9OOrW1ZE3LGP8ZCtZMAciV3GHRBXHUIslu7PUxj6LHXQz+7qDO6xmuEp4emki +vNHdGEVtxW3WObO+i+V/hWIgXubXqxlSUUG7AfAt65278l2s5N+i4+p -----END CERTIFICATE----- pytest-httpbin-2.0.0/pytest_httpbin/certs/etc/000077500000000000000000000000001442625232000214625ustar00rootroot00000000000000pytest-httpbin-2.0.0/pytest_httpbin/certs/etc/README.md000066400000000000000000000001401442625232000227340ustar00rootroot00000000000000Here is how I generated these: https://gist.github.com/fntlnz/cf14feb5a46b2eda428e000157447309 pytest-httpbin-2.0.0/pytest_httpbin/certs/etc/certificate.conf000066400000000000000000000004341442625232000246140ustar00rootroot00000000000000[req] default_bits = 2048 prompt = no default_md = sha256 req_extensions = req_ext distinguished_name = dn [dn] C = HI ST = kevin1024 L = Kailua O = Pytest-httpbin OU = Pytest-httpbin CN = 127.0.0.1 [req_ext] subjectAltName = @alt_names [alt_names] DNS.1 = localhost IP.1 = 127.0.0.1 pytest-httpbin-2.0.0/pytest_httpbin/certs/etc/localhost.crt000066400000000000000000000031061442625232000241640ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIIEdjCCAl6gAwIBAgIJAJZYfkBVjU9hMA0GCSqGSIb3DQEBCwUAMF0xCzAJBgNV BAYTAlVTMQswCQYDVQQIDAJISTESMBAGA1UEBwwJa2V2aW4xMDI0MS0wKwYDVQQK DCRweXRlc3QtaHR0cGJpbiBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMTkwMjEx MTY0OTM5WhcNMzkwMjA2MTY0OTM5WjB4MQswCQYDVQQGEwJISTESMBAGA1UECAwJ a2V2aW4xMDI0MQ8wDQYDVQQHDAZLYWlsdWExFzAVBgNVBAoMDlB5dGVzdC1odHRw YmluMRcwFQYDVQQLDA5QeXRlc3QtaHR0cGJpbjESMBAGA1UEAwwJMTI3LjAuMC4x MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvSQUs9vEg5m6GUeEK44o 2fZzTMMfiRCUqPTyh1LGen7A2CSPYMRst9mb9ygZjQGqoVKIAQC+RuEsMl8pjw/g vKoJPcKwONxnOwILbLsuGZ+szgx/q9IZ3BQR5pXenJP8A9hCeUzREU6OjFqQEB4g zjsBhUsf5cfn+YCKPhvWflSy6tgjjHK5ocNSoWvmeDbz1elgd7XR8tIYlgT8t8aA n66IRtONUJRuik/3mOdQUdC2E0dOVD2ivcSKLbudGGbVscEl0JZNfZhgqUCcEMSQ kHNxlXmWd67X6VzBKjq0GoYa5WPsZtT3kpdyiP0runb0z/ciDKLJ5CbeBaWeN3bW qwIDAQABox4wHDAaBgNVHREEEzARgglsb2NhbGhvc3SHBH8AAAEwDQYJKoZIhvcN AQELBQADggIBAFC2Ozs6U3Ia01Lzbm+aIwDRy5A4DSZ8q5OVQxmcE0vQ+yOHhQt4 bh5z3+q09Gycnsb7Ydwg6nNgT4Jbyq4eyjS73R4VHerdBdFyujEv6tVwho1mtLSc wwLbhp6YvbI7wsomc3FIIgOw2Oi6ZGQQneQikXm0yTe6+MZcPs9+4D2lwPFhxGnA +6lAsj+zvaZknvVr9lfhbP4RvCMnyNZsf4Z2bv0i0cdA4uaHRQD9KB6DyLGTLjHZ YDZS52UINsoPehERWf/I/z/n4K1WKzCY6By3pRSKOHNhdo7UHg659AHByf5kBLGX ByvVMZ4XzpoUYcT+93EsoU0jU/i4zKbY2z27ny9Erb1JzwYIXtUoAO1tkqZrtGFs LG+l8T4PazRDe0redwb3XkNRzS54J/ocrUBeNhFDQJjmLOMflsnLDRPxnZzEkGjm +svpq0UChPSiEkaCdF1gL5euoPIuQ6KpSMbf+WLjuFhwnMZyvbh1xEd7MnLg7qU8 karqmiEiyYzmhn7ygcTCn7Hgo98tIzydo0+9fk5pmyzE5PjI1uVJJ76JXK74aJPy iUK9OOrW1ZE3LGP8ZCtZMAciV3GHRBXHUIslu7PUxj6LHXQz+7qDO6xmuEp4emki +vNHdGEVtxW3WObO+i+V/hWIgXubXqxlSUUG7AfAt65278l2s5N+i4+p -----END CERTIFICATE----- pytest-httpbin-2.0.0/pytest_httpbin/certs/etc/localhost.csr000066400000000000000000000020761442625232000241700ustar00rootroot00000000000000-----BEGIN CERTIFICATE REQUEST----- MIIC6jCCAdICAQAweDELMAkGA1UEBhMCSEkxEjAQBgNVBAgMCWtldmluMTAyNDEP MA0GA1UEBwwGS2FpbHVhMRcwFQYDVQQKDA5QeXRlc3QtaHR0cGJpbjEXMBUGA1UE CwwOUHl0ZXN0LWh0dHBiaW4xEjAQBgNVBAMMCTEyNy4wLjAuMTCCASIwDQYJKoZI hvcNAQEBBQADggEPADCCAQoCggEBAL0kFLPbxIOZuhlHhCuOKNn2c0zDH4kQlKj0 8odSxnp+wNgkj2DEbLfZm/coGY0BqqFSiAEAvkbhLDJfKY8P4LyqCT3CsDjcZzsC C2y7LhmfrM4Mf6vSGdwUEeaV3pyT/APYQnlM0RFOjoxakBAeIM47AYVLH+XH5/mA ij4b1n5UsurYI4xyuaHDUqFr5ng289XpYHe10fLSGJYE/LfGgJ+uiEbTjVCUbopP 95jnUFHQthNHTlQ9or3Eii27nRhm1bHBJdCWTX2YYKlAnBDEkJBzcZV5lneu1+lc wSo6tBqGGuVj7GbU95KXcoj9K7p29M/3IgyiyeQm3gWlnjd21qsCAwEAAaAtMCsG CSqGSIb3DQEJDjEeMBwwGgYDVR0RBBMwEYIJbG9jYWxob3N0hwR/AAABMA0GCSqG SIb3DQEBCwUAA4IBAQCJNlvkm7kp2O4H7rhE5yohTN5x5vQVTS3dHnA+laWouigE /6Uy6MKZVoOOgeaG9f+9Ej/x/jVKT7zdYPOLn3K9YLO44sG3pY4CNfrW6Y9y5tpz VXZ4N0WsKj108+1ievC/Ny8tCY5UQjfQZn3X+wVkk3aZWM5U3YJvGj9cGe/Jnijp a7vcvq5X5otgbQiy/qbU/Cx+FJy0lfeBiEaVIIEyOACAMlXLeIKeHHUOt+B/8OAv hLn4qbCxHrjJm8rj2+kqaSj1kQBwds3nKWVAExpv4m9YDyjVsiJcM1OMEZrjmjPn WvY2dLTCaNesreKeFyRIg6oGZrGFWQ4ORBGlrmdl -----END CERTIFICATE REQUEST----- pytest-httpbin-2.0.0/pytest_httpbin/certs/etc/localhost.key000066400000000000000000000032131442625232000241630ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- MIIEowIBAAKCAQEAvSQUs9vEg5m6GUeEK44o2fZzTMMfiRCUqPTyh1LGen7A2CSP YMRst9mb9ygZjQGqoVKIAQC+RuEsMl8pjw/gvKoJPcKwONxnOwILbLsuGZ+szgx/ q9IZ3BQR5pXenJP8A9hCeUzREU6OjFqQEB4gzjsBhUsf5cfn+YCKPhvWflSy6tgj jHK5ocNSoWvmeDbz1elgd7XR8tIYlgT8t8aAn66IRtONUJRuik/3mOdQUdC2E0dO VD2ivcSKLbudGGbVscEl0JZNfZhgqUCcEMSQkHNxlXmWd67X6VzBKjq0GoYa5WPs ZtT3kpdyiP0runb0z/ciDKLJ5CbeBaWeN3bWqwIDAQABAoIBAHmM53USxf6g23UF fc4T5PL2K/Dn8KtAKZlPGVGYA4+TR9Ff5XiVoxyfz1iNv6XbrVFRXa/vT1jzuliA yY9z78SvLZMwO9m+4uSMEtWEkULMV9xvMdk1A4NornxWUiKkA7Bg2Y9kq3MI3hka 1jxVcFW4m+iSd+ROjSjNz4nMkBLMtV8CZ9zVNkF7ZnGtVYQhyi4l+o5NXbo/2zpN rkIMm4QWWgyVMWzZnTa61jwtHKOapgg94FZw2LGIzZspZpZdk4Jerxzg5mfv6FUh /ngPGmQ4p2cMl9M8UMpUdTlO9sPkt63wmSbNrd1zeeOx2SMmDgeowOKWH1CRnsPO QXj1lbkCgYEA9O8sB7fsARx8oxDQBYj/Jtiz+805/QLpwBMWopmutLJm2Dy3jIm8 DZzErr4XGGreGv5sUX6JAYCAXMK14mzzURb65QX6fQpVNgrE+RZSRpc53/YWkaok OtUUonigN04x6kC3OVuqCVz8g7Qzvm2OUakBFz9TIypFvk9CNn2nZtUCgYEAxa+f NIsKAWz4l5j/kVkt4QklOHyz0BOrNpycyjceP5GI7m14UHBR/8INseG3WNkpC5j/ k1Tq1dnPYDb0oFiUIPzQ+nZHNWZU99vgwG1odSVRDsVI+Vca1VknSy6rZykGs0Yy o+/EiZHx21GczRH6eFBkY/mJbqfVUuhNn/qvB38CgYEA1caqN1JfudiTL//MkAgy KkWZUXyd0CZqvinq56Aay7up57GWwiK072yUfa+LmNQtZoIJKFe4XIc7gbqv5SAS fgQAl0PQjLIoDTL5GC5TQSlcagzvRdOqK28uw19k9uBY0IwLXxSSI/n0qz7sqpgU T1GikhfDCD4tAR1MPSMOqMECgYBGTBp4K81GDoMkHZMcE7Nd58ull6q1npju1ahn vEv0XQNtjd4P9LEkGtSV4ec6IBcZebHAqZzMqSS2WTSKZJVgWabSuga+dYJXlYgJ xZ40si1t7Dfz+safAZIYiSMIjy1DyP2vEE86gHyZ+h6hSfhgmm3oo07824/faJ5Z +mINbwKBgGhwUhu5PYylZjIJqlsIaQMdIZaFmNJO2GnedBxjckLmk4iNDUwLo6Eb +1buSly8Zz9RybvuhYy+ppEU6kRDeN7uIEps3O44knOhRNQMCUH7j9Edkh0vtkwB 6on/+SVmdY7lDWpz7PICX9rN0ziCETFhohrll+SneBVNlHnqdrwL -----END RSA PRIVATE KEY----- pytest-httpbin-2.0.0/pytest_httpbin/certs/etc/rootCA.crt000066400000000000000000000035121442625232000233640ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIIFNjCCAx4CCQCxvkG1KFHCuzANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJV UzELMAkGA1UECAwCSEkxEjAQBgNVBAcMCWtldmluMTAyNDEtMCsGA1UECgwkcHl0 ZXN0LWh0dHBiaW4gQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTE5MDIxMTE1NDgz MFoXDTM5MDIwNjE1NDgzMFowXTELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkhJMRIw EAYDVQQHDAlrZXZpbjEwMjQxLTArBgNVBAoMJHB5dGVzdC1odHRwYmluIENlcnRp ZmljYXRlIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB ANbSc+N9CYgRPVMIQTEXqDeFG1GvHjgjhwN/nV/JGqmG8ZgD26WMRs9b6yHdD8Xx Wgq6IqOm+dzkfRCnELPtYn96l1SSfZBEAAo5137ZzaKLLvKp2cjUwLN3Y7ZlF8CV rZT7ObII9J0Xt67XrdPXeKIVzZjg9CtPFFE+OzrLl8UNH2N5zGxJ43G0v1f+5qYu /oIHRiN4Wdd53MJaFOXMzI43/vYztHpW4tsKhmR8cTgpdbM4yCWU5mYDz+SPsMvN 7OVcTW+ALifxIjr/J0l1uIFfq00UgPv1SaLGL1bfrQFVpPfRl6mNBRf1xszDXk4x xsv67EpWdQ2UIHvP9LMe+IeVqf+V+9u2VuijYeZo6T8lCLPRznqO24pkTkioSfpT tluxWaY2/hdlYBWVuK5pV49L6ls6ci03Q+LDzN29D+rfGraWDWWbkF/8qQZOKE85 /rW6hpsEgOVgtVVTm2wCH7v1VpEnfj9LBQgvrDpawwP9OQyueGnrMC6Oqsx7L8MM 2w+4qZ7/XlrrPlxMorNyQsFpDI0tui3qiggvlHUFjn9CDfulAZlrqExuAmrXzpJo sEfwmwqXijrtZqBm9nrTC2piUUcE7eqKPk/qsBDf+Y+WJxszyRrBron3FjI/IgLc efa8ncsdyFybvIJ3RIeI01Ah3iTmxSjxW/5zZEamhsdPAgMBAAEwDQYJKoZIhvcN AQELBQADggIBAEkLPQ/X29BWQus+uRqcpHnv3N82ymOfVTzlLzlddRXTJY2G6aMO lSRoTDIDplyCPuS+mapqXh3TjeUeDNHriAmS+CCACpsYy11CdLsc7TwonApa4ttL b9ubmZ+QpK+5aTXiglxqB/EMzT9SNOCxZb89+ONg6J/4AgW19OkKqwIsiBN7l7NO pi5tLE9YqR4KaQRs/3meAj7xjjzWkXW7w6KbTAc5IbrzejThizmWsJjWM5N/BkZH GN/MCQ2cWZ7U1YkwgBX2VUeR/xqgyBWBITj5SFoIMjN6+DFC/Cegu0OdmQ4lZAVh dFVgfQd5FSdIvAo4tnDiOWJzIoF/RwybgqHRYBg4RBLgBTBqYfgtc0R5us6E/QNa rGRHiq6JOeCoCvWvkWOa/DslmFD+12TWjSUIuYbse6lqiEwCpF16M6ZIJNpAJh80 sAQyY9UnPsBsqkptwgeGoXk+1t3NTteetMKApgC+OuxZi7ijbCArVFwpHp2M22nJ AShGgjxPNZV4AtR1HKAYW+C12IbuFMrS6uby8fj+dLJXqjq3kxuE1h8oQsME/wF9 FT8aFVhZJ+VbNNFtcdrjNnN++mBm9mBC79ANbLG2N5FZZJynicwRqWKDu52u6t20 buVa8cFuOSK2Prz/3RCYjPlszebE26KNCMHPG3U0ZIUJM2hmlBfRVwZW -----END CERTIFICATE----- pytest-httpbin-2.0.0/pytest_httpbin/certs/etc/rootCA.key000066400000000000000000000062531442625232000233710ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- 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 -----END RSA PRIVATE KEY----- pytest-httpbin-2.0.0/pytest_httpbin/certs/etc/rootCA.srl000066400000000000000000000000211442625232000233640ustar00rootroot0000000000000096587E40558D4F61 pytest-httpbin-2.0.0/pytest_httpbin/certs/key.pem000066400000000000000000000032131442625232000222010ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- MIIEowIBAAKCAQEAvSQUs9vEg5m6GUeEK44o2fZzTMMfiRCUqPTyh1LGen7A2CSP YMRst9mb9ygZjQGqoVKIAQC+RuEsMl8pjw/gvKoJPcKwONxnOwILbLsuGZ+szgx/ q9IZ3BQR5pXenJP8A9hCeUzREU6OjFqQEB4gzjsBhUsf5cfn+YCKPhvWflSy6tgj jHK5ocNSoWvmeDbz1elgd7XR8tIYlgT8t8aAn66IRtONUJRuik/3mOdQUdC2E0dO VD2ivcSKLbudGGbVscEl0JZNfZhgqUCcEMSQkHNxlXmWd67X6VzBKjq0GoYa5WPs ZtT3kpdyiP0runb0z/ciDKLJ5CbeBaWeN3bWqwIDAQABAoIBAHmM53USxf6g23UF fc4T5PL2K/Dn8KtAKZlPGVGYA4+TR9Ff5XiVoxyfz1iNv6XbrVFRXa/vT1jzuliA yY9z78SvLZMwO9m+4uSMEtWEkULMV9xvMdk1A4NornxWUiKkA7Bg2Y9kq3MI3hka 1jxVcFW4m+iSd+ROjSjNz4nMkBLMtV8CZ9zVNkF7ZnGtVYQhyi4l+o5NXbo/2zpN rkIMm4QWWgyVMWzZnTa61jwtHKOapgg94FZw2LGIzZspZpZdk4Jerxzg5mfv6FUh /ngPGmQ4p2cMl9M8UMpUdTlO9sPkt63wmSbNrd1zeeOx2SMmDgeowOKWH1CRnsPO QXj1lbkCgYEA9O8sB7fsARx8oxDQBYj/Jtiz+805/QLpwBMWopmutLJm2Dy3jIm8 DZzErr4XGGreGv5sUX6JAYCAXMK14mzzURb65QX6fQpVNgrE+RZSRpc53/YWkaok OtUUonigN04x6kC3OVuqCVz8g7Qzvm2OUakBFz9TIypFvk9CNn2nZtUCgYEAxa+f NIsKAWz4l5j/kVkt4QklOHyz0BOrNpycyjceP5GI7m14UHBR/8INseG3WNkpC5j/ k1Tq1dnPYDb0oFiUIPzQ+nZHNWZU99vgwG1odSVRDsVI+Vca1VknSy6rZykGs0Yy o+/EiZHx21GczRH6eFBkY/mJbqfVUuhNn/qvB38CgYEA1caqN1JfudiTL//MkAgy KkWZUXyd0CZqvinq56Aay7up57GWwiK072yUfa+LmNQtZoIJKFe4XIc7gbqv5SAS fgQAl0PQjLIoDTL5GC5TQSlcagzvRdOqK28uw19k9uBY0IwLXxSSI/n0qz7sqpgU T1GikhfDCD4tAR1MPSMOqMECgYBGTBp4K81GDoMkHZMcE7Nd58ull6q1npju1ahn vEv0XQNtjd4P9LEkGtSV4ec6IBcZebHAqZzMqSS2WTSKZJVgWabSuga+dYJXlYgJ xZ40si1t7Dfz+safAZIYiSMIjy1DyP2vEE86gHyZ+h6hSfhgmm3oo07824/faJ5Z +mINbwKBgGhwUhu5PYylZjIJqlsIaQMdIZaFmNJO2GnedBxjckLmk4iNDUwLo6Eb +1buSly8Zz9RybvuhYy+ppEU6kRDeN7uIEps3O44knOhRNQMCUH7j9Edkh0vtkwB 6on/+SVmdY7lDWpz7PICX9rN0ziCETFhohrll+SneBVNlHnqdrwL -----END RSA PRIVATE KEY----- pytest-httpbin-2.0.0/pytest_httpbin/plugin.py000066400000000000000000000017231442625232000214420ustar00rootroot00000000000000import pytest from httpbin import app as httpbin_app from . import certs, serve @pytest.fixture(scope="session") def httpbin(request): with serve.Server(application=httpbin_app) as server: yield server @pytest.fixture(scope="session") def httpbin_secure(request): with serve.SecureServer(application=httpbin_app) as server: yield server @pytest.fixture(scope="session", params=["http", "https"]) def httpbin_both(request, httpbin, httpbin_secure): if request.param == "http": return httpbin elif request.param == "https": return httpbin_secure @pytest.fixture(scope="class") def class_based_httpbin(request, httpbin): request.cls.httpbin = httpbin @pytest.fixture(scope="class") def class_based_httpbin_secure(request, httpbin_secure): request.cls.httpbin_secure = httpbin_secure @pytest.fixture(scope="function") def httpbin_ca_bundle(monkeypatch): monkeypatch.setenv("REQUESTS_CA_BUNDLE", certs.where()) pytest-httpbin-2.0.0/pytest_httpbin/serve.py000066400000000000000000000103601442625232000212650ustar00rootroot00000000000000import os import ssl import threading from urllib.parse import urljoin from wsgiref.handlers import SimpleHandler from wsgiref.simple_server import WSGIRequestHandler, WSGIServer, make_server CERT_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "certs") class ServerHandler(SimpleHandler): server_software = "Pytest-HTTPBIN/0.1.0" http_version = "1.1" def cleanup_headers(self): SimpleHandler.cleanup_headers(self) self.headers["Connection"] = "Close" def close(self): try: self.request_handler.log_request( self.status.split(" ", 1)[0], self.bytes_sent ) finally: SimpleHandler.close(self) class Handler(WSGIRequestHandler): def handle(self): """Handle a single HTTP request""" self.raw_requestline = self.rfile.readline() if not self.parse_request(): # An error code has been sent, just exit return handler = ServerHandler( self.rfile, self.wfile, self.get_stderr(), self.get_environ() ) handler.request_handler = self # backpointer for logging handler.run(self.server.get_app()) def get_environ(self): """ wsgiref simple server adds content-type text/plain to everything, this removes it if it's not actually in the headers. """ # Note: Can't use super since this is an oldstyle class in python 2.x environ = WSGIRequestHandler.get_environ(self).copy() if self.headers.get("content-type") is None: del environ["CONTENT_TYPE"] return environ class SecureWSGIServer(WSGIServer): def finish_request(self, request, client_address): """ Negotiates SSL and then mimics BaseServer behavior. """ request.settimeout(1.0) try: context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) context.load_cert_chain( os.path.join(CERT_DIR, "cert.pem"), os.path.join(CERT_DIR, "key.pem"), ) with context.wrap_socket( request, server_side=True, suppress_ragged_eofs=False ) as ssock: self.base_environ["HTTPS"] = "yes" self.RequestHandlerClass(ssock, client_address, self) except Exception as e: print("pytest-httpbin server hit an exception serving request: %s" % e) print("attempting to ignore so the rest of the tests can run") # WSGIRequestHandler seems to close the socket for us. # Thanks, WSGIRequestHandler!! class Server: """ HTTP server running a WSGI application in its own thread. """ port_envvar = "HTTPBIN_HTTP_PORT" def __init__(self, host="127.0.0.1", port=0, application=None, **kwargs): self.app = application if self.port_envvar in os.environ: port = int(os.environ[self.port_envvar]) self._server = make_server( host, port, self.app, handler_class=Handler, **kwargs ) self.host = self._server.server_address[0] self.port = self._server.server_address[1] self.protocol = "http" self._thread = threading.Thread( name=self.__class__, target=self._server.serve_forever, ) def __del__(self): if hasattr(self, "_server"): self.stop() def start(self): self._thread.start() def __enter__(self): self.start() return self def __exit__(self, *args, **kwargs): self.stop() suppress_exc = self._server.__exit__(*args, **kwargs) self._thread.join() return suppress_exc def __add__(self, other): return self.url + other def stop(self): self._server.shutdown() @property def url(self): return f"{self.protocol}://{self.host}:{self.port}" def join(self, url, allow_fragments=True): return urljoin(self.url, url, allow_fragments=allow_fragments) class SecureServer(Server): port_envvar = "HTTPBIN_HTTPS_PORT" def __init__(self, host="127.0.0.1", port=0, application=None, **kwargs): kwargs["server_class"] = SecureWSGIServer super().__init__(host, port, application, **kwargs) self.protocol = "https" pytest-httpbin-2.0.0/pytest_httpbin/version.py000066400000000000000000000000261442625232000216240ustar00rootroot00000000000000__version__ = "2.0.0" pytest-httpbin-2.0.0/runtests.sh000077500000000000000000000000361442625232000167340ustar00rootroot00000000000000#!/bin/bash py.test $1 -v -s pytest-httpbin-2.0.0/setup.cfg000066400000000000000000000011061442625232000163260ustar00rootroot00000000000000[bdist_wheel] # This flag says that the code is written to work on both Python 2 and Python # 3. If at all possible, it is good practice to do this. If you cannot, you # will need to generate wheels for each Python version that you support. universal=1 [flake8] disable-noqa = True max-line-length = 88 extend-ignore = # whitespace before : is not PEP8 compliant (& conflicts with black) E203 [tool:pytest] addopts = --strict-config --strict-markers filterwarnings = error ignore:ast\.(Str|NameConstant) is deprecated:DeprecationWarning:_pytest xfail_strict = true pytest-httpbin-2.0.0/setup.py000066400000000000000000000042011442625232000162160ustar00rootroot00000000000000import codecs import os from setuptools import find_packages, setup __version__ = None with open("pytest_httpbin/version.py") as f: code = compile(f.read(), "pytest_httpbin/version.py", "exec") exec(code) here = os.path.abspath(os.path.dirname(__file__)) # Get the long description from the relevant file with codecs.open(os.path.join(here, "DESCRIPTION.rst"), encoding="utf-8") as f: long_description = f.read() setup( name="pytest-httpbin", # There are various approaches to referencing the version. For a discussion, # see http://packaging.python.org/en/latest/tutorial.html#version version=__version__, description="Easily test your HTTP library against a local copy of httpbin", long_description=long_description, long_description_content_type="text/x-rst", # The project URL. url="https://github.com/kevin1024/pytest-httpbin", # Author details author="Kevin McCarthy", author_email="me@kevinmccarthy.org", # Choose your license license="MIT", classifiers=[ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "Topic :: Software Development :: Testing", "Topic :: Software Development :: Libraries", "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", ], # What does your project relate to? keywords="pytest-httpbin testing pytest httpbin", packages=find_packages(exclude=["contrib", "docs", "tests*"]), include_package_data=True, # include files listed in MANIFEST.in install_requires=["httpbin"], extras_require={"test": ["requests", "pytest", "werkzeug<2.1.0"]}, python_requires=">=3.7", # the following makes a plugin available to pytest entry_points={ "pytest11": [ "httpbin = pytest_httpbin.plugin", ] }, ) pytest-httpbin-2.0.0/tests/000077500000000000000000000000001442625232000156515ustar00rootroot00000000000000pytest-httpbin-2.0.0/tests/conftest.py000066400000000000000000000001741442625232000200520ustar00rootroot00000000000000import pytest @pytest.fixture(autouse=True, scope="function") def httpbin_ca_bundle_autoused(httpbin_ca_bundle): pass pytest-httpbin-2.0.0/tests/test_httpbin.py000066400000000000000000000036321442625232000207360ustar00rootroot00000000000000import ssl import sys import unittest import pytest import requests.exceptions import pytest_httpbin def test_httpbin_gets_injected(httpbin): assert httpbin.url def test_httpbin_accepts_get_requests(httpbin): assert requests.get(httpbin.url + "/get").status_code == 200 def test_httpbin_secure_accepts_get_requests(httpbin_secure): assert requests.get(httpbin_secure.url + "/get").status_code == 200 def test_httpbin_secure_accepts_lots_of_get_requests(httpbin_secure): for i in range(10): assert requests.get(httpbin_secure.url + "/get").status_code == 200 def test_httpbin_accepts_lots_of_get_requests_in_single_session(httpbin): session = requests.Session() for i in range(10): assert session.get(httpbin.url + "/get").status_code == 200 def test_httpbin_both(httpbin_both): # this test will get called twice, once with an http url, once with an # https url assert requests.get(httpbin_both.url + "/get").status_code == 200 def test_httpbin_join(httpbin): assert httpbin.join("foo") == httpbin.url + "/foo" def test_httpbin_str(httpbin): assert httpbin + "/foo" == httpbin.url + "/foo" def test_chunked_encoding(httpbin): assert requests.get(httpbin.url + "/stream/20").status_code == 200 @pytest.mark.xfail( condition=sys.version_info < (3, 8) and ssl.OPENSSL_VERSION_INFO >= (3, 0, 0), reason="fails on python3.7 openssl 3+", raises=requests.exceptions.SSLError, ) def test_chunked_encoding_secure(httpbin_secure): assert requests.get(httpbin_secure.url + "/stream/20").status_code == 200 @pytest_httpbin.use_class_based_httpbin @pytest_httpbin.use_class_based_httpbin_secure class TestClassBassedTests(unittest.TestCase): def test_http(self): assert requests.get(self.httpbin.url + "/get").status_code == 200 def test_http_secure(self): assert requests.get(self.httpbin_secure.url + "/get").status_code == 200 pytest-httpbin-2.0.0/tests/test_server.py000066400000000000000000000072211442625232000205720ustar00rootroot00000000000000import contextlib import os import re import socket import pytest import requests.exceptions from httpbin import app as httpbin_app from util import get_raw_http_response from pytest_httpbin import serve def test_content_type_header_not_automatically_added(httpbin): """ The server was automatically adding this for some reason, see issue #5 """ resp = requests.get(httpbin + "/headers").json()["headers"] assert "Content-Type" not in resp def test_unicode_data(httpbin): """ UTF-8 was not getting recognized for what it was and being encoded as if it was binary, see issue #7 """ resp = requests.post( httpbin + "/post", data="оживлённым".encode(), headers={ "content-type": "text/html; charset=utf-8", }, ) assert resp.json()["data"] == "оживлённым" def test_server_should_be_http_1_1(httpbin): """ The server should speak HTTP/1.1 since we live in the future, see issue #6 """ resp = get_raw_http_response(httpbin.host, httpbin.port, "/get") assert resp.startswith(b"HTTP/1.1") def test_dont_crash_on_certificate_problems(httpbin_secure): with pytest.raises(requests.exceptions.SSLError): # this request used to hang requests.get(httpbin_secure + "/get", verify=True, cert=__file__) # and this request would never happen requests.get( httpbin_secure + "/get", verify=True, ) def test_dont_crash_on_handshake_timeout(httpbin_secure, capsys): with socket.socket() as sock: sock.connect((httpbin_secure.host, httpbin_secure.port)) # this request used to hang assert sock.recv(1) == b"" assert ( re.match( r"pytest-httpbin server hit an exception serving request: .* The " "handshake operation timed out\nattempting to ignore so the rest " "of the tests can run\n", capsys.readouterr().out, ) is not None ) # and this request would never happen requests.get( httpbin_secure + "/get", verify=True, ) @pytest.mark.parametrize("protocol", ("http", "https")) def test_fixed_port_environment_variables(protocol): """ Note that we cannot test the fixture here because it is session scoped and was already started. Thus, let's just test a new Server instance. """ if protocol == "http": server_cls = serve.Server envvar = "HTTPBIN_HTTP_PORT" elif protocol == "https": server_cls = serve.SecureServer envvar = "HTTPBIN_HTTPS_PORT" else: raise RuntimeError(f"Unexpected protocol param: {protocol}") # just have different port to avoid adrress already in use # if the second test run too fast after the first one (happens on pypy) port = 12345 + len(protocol) server = contextlib.nullcontext() try: envvar_original = os.environ.get(envvar, None) os.environ[envvar] = str(port) server = server_cls(application=httpbin_app) assert server.port == port finally: # if we don't do this, it blocks: with server: pass # restore the original environ: if envvar_original is None: del os.environ[envvar] else: os.environ[envvar] = envvar_original def test_redirect_location_is_https_for_secure_server(httpbin_secure): assert httpbin_secure.url.startswith("https://") response = requests.get( httpbin_secure + "/redirect-to?url=/html", allow_redirects=False ) assert response.status_code == 302 assert response.headers.get("Location") assert response.headers["Location"] == "/html" pytest-httpbin-2.0.0/tests/util.py000066400000000000000000000012011442625232000171720ustar00rootroot00000000000000import socket def get_raw_http_response(host, port, path): CRLF = b"\r\n" request = [ b"GET " + path.encode("ascii") + b" HTTP/1.1", b"Host: " + host.encode("ascii"), b"Connection: Close", b"", b"", ] # Connect to the server with socket.socket() as s: s.connect((host, port)) # Send an HTTP request s.send(CRLF.join(request)) # Get the response (in several parts, if necessary) response = b"" buffer = s.recv(4096) while buffer: response += buffer buffer = s.recv(4096) return response pytest-httpbin-2.0.0/tox.ini000066400000000000000000000013371442625232000160260ustar00rootroot00000000000000# content of: tox.ini , put in same dir as setup.py [tox] minversion=3.28.0 requires= virtualenv>=20.13.2 tox-wheel>=0.7.0 tox-gh-actions>=2.9.1 tox<4 envlist = py37, py38, py39, py310, pypy3 [testenv] wheel = True wheel_build_env = build wheel_pep517 = build extras = test commands = pytest -v -s {posargs} [testenv:build] # empty environment to build universal wheel once per tox invocation # https://github.com/ionelmc/tox-wheel#build-configuration [testenv:release] deps = build twine whitelist_externals = cp rm commands = rm -rf {toxinidir}/dist cp -r {distdir} {toxinidir}/dist # copy the wheel built by tox-wheel {envpython} -m build --sdist twine check {toxinidir}/dist/*.*