Allow setting the response status code in the mockserver response-headers resource

This commit is contained in:
Adrian Chaves 2026-08-06 15:35:12 +02:00
parent dafff0edfd
commit 689e762896
3 changed files with 17 additions and 74 deletions

View File

@ -380,11 +380,13 @@ class UriResource(BaseResource):
class ResponseHeadersResource(BaseResource):
"""Return a response with headers set from the JSON request body"""
"""Return a response with headers set from the JSON request body, and the
status code set from the *n* URL parameter, 200 by default."""
def render(self, request: Request) -> bytes:
assert request.content
body = json.loads(request.content.read().decode())
request.setResponseCode(getarg(request, b"n", 200, type_=int))
for header_name, header_value in body.items():
request.responseHeaders.setRawHeaders(header_name, [header_value])
return json.dumps(body).encode("utf-8")

View File

@ -1,73 +0,0 @@
import json
from twisted.internet import defer
from twisted.trial.unittest import TestCase
from scrapy.crawler import CrawlerRunner
from scrapy.http import Request
from tests.mockserver import MockServer
from tests.spiders import MetaSpider
class CookiesSpider(MetaSpider):
name = "cookies"
def start_requests(self):
url = self.mockserver.url("/echo2/")
for status in [200, 302, 503]:
# Response params that mockserver will return
body = {
"status": status,
"headers": {
"Set-cookie": f"status={status}",
},
"body": "<html></html>",
}
if status == 302:
body["headers"]["location"] = self.mockserver.url("/")
yield Request(
url,
callback=self.parse,
meta={"cookiejar": status},
body=json.dumps(body),
)
def parse(self, response):
pass
def close(self, spider):
mw = [
m
for m in self.crawler.engine.downloader.middleware.middlewares
if "Cookies" in str(type(m))
][0]
jars_data = {}
for k, jar in mw.jars.items():
jars_data[k] = {
s: v.value for s, v in jar._cookies["127.0.0.1"]["/echo2"].items()
}
self.crawler.stats._stats["cookies_values"] = jars_data
class CookiesTestCase(TestCase):
def setUp(self):
self.mockserver = MockServer()
self.mockserver.__enter__()
self.runner = CrawlerRunner()
def tearDown(self):
self.mockserver.__exit__(None, None, None)
@defer.inlineCallbacks
def test_cookies(self):
crawler = CrawlerRunner().create_crawler(CookiesSpider)
yield crawler.crawl(mockserver=self.mockserver)
cookies_stats = crawler.stats._stats.get("cookies_values")
expected_cookies = {
200: {"status": "200"},
302: {"status": "302"},
503: {"status": "503"},
}
self.assertEqual(cookies_stats, expected_cookies)

View File

@ -284,6 +284,20 @@ class TestHttpBase(ABC):
header_value.encode(encoding="utf-8")
]
@coroutine_test
async def test_download_has_correct_response_status_and_headers(
self, mockserver: MockServer
) -> None:
request = Request(
mockserver.url("/response-headers?n=302", is_secure=self.is_secure),
headers={"content-type": "application/json"},
body=json.dumps({"Set-Cookie": "status=302"}),
)
async with self.get_dh() as download_handler:
response = await download_handler.download_request(request)
assert response.status == 302
assert response.headers.getlist("Set-Cookie") == [b"status=302"]
@coroutine_test
async def test_download_no_extra_response_headers(
self, mockserver: MockServer