{"id":13501544,"url":"https://github.com/csernazs/pytest-httpserver","last_synced_at":"2025-10-20T12:58:02.978Z","repository":{"id":37432374,"uuid":"143554032","full_name":"csernazs/pytest-httpserver","owner":"csernazs","description":"Http server for pytest to test http clients","archived":false,"fork":false,"pushed_at":"2025-10-13T20:46:13.000Z","size":887,"stargazers_count":238,"open_issues_count":13,"forks_count":30,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-10-20T12:57:49.064Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/csernazs.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGES.rst","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2018-08-04T18:47:08.000Z","updated_at":"2025-10-02T06:28:53.000Z","dependencies_parsed_at":"2023-01-31T05:31:02.888Z","dependency_job_id":"d8b241fe-fe85-4c0d-86f4-ad509f015cbc","html_url":"https://github.com/csernazs/pytest-httpserver","commit_stats":{"total_commits":349,"total_committers":21,"mean_commits":16.61904761904762,"dds":"0.26361031518624645","last_synced_commit":"ded7fa608ec4d024794e622c21b65f4fc389f04d"},"previous_names":[],"tags_count":31,"template":false,"template_full_name":null,"purl":"pkg:github/csernazs/pytest-httpserver","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/csernazs%2Fpytest-httpserver","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/csernazs%2Fpytest-httpserver/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/csernazs%2Fpytest-httpserver/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/csernazs%2Fpytest-httpserver/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/csernazs","download_url":"https://codeload.github.com/csernazs/pytest-httpserver/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/csernazs%2Fpytest-httpserver/sbom","scorecard":{"id":310830,"data":{"date":"2025-08-11","repo":{"name":"github.com/csernazs/pytest-httpserver","commit":"4334e4960d2cc568e7910e2cdf4fdcac8e6d8806"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.6,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Maintained","score":10,"reason":"17 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":2,"reason":"Found 1/5 approved changesets -- score normalized to 2","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/ci.yml:1","Warn: no topLevel permission defined: .github/workflows/dependabot-validate.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Info: Possibly incomplete results: error parsing job operating system: .github/workflows/ci.yml:63","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/csernazs/pytest-httpserver/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:54: update your workflow using https://app.stepsecurity.io/secureworkflow/csernazs/pytest-httpserver/ci.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:80: update your workflow using https://app.stepsecurity.io/secureworkflow/csernazs/pytest-httpserver/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:90: update your workflow using https://app.stepsecurity.io/secureworkflow/csernazs/pytest-httpserver/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/dependabot-validate.yml:12: update your workflow using https://app.stepsecurity.io/secureworkflow/csernazs/pytest-httpserver/dependabot-validate.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/dependabot-validate.yml:13: update your workflow using https://app.stepsecurity.io/secureworkflow/csernazs/pytest-httpserver/dependabot-validate.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/dependabot-validate.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/csernazs/pytest-httpserver/dependabot-validate.yml/master?enable=pin","Info:   0 out of   4 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   3 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":2,"reason":"badge detected: InProgress","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 30 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-17T23:09:14.400Z","repository_id":37432374,"created_at":"2025-08-17T23:09:14.400Z","updated_at":"2025-08-17T23:09:14.400Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":280094904,"owners_count":26271003,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-20T02:00:06.978Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T22:01:41.150Z","updated_at":"2025-10-20T12:58:02.932Z","avatar_url":"https://github.com/csernazs.png","language":"Python","funding_links":["https://opencollective.com/pytest"],"categories":["Python"],"sub_categories":[],"readme":"[![Build Status](https://github.com/csernazs/pytest-httpserver/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/csernazs/pytest-httpserver/actions?query=workflow%3Abuild+branch%3Amaster)\n[![Documentation Status](https://readthedocs.org/projects/pytest-httpserver/badge/?version=latest)](https://pytest-httpserver.readthedocs.io/en/latest/?badge=latest)\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)\n[![codecov](https://codecov.io/gh/csernazs/pytest-httpserver/branch/master/graph/badge.svg?token=MX2JXbHqRH)](https://codecov.io/gh/csernazs/pytest-httpserver)\n[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)\n[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)\n[![Downloads](https://static.pepy.tech/badge/pytest-httpserver/month)](https://pepy.tech/project/pytest-httpserver)\n[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit)](https://github.com/pre-commit/pre-commit)\n\n## pytest_httpserver\n\nHTTP server for pytest\n\n\n### Nutshell\n\nThis library is designed to help to test http clients without contacting the real http server.\nIn other words, it is a fake http server which is accessible via localhost can be started with\nthe pre-defined expected http requests and their responses.\n\n### Example\n\n#### Handling a simple GET request\n```python\ndef test_my_client(\n    httpserver,\n):  # httpserver is a pytest fixture which starts the server\n    # set up the server to serve /foobar with the json\n    httpserver.expect_request(\"/foobar\").respond_with_json({\"foo\": \"bar\"})\n    # check that the request is served\n    assert requests.get(httpserver.url_for(\"/foobar\")).json() == {\"foo\": \"bar\"}\n```\n\n#### Handing a POST request with an expected json body\n```python\ndef test_json_request(\n    httpserver,\n):  # httpserver is a pytest fixture which starts the server\n    # set up the server to serve /foobar with the json\n    httpserver.expect_request(\n        \"/foobar\", method=\"POST\", json={\"id\": 12, \"name\": \"foo\"}\n    ).respond_with_json({\"foo\": \"bar\"})\n    # check that the request is served\n    assert requests.post(\n        httpserver.url_for(\"/foobar\"), json={\"id\": 12, \"name\": \"foo\"}\n    ).json() == {\"foo\": \"bar\"}\n```\n\n\nYou can also use the library without pytest. There's a with statement to ensure that the server is stopped.\n\n\n```python\nwith HTTPServer() as httpserver:\n    # set up the server to serve /foobar with the json\n    httpserver.expect_request(\"/foobar\").respond_with_json({\"foo\": \"bar\"})\n    # check that the request is served\n    print(requests.get(httpserver.url_for(\"/foobar\")).json())\n```\n\n### Documentation\n\nPlease find the API documentation at https://pytest-httpserver.readthedocs.io/en/latest/.\n\n### Features\n\nYou can set up a dozen of expectations for the requests, and also what response should be sent by the server to the client.\n\n\n#### Requests\n\nThere are three different types:\n\n- **permanent**: this will be always served when there's match for this request, you can make as many HTTP requests as you want\n- **oneshot**: this will be served only once when there's a match for this request, you can only make 1 HTTP request\n- **ordered**: same as oneshot but the order must be strictly matched to the order of setting up\n\nYou can also fine-tune the expected request. The following can be specified:\n\n- URI (this is a must)\n- HTTP method\n- headers\n- query string\n- data (HTTP body of the request)\n- JSON (HTTP body loaded as JSON)\n\n\n#### Responses\n\nOnce you have the expectations for the request set up, you should also define the response you want to send back.\nThe following is supported currently:\n\n- respond arbitrary data (string or bytearray)\n- respond a json (a python dict converted in-place to json)\n- respond a Response object of werkzeug\n- use your own function\n\nSimilar to requests, you can fine-tune what response you want to send:\n\n- HTTP status\n- headers\n- data\n\n\n#### Behave support\n\nUsing the `BlockingHTTPServer` class, the assertion for a request and the\nresponse can be performed in real order. For more info, see the\n[test](tests/test_blocking_httpserver.py), the\n[howto](https://pytest-httpserver.readthedocs.io/en/latest/howto.html#running-httpserver-in-blocking-mode)\nand the [API\ndocumentation](https://pytest-httpserver.readthedocs.io/en/latest/api.html#blockinghttpserver).\n\n\n### Missing features\n* HTTP/2\n* Keepalive\n* ~~TLS~~\n\n### Donation\n\nCurrently, this project is based heavily on werkzeug and pytest.\n\nWerkzeug does all the heavy lifting behind the scenes, parsing HTTP request and\ndefining Request and Response objects, which are currently transparent in the\nAPI.\n\nIf you wish to donate to werkzeug: https://palletsprojects.com/donate\n\n\nPytest is the de-facto test library for python.\n\nIf you wish to donate to pytest: https://opencollective.com/pytest\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcsernazs%2Fpytest-httpserver","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcsernazs%2Fpytest-httpserver","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcsernazs%2Fpytest-httpserver/lists"}