diff --git a/_service b/_service deleted file mode 100644 index 23914e1..0000000 --- a/_service +++ /dev/null @@ -1,14 +0,0 @@ - - - python-httpbin - https://github.com/postmanlabs/httpbin.git - git - enable - 0.7.0+git%cd.%h - - - xz - *.tar - - - diff --git a/fix-setup-py.patch b/fix-setup-py.patch deleted file mode 100644 index e81092f..0000000 --- a/fix-setup-py.patch +++ /dev/null @@ -1,14 +0,0 @@ -Index: python-httpbin-0.7.0+git20181107.f8ec666/setup.py -=================================================================== ---- python-httpbin-0.7.0+git20181107.f8ec666.orig/setup.py -+++ python-httpbin-0.7.0+git20181107.f8ec666/setup.py -@@ -35,7 +35,7 @@ setup( - packages=find_packages(), - include_package_data = True, # include files listed in MANIFEST.in - install_requires=[ -- 'Flask', 'MarkupSafe', 'decorator', 'itsdangerous', 'six', 'brotlipy', -- 'raven[flask]', 'werkzeug>=0.14.1', 'gevent', 'flasgger' -+ 'Flask>=2.1', 'MarkupSafe', 'decorator', 'itsdangerous', 'six', 'brotli', -+ 'werkzeug>=2.0', 'gevent', 'flasgger' - ], - ) diff --git a/flask3.patch b/flask3.patch new file mode 100644 index 0000000..24ab8c8 --- /dev/null +++ b/flask3.patch @@ -0,0 +1,109 @@ +From c1d9e33049263fed3cb27806a97f094acc350905 Mon Sep 17 00:00:00 2001 +From: Nate Prewitt +Date: Thu, 12 Oct 2023 08:30:42 -0700 +Subject: [PATCH] Support Flask 3.0 (#29) + +--- + httpbin/core.py | 8 +++----- + httpbin/helpers.py | 21 ++++++++++++++++----- + pyproject.toml | 3 +-- + 3 files changed, 20 insertions(+), 12 deletions(-) + +diff --git a/httpbin/core.py b/httpbin/core.py +index 5c1783a1..a82c1b88 100644 +--- a/httpbin/core.py ++++ b/httpbin/core.py +@@ -32,7 +32,7 @@ + from werkzeug.wrappers import Response + except ImportError: # werkzeug < 2.1 + from werkzeug.wrappers import BaseResponse as Response +-from werkzeug.http import parse_authorization_header ++ + from flasgger import Swagger, NO_SANITIZER + + from . import filters +@@ -47,6 +47,7 @@ + H, + ROBOT_TXT, + ANGRY_ASCII, ++ parse_authorization_header, + parse_multi_value_header, + next_stale_after_value, + digest_challenge_response, +@@ -636,16 +637,13 @@ def redirect_to(): + args_dict = request.args.items() + args = CaseInsensitiveDict(args_dict) + +- # We need to build the response manually and convert to UTF-8 to prevent +- # werkzeug from "fixing" the URL. This endpoint should set the Location +- # header to the exact string supplied. + response = app.make_response("") + response.status_code = 302 + if "status_code" in args: + status_code = int(args["status_code"]) + if status_code >= 300 and status_code < 400: + response.status_code = status_code +- response.headers["Location"] = args["url"].encode("utf-8") ++ response.headers["Location"] = args["url"] + + return response + +diff --git a/httpbin/helpers.py b/httpbin/helpers.py +index b29e1835..836c8026 100644 +--- a/httpbin/helpers.py ++++ b/httpbin/helpers.py +@@ -13,8 +13,14 @@ + import time + import os + from hashlib import md5, sha256, sha512 +-from werkzeug.http import parse_authorization_header + from werkzeug.datastructures import WWWAuthenticate ++from werkzeug.http import dump_header ++ ++try: ++ from werkzeug.http import parse_authorization_header ++except ImportError: # werkzeug < 2.3 ++ from werkzeug.datastructures import Authorization ++ parse_authorization_header = Authorization.from_header + + from flask import request, make_response + from six.moves.urllib.parse import urlparse, urlunparse +@@ -466,9 +472,14 @@ def digest_challenge_response(app, qop, algorithm, stale = False): + ]), algorithm) + opaque = H(os.urandom(10), algorithm) + +- auth = WWWAuthenticate("digest") +- auth.set_digest('me@kennethreitz.com', nonce, opaque=opaque, +- qop=('auth', 'auth-int') if qop is None else (qop,), algorithm=algorithm) +- auth.stale = stale ++ values = { ++ 'realm': 'me@kennethreitz.com', ++ 'nonce': nonce, ++ 'opaque': opaque, ++ 'qop': dump_header(('auth', 'auth-int') if qop is None else (qop,)), ++ 'algorithm': algorithm, ++ 'stale': stale, ++ } ++ auth = WWWAuthenticate("digest", values=values) + response.headers['WWW-Authenticate'] = auth.to_header() + return response +diff --git a/pyproject.toml b/pyproject.toml +index 020457ec..9454e569 100644 +--- a/pyproject.toml ++++ b/pyproject.toml +@@ -31,14 +31,13 @@ classifiers = [ + "Programming Language :: Python :: 3.12", + ] + dependencies = [ +- "Flask", ++ "flask >= 2.2.4", + "brotlicffi", + "decorator", + "flasgger", + 'greenlet < 3.0; python_version<"3.12"', + 'greenlet >= 3.0.0a1; python_version>="3.12.0rc0"', + 'importlib-metadata; python_version<"3.8"', +- "werkzeug >= 0.14.1", + "six", + ] + diff --git a/httpbin-0.10.1.tar.gz b/httpbin-0.10.1.tar.gz new file mode 100644 index 0000000..74844d4 --- /dev/null +++ b/httpbin-0.10.1.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7b8596beb0e75a7b653c39d1f3cf263d6d5c476d29e1df6f7bb2b70bf9f06a3d +size 107058 diff --git a/httpbin-pr674-wekzeug2.1.patch b/httpbin-pr674-wekzeug2.1.patch deleted file mode 100644 index 5696f4c..0000000 --- a/httpbin-pr674-wekzeug2.1.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 5cc81ce87a3c447a127e4a1a707faf9f3b1c9b6b Mon Sep 17 00:00:00 2001 -From: Maximino BOGADO -Date: Wed, 30 Mar 2022 16:26:31 +0200 -Subject: [PATCH] Replace BaseResponse to Response class (new werkzeug version - 2.1.0) - ---- - httpbin/core.py | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/httpbin/core.py b/httpbin/core.py -index 305c9882..2bad408e 100644 ---- a/httpbin/core.py -+++ b/httpbin/core.py -@@ -29,7 +29,7 @@ - from six.moves import range as xrange - from werkzeug.datastructures import WWWAuthenticate, MultiDict - from werkzeug.http import http_date --from werkzeug.wrappers import BaseResponse -+from werkzeug.wrappers import Response - from werkzeug.http import parse_authorization_header - from flasgger import Swagger, NO_SANITIZER - -@@ -77,7 +77,7 @@ def jsonify(*args, **kwargs): - - - # Prevent WSGI from correcting the casing of the Location header --BaseResponse.autocorrect_location_header = False -+Response.autocorrect_location_header = False - - # Find the correct template folder when running from a different location - tmpl_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "templates") diff --git a/python-httpbin-0.7.0+git20181107.f8ec666.tar.xz b/python-httpbin-0.7.0+git20181107.f8ec666.tar.xz deleted file mode 100644 index fa67ec8..0000000 --- a/python-httpbin-0.7.0+git20181107.f8ec666.tar.xz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6ca690b5d5d0b1e75a947559663400492c48be4713502f9466da658d4270f638 -size 98088 diff --git a/python-httpbin.changes b/python-httpbin.changes index 2e25630..1bda103 100644 --- a/python-httpbin.changes +++ b/python-httpbin.changes @@ -1,3 +1,29 @@ +------------------------------------------------------------------- +Tue Oct 24 13:30:26 UTC 2023 - Markéta Machová + +- Use Brotli instead of dropped brotlicffi + +------------------------------------------------------------------- +Thu Oct 19 08:11:44 UTC 2023 - Markéta Machová + +- Repackage, new active upstream + * In their words: We were unable to get ahold of the folks at postmanlabs to + maintain the original project, and httpbin is used for other packages + within the python ecosystem, such as pytest-httpbin which is in turn used + by packages such as requests so we have forked this package. That means + that httpbin.org is not actually backed by this repo, but the httpbin + package is. Confusing right? + * Drop now unneeded _service, changes in the *spec +- Update to 0.10.1 + * Override docker image port with HTTPBIN_PORT + * A number of fixes for code rot, thanks @mgorny and @tjni +- Drop upstreamed/no-longer-needed patches: + * fix-setup-py.patch + * httpbin-pr674-wekzeug2.1.patch + * werkzeug.patch + * support-werkzeug-2.3.patch +- Add flask3.patch to support Flask 3.0 + ------------------------------------------------------------------- Wed Jun 21 08:35:31 UTC 2023 - Steve Kowalik diff --git a/python-httpbin.spec b/python-httpbin.spec index 60bf3a3..b88f608 100644 --- a/python-httpbin.spec +++ b/python-httpbin.spec @@ -16,44 +16,35 @@ # -# The PyPI version is 0.7.0 but the metadata reads an internal file with version 0.9.2 -%define internalversion 0.9.2 +%define modname httpbin %{?sle15_python_module_pythons} Name: python-httpbin -Version: 0.7.0+git20181107.f8ec666 +Version: 0.10.1 Release: 0 Summary: HTTP Request and Response Service License: MIT -URL: https://github.com/Runscope/httpbin -Source: python-httpbin-%{version}.tar.xz -# PATCH-FIX-UPSTREAM werkzeug.patch -- gh#postmanlabs/httpbin#555 -Patch0: werkzeug.patch -# PATCH-FIX-UPSTREAM fix-setup-py.patch -- gh#postmanlabs/httpbin#553 -Patch1: fix-setup-py.patch -# PATCH-FIX-UPSTREAM httpbin-pr674-wekzeug2.1.patch -- gh#postmanlabs/httpbin#674 -Patch2: httpbin-pr674-wekzeug2.1.patch -# PATCH-FIX-OPENSUSE Support Werkzeug >= 2.3 -Patch3: support-werkzeug-2.3.patch +URL: https://github.com/psf/httpbin +Source: https://files.pythonhosted.org/packages/source/h/%{modname}/%{modname}-%{version}.tar.gz +# PATCH-FIX-UPSTREAM https://github.com/psf/httpbin/pull/29 Support Flask 3.0 +Patch: flask3.patch BuildRequires: %{python_module Brotli} -BuildRequires: %{python_module Flask >= 2.1} -BuildRequires: %{python_module MarkupSafe} +BuildRequires: %{python_module Flask >= 2.2.4} BuildRequires: %{python_module Werkzeug >= 2.0} BuildRequires: %{python_module decorator} BuildRequires: %{python_module flasgger} BuildRequires: %{python_module gevent} -BuildRequires: %{python_module itsdangerous} +BuildRequires: %{python_module pip} BuildRequires: %{python_module pytest} BuildRequires: %{python_module setuptools} +BuildRequires: %{python_module wheel} BuildRequires: fdupes BuildRequires: python-rpm-macros Requires: python-Brotli -Requires: python-Flask >= 2.1 -Requires: python-MarkupSafe +Requires: python-Flask >= 2.2.4 Requires: python-Werkzeug >= 2.0 Requires: python-decorator Requires: python-flasgger Requires: python-gevent -Requires: python-itsdangerous Requires: python-six BuildArch: noarch %python_subpackages @@ -69,16 +60,17 @@ all kinds of HTTP scenarios. Additional endpoints are being considered. All endpoint responses are JSON-encoded. %prep -%autosetup -p1 -chmod -x httpbin/templates/forms-post.html +%autosetup -p1 -n %{modname}-%{version} +# we are running CPython, let us use Brotli instead of brotlicffi (they should be compatible) +sed -i 's/brotlicffi/brotli/' httpbin/filters.py %build export LANG=en_US.UTF-8 -%python_build +%pyproject_wheel %install export LANG=en_US.UTF-8 -%python_install +%pyproject_install %python_expand %fdupes %{buildroot}%{$python_sitelib} %check @@ -88,6 +80,6 @@ export LANG=en_US.UTF-8 %doc README.md %license LICENSE %{python_sitelib}/httpbin -%{python_sitelib}/httpbin-%{internalversion}*-info +%{python_sitelib}/httpbin-%{version}*-info %changelog diff --git a/support-werkzeug-2.3.patch b/support-werkzeug-2.3.patch deleted file mode 100644 index db72fdf..0000000 --- a/support-werkzeug-2.3.patch +++ /dev/null @@ -1,40 +0,0 @@ -Index: python-httpbin-0.7.0+git20181107.f8ec666/test_httpbin.py -=================================================================== ---- python-httpbin-0.7.0+git20181107.f8ec666.orig/test_httpbin.py -+++ python-httpbin-0.7.0+git20181107.f8ec666/test_httpbin.py -@@ -167,8 +167,8 @@ class HttpbinTestCase(unittest.TestCase) - - def test_base64(self): - greeting = u'Здравствуй, мир!' -- b64_encoded = _string_to_base64(greeting) -- response = self.app.get(b'/base64/' + b64_encoded) -+ b64_encoded = _string_to_base64(greeting).decode('utf-8') -+ response = self.app.get('/base64/' + b64_encoded) - content = response.data.decode('utf-8') - self.assertEqual(greeting, content) - -@@ -422,7 +422,7 @@ class HttpbinTestCase(unittest.TestCase) - body, stale_after + 1) - self.assertEqual(stale_response.status_code, 401) - header = stale_response.headers.get('WWW-Authenticate') -- self.assertIn('stale=TRUE', header) -+ self.assertIn('stale=True', header) - - def _test_digest_response_for_auth_request(self, header, username, password, qop, uri, body, nc=1, nonce=None): - auth_type, auth_info = header.split(None, 1) -@@ -474,13 +474,13 @@ class HttpbinTestCase(unittest.TestCase) - wrong_pass_response, nonce = self._test_digest_response_for_auth_request(header, username, "wrongPassword", qop, uri, body) - self.assertEqual(wrong_pass_response.status_code, 401) - header = wrong_pass_response.headers.get('WWW-Authenticate') -- self.assertNotIn('stale=TRUE', header) -+ self.assertNotIn('stale=True', header) - - reused_nonce_response, nonce = self._test_digest_response_for_auth_request(header, username, password, qop, uri, \ - body, nonce=nonce) - self.assertEqual(reused_nonce_response.status_code, 401) - header = reused_nonce_response.headers.get('WWW-Authenticate') -- self.assertIn('stale=TRUE', header) -+ self.assertIn('stale=True', header) - - def test_drip(self): - response = self.app.get('/drip?numbytes=400&duration=2&delay=1') diff --git a/werkzeug.patch b/werkzeug.patch deleted file mode 100644 index d369db0..0000000 --- a/werkzeug.patch +++ /dev/null @@ -1,34 +0,0 @@ -From b6cb2b47a3813da5df8dbffada284b72d7fe099e Mon Sep 17 00:00:00 2001 -From: Simon Kowallik -Date: Sat, 18 May 2019 13:10:08 +0200 -Subject: [PATCH] fix #554: update tests, Pipfile, Pipfile.lock for - werkzeug>=0.15.1 - -- update test_httpbin.py to reflect new behaviour of werkzeug -- require werkzeug>=0.15.1 ---- - Pipfile | 2 +- - Pipfile.lock | 6 +++--- - test_httpbin.py | 2 -- - 3 files changed, 4 insertions(+), 6 deletions(-) - -Index: python-httpbin-0.7.0+git20181107.f8ec666/test_httpbin.py -=================================================================== ---- python-httpbin-0.7.0+git20181107.f8ec666.orig/test_httpbin.py -+++ python-httpbin-0.7.0+git20181107.f8ec666/test_httpbin.py -@@ -148,7 +148,6 @@ class HttpbinTestCase(unittest.TestCase) - data = json.loads(response.data.decode('utf-8')) - self.assertEqual(data['args'], {}) - self.assertEqual(data['headers']['Host'], 'localhost') -- self.assertEqual(data['headers']['Content-Length'], '0') - self.assertEqual(data['headers']['User-Agent'], 'test') - # self.assertEqual(data['origin'], None) - self.assertEqual(data['url'], 'http://localhost/get') -@@ -162,7 +161,6 @@ class HttpbinTestCase(unittest.TestCase) - data = json.loads(response.data.decode('utf-8')) - self.assertEqual(data['args'], {}) - self.assertEqual(data['headers']['Host'], 'localhost') -- self.assertEqual(data['headers']['Content-Length'], '0') - self.assertEqual(data['url'], 'http://localhost/anything/foo/bar') - self.assertEqual(data['method'], 'GET') - self.assertTrue(response.data.endswith(b'\n'))