Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/werkzeug/wrappers/request.py: 38%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

268 statements  

1from __future__ import annotations 

2 

3import collections.abc as cabc 

4import functools 

5import json 

6import typing as t 

7import wsgiref.types as wt 

8from io import BytesIO 

9from types import TracebackType 

10 

11from .._internal import _wsgi_decoding_dance 

12from ..datastructures.file_storage import FileStorage 

13from ..datastructures.headers import EnvironHeaders 

14from ..datastructures.structures import CombinedMultiDict 

15from ..datastructures.structures import ImmutableMultiDict 

16from ..datastructures.structures import iter_multi_items 

17from ..datastructures.structures import MultiDict 

18from ..exceptions import BadRequest 

19from ..exceptions import RequestEntityTooLarge 

20from ..exceptions import UnsupportedMediaType 

21from ..formparser import _FormDataParser 

22from ..formparser import _make_stream_factory 

23from ..sansio.request import Request as _SansIORequest 

24from ..utils import cached_property 

25from ..wsgi import _FileWrapper 

26from ..wsgi import _get_server 

27from ..wsgi import _LimitedStream 

28 

29T = t.TypeVar("T") 

30 

31 

32class Request(_SansIORequest): 

33 """Represents an incoming WSGI HTTP request, with headers and body 

34 taken from the WSGI environment. Has properties and methods for 

35 using the functionality defined by various HTTP specs. The data in 

36 requests object is read-only. 

37 

38 Text data is assumed to use UTF-8 encoding, which should be true for 

39 the vast majority of modern clients. Using an encoding set by the 

40 client is unsafe in Python due to extra encodings it provides, such 

41 as ``zip``. To change the assumed encoding, subclass and replace 

42 :attr:`charset`. 

43 

44 :param environ: The WSGI environ is generated by the WSGI server and 

45 contains information about the server configuration and client 

46 request. 

47 :param shallow: Makes reading from :attr:`stream` (and any method 

48 that would read from it) raise a :exc:`RuntimeError`. Useful to 

49 prevent consuming the form data in middleware, which would make 

50 it unavailable to the final application. 

51 

52 .. versionchanged:: 3.2 

53 The ``populate_request`` parameter is deprecated and will be removed in 

54 Werkzeug 4.0. ``environ["werkzeug.request"]`` will no longer be set. 

55 

56 .. versionchanged:: 3.0 

57 The ``charset``, ``url_charset``, and ``encoding_errors`` parameters 

58 were removed. 

59 

60 .. versionchanged:: 2.1 

61 Old ``BaseRequest`` and mixin classes were removed. 

62 

63 .. versionchanged:: 2.1 

64 Remove the ``disable_data_descriptor`` attribute. 

65 

66 .. versionchanged:: 2.0 

67 Combine ``BaseRequest`` and mixins into a single ``Request`` 

68 class. 

69 

70 .. versionchanged:: 0.5 

71 Read-only mode is enforced with immutable classes for all data. 

72 """ 

73 

74 max_content_length: int | None = None 

75 """Stop reading data after this many bytes and raise 

76 :exc:`.RequestEntityTooLarge`. This amount of memory, plus additional object 

77 overhead, could be used during one request. 

78 

79 It's better to configure this in the WSGI server or HTTP server, rather than 

80 the WSGI application, which is why it's not set by default. Not setting it 

81 anywhere would be an issue with that application, not with Werkzeug. 

82 

83 This is applied to :attr:`stream` and anything that reads it such as 

84 :attr:`data` and :meth:`parse_form_data`. 

85 

86 .. versionadded:: 0.5 

87 """ 

88 

89 max_form_memory_size: int | None = 500_000 

90 """Stop parsing ``multipart/form-data`` if any non-file part is larger than 

91 this number of bytes, and raise :exc:`.RequestEntityTooLarge`. File parts 

92 can be larger, they are moved to disk at this limit. The default is 500kB. 

93 This is an additional check, it does not replace :attr:`max_content_length`. 

94 

95 .. versionchanged:: 3.1.9 

96 This is not applied to ``application/x-www-form-urlencoded``. 

97 

98 .. versionchanged:: 3.1 

99 Defaults to 500kb instead of unlimited. 

100 

101 .. versionadded:: 0.5 

102 """ 

103 

104 max_form_parts = 1000 

105 """Stop parsing ``multipart/form-data`` if more than this number of parts 

106 are received, and raise :exc:`.RequestEntityTooLarge`. This is useful to 

107 stop a very large number of very small fields, especially files. The 

108 default is 1000. This is an additional check, it does not replace 

109 :attr:`max_content_length`. 

110 

111 .. versionadded:: 2.2.3 

112 """ 

113 

114 form_data_parser_class: None = None 

115 """The class to use to parse form data. 

116 

117 .. deprecated:: 3.2 

118 Will be removed in Werkzeug 4.0. Override ``parse_form_data`` instead. 

119 """ 

120 

121 #: The WSGI environment containing HTTP headers and information from 

122 #: the WSGI server. 

123 environ: wt.WSGIEnvironment 

124 

125 #: Set when creating the request object. If ``True``, reading from 

126 #: the request body will cause a ``RuntimeException``. Useful to 

127 #: prevent modifying the stream from middleware. 

128 shallow: bool 

129 

130 def __init__( 

131 self, 

132 environ: wt.WSGIEnvironment, 

133 populate_request: None = None, 

134 shallow: bool = False, 

135 ) -> None: 

136 super().__init__( 

137 method=environ.get("REQUEST_METHOD", "GET"), 

138 scheme=environ.get("wsgi.url_scheme", "http"), 

139 server=_get_server(environ), 

140 root_path=_wsgi_decoding_dance(environ.get("SCRIPT_NAME") or ""), 

141 path=_wsgi_decoding_dance(environ.get("PATH_INFO") or ""), 

142 query_string=environ.get("QUERY_STRING", "").encode("latin1"), 

143 headers=EnvironHeaders(environ), 

144 remote_addr=environ.get("REMOTE_ADDR"), 

145 ) 

146 self.environ = environ 

147 self.shallow = shallow 

148 

149 if populate_request is not None: 

150 import warnings 

151 

152 warnings.warn( 

153 "The 'populate_request' parameter is deprecated and will be" 

154 " removed in Werkzeug 4.0. 'environ[\"werkzeug.request\"]' will" 

155 " no longer be set.", 

156 DeprecationWarning, 

157 stacklevel=2, 

158 ) 

159 else: 

160 populate_request = True # type: ignore[assignment] 

161 

162 if populate_request and not shallow: 

163 self.environ["werkzeug.request"] = self 

164 

165 @classmethod 

166 def from_values(cls, *args: t.Any, **kwargs: t.Any) -> t.Self: 

167 """Create a new request object based on the values provided. If 

168 environ is given missing values are filled from there. This method is 

169 useful for small scripts when you need to simulate a request from an URL. 

170 Do not use this method for unittesting, there is a full featured client 

171 object (:class:`Client`) that allows to create multipart requests, 

172 support for cookies etc. 

173 

174 This accepts the same options as the 

175 :class:`~werkzeug.test.EnvironBuilder`. 

176 

177 .. versionchanged:: 0.5 

178 This method now accepts the same arguments as 

179 :class:`~werkzeug.test.EnvironBuilder`. Because of this the 

180 `environ` parameter is now called `environ_overrides`. 

181 

182 :return: request object 

183 """ 

184 from ..test import EnvironBuilder 

185 

186 with EnvironBuilder(*args, **kwargs) as builder: 

187 return builder.get_request(cls) # type: ignore[return-value] 

188 

189 @t.overload 

190 @classmethod 

191 def application( 

192 cls, f: t.Callable[[T, t.Self], wt.WSGIApplication] 

193 ) -> t.Callable[[T, wt.WSGIEnvironment, wt.StartResponse], t.Iterable[bytes]]: ... 

194 @t.overload 

195 @classmethod 

196 def application( 

197 cls, f: t.Callable[[t.Self], wt.WSGIApplication] 

198 ) -> wt.WSGIApplication: ... 

199 @classmethod 

200 def application( 

201 cls, f: t.Callable[..., wt.WSGIApplication] 

202 ) -> t.Callable[..., t.Iterable[bytes]]: 

203 """Create a WSGI application by decorating a function that takes a 

204 :class:`Request` and returns a :class:`.Response`. If the function 

205 raises an :exc:`.HTTPException`, it will be converted to an error 

206 response. :meth:`Request.close` is called when returning. 

207 

208 .. code-block:: python 

209 

210 @Request.application 

211 def my_wsgi_app(request: Request) -> Response: 

212 return Response("Hello, World!") 

213 

214 If a request was already created with ``populate_request=True`` (the 

215 default) it will be taken from``environ["werkzeug.request"]`` instead of 

216 creating a new object. 

217 

218 :param f: The application callable. 

219 

220 .. versionchanged:: 0.14 

221 ``HTTPException`` is caught and converted to a response. 

222 """ 

223 from ..exceptions import HTTPException 

224 

225 @functools.wraps(f) 

226 def application(*args: t.Any) -> cabc.Iterable[bytes]: 

227 # Allow either a function (environ, start_response) or a 

228 # bound method (self, environ, start_response). 

229 *rest, environ, start_response = args 

230 

231 with cls(environ) as request: 

232 try: 

233 response = f(*rest, request) 

234 except HTTPException as e: 

235 response = e.get_response() 

236 

237 return response(request.environ, start_response) 

238 

239 return application 

240 

241 def _get_file_stream( 

242 self, 

243 total_content_length: int | None, 

244 content_type: str | None, 

245 filename: str | None = None, 

246 content_length: int | None = None, 

247 ) -> t.IO[bytes]: 

248 """Called to get a stream for the file upload. 

249 

250 This must provide a file-like class with `read()`, `readline()` 

251 and `seek()` methods that is both writeable and readable. 

252 

253 The default implementation returns a temporary file if the total 

254 content length is higher than 500KB. Because many browsers do not 

255 provide a content length for the files only the total content 

256 length matters. 

257 

258 :param total_content_length: the total content length of all the 

259 data in the request combined. This value 

260 is guaranteed to be there. 

261 :param content_type: the mimetype of the uploaded file. 

262 :param filename: the filename of the uploaded file. May be `None`. 

263 :param content_length: the length of this file. This value is usually 

264 not provided because webbrowsers do not provide 

265 this value. 

266 

267 .. deprecated:: 3.2 

268 Will be removed in Werkzeug 4.0. Override ``_parse_form_data`` instead. 

269 """ 

270 import warnings 

271 

272 warnings.warn( 

273 "'_get_file_stream' is deprecated and will be removed in Werkzeug 4.0." 

274 " Override '_parse_form_data` instead.", 

275 DeprecationWarning, 

276 stacklevel=2, 

277 ) 

278 return _make_stream_factory(self.max_form_memory_size)(None, None, None, None) 

279 

280 @property 

281 def want_form_data_parsed(self) -> bool: 

282 """``True`` if the request method carries content. By default 

283 this is true if a ``Content-Type`` is sent. 

284 

285 .. deprecated:: 3.2 

286 Will be removed in Werkzeug 4.0. Override ``_parse_form_data`` instead. 

287 

288 .. versionadded:: 0.8 

289 """ 

290 import warnings 

291 

292 warnings.warn( 

293 "'want_form_data_parsed' is deprecated and will be removed in Werkzeug 4.0." 

294 " Override '_parse_form_data' instead.", 

295 DeprecationWarning, 

296 stacklevel=2, 

297 ) 

298 return self.content_type is not None 

299 

300 def make_form_data_parser(self) -> _FormDataParser: 

301 """Creates the form data parser. Instantiates the 

302 :attr:`form_data_parser_class` with some parameters. 

303 

304 .. deprecated:: 3.2 

305 Will be removed in Werkzeug 4.0. Override ``_parse_form_data`` instead. 

306 

307 .. versionadded:: 0.8 

308 """ 

309 import warnings 

310 

311 warnings.warn( 

312 "'make_form_data_parser' is deprecated and will be removed in Werkzeug 4.0." 

313 " Override '_parse_form_data' instead.", 

314 DeprecationWarning, 

315 stacklevel=2, 

316 ) 

317 return self._private_make_form_data_parser() 

318 

319 def _private_make_form_data_parser(self) -> _FormDataParser: 

320 kwargs: dict[str, t.Any] = { 

321 "max_form_memory_size": self.max_form_memory_size, 

322 "max_content_length": self.max_content_length, 

323 "max_form_parts": self.max_form_parts, 

324 } 

325 

326 if type(self)._get_file_stream is not Request._get_file_stream: 

327 import warnings 

328 

329 warnings.warn( 

330 "'Request._get_file_stream' is deprecated and will not be used in" 

331 " Werkzeug 4.0. Override '_parse_form_data' instead.", 

332 DeprecationWarning, 

333 stacklevel=1, 

334 ) 

335 kwargs["stream_factory"] = self._get_file_stream 

336 

337 if self.parameter_storage_class is not None: 

338 import warnings 

339 

340 warnings.warn( 

341 "Setting 'Request.parameter_storage_class' is deprecated and will be" 

342 " removed in Werkzeug 4.0. It will always be 'ImmutableMultiDict'.", 

343 DeprecationWarning, 

344 stacklevel=1, 

345 ) 

346 kwargs["cls"] = self.parameter_storage_class 

347 

348 if self.form_data_parser_class is not None: 

349 import warnings 

350 

351 warnings.warn( 

352 "Setting 'Request.form_data_parser_class' is deprecated and will be" 

353 " removed in Werkzeug 4.0. Override '_parse_form_data' instead.", 

354 DeprecationWarning, 

355 stacklevel=1, 

356 ) 

357 return self.form_data_parser_class(**kwargs) 

358 

359 return _FormDataParser(**kwargs) 

360 

361 def _parse_form_data( 

362 self, stream: t.IO[bytes] 

363 ) -> tuple[MultiDict[str, str], MultiDict[str, FileStorage]] | None: 

364 """Parse the given stream as form data. 

365 

366 :param stream: The stream to read the data from. 

367 :return: ``(form, files)``, or ``None`` if the data could not be parsed. 

368 

369 .. versionadded:: 3.2 

370 """ 

371 if type(self).make_form_data_parser is not Request.make_form_data_parser: 

372 import warnings 

373 

374 warnings.warn( 

375 "'Request.make_form_data_parser' is deprecated and will not be used in" 

376 " Werkzeug 4.0. Override `_parse_form_data` instead.", 

377 DeprecationWarning, 

378 stacklevel=1, 

379 ) 

380 parser = self.make_form_data_parser() 

381 else: 

382 # TODO inline after deprecation 

383 parser = self._private_make_form_data_parser() 

384 

385 _, form, files = parser.parse( 

386 stream=stream, 

387 mimetype=self.mimetype, 

388 content_length=self.content_length, 

389 options=self.mimetype_params, 

390 ) 

391 return form, files 

392 

393 def _load_form_data(self) -> None: 

394 """Internal method to parse and cache form data. 

395 

396 .. versionadded:: 0.8 

397 

398 :meta private: 

399 """ 

400 if "form" in self.__dict__: 

401 # The data has already been parsed and cached. 

402 return 

403 

404 if type(self).want_form_data_parsed is not Request.want_form_data_parsed: 

405 import warnings 

406 

407 warnings.warn( 

408 "'Request.want_form_data_parsed' is deprecated and will be removed in" 

409 " Werkzeug 4.0. Override '_parse_form_data' instead.", 

410 DeprecationWarning, 

411 stacklevel=1, 

412 ) 

413 

414 if not self.want_form_data_parsed: 

415 if self.parameter_storage_class is not None: 

416 import warnings 

417 

418 warnings.warn( 

419 "Setting 'Request.parameter_storage_class' is deprecated and" 

420 " will be removed in Werkzeug 4.0. It will always be" 

421 " 'ImmutableMultiDict'.", 

422 DeprecationWarning, 

423 stacklevel=1, 

424 ) 

425 self.form = self.parameter_storage_class() 

426 self.files = self.parameter_storage_class() 

427 else: 

428 self.form = ImmutableMultiDict() 

429 self.files = ImmutableMultiDict() 

430 else: 

431 if ( 

432 type(self)._get_stream_for_parsing 

433 is not Request._get_stream_for_parsing 

434 ): 

435 import warnings 

436 

437 warnings.warn( 

438 "'Request._get_stream_for_parsing' is deprecated and will not be" 

439 " used in Werkzeug 4.0. It is handled internally.", 

440 DeprecationWarning, 

441 stacklevel=1, 

442 ) 

443 stream = self._get_stream_for_parsing() 

444 else: 

445 # TODO inline after deprecation 

446 stream = self._private_get_stream_for_parsing() 

447 

448 result = self._parse_form_data(stream) 

449 

450 if result is None: 

451 self.form = ImmutableMultiDict() 

452 self.files = ImmutableMultiDict() 

453 else: 

454 self.form, self.files = result # type: ignore[assignment] 

455 

456 def _get_stream_for_parsing(self) -> t.IO[bytes]: 

457 """Access :attr:`stream`. If :meth:`get_data` has already read and 

458 cached the data, return a stream of the cached data instead. 

459 

460 .. deprecated:: 3.2 

461 Will be removed in Werkzeug 4.0. Override ``_parse_form_data`` instead. 

462 

463 .. versionadded:: 0.9.3 

464 """ 

465 import warnings 

466 

467 warnings.warn( 

468 "'_get_stream_for_parsing' is deprecated and will be removed in Werkzeug" 

469 " 4.0. Override '_parse_form_data' instead.", 

470 DeprecationWarning, 

471 stacklevel=2, 

472 ) 

473 return self._private_get_stream_for_parsing() 

474 

475 def _private_get_stream_for_parsing(self) -> t.IO[bytes]: 

476 if self._cached_data is not None: 

477 return BytesIO(self._cached_data) 

478 

479 return self.stream 

480 

481 def close(self) -> None: 

482 """Closes associated resources of this request object. This 

483 closes all file handles explicitly. You can also use the request 

484 object in a with statement which will automatically close it. 

485 

486 .. versionadded:: 0.9 

487 """ 

488 files = self.__dict__.get("files") 

489 for _key, value in iter_multi_items(files or ()): 

490 value.close() 

491 

492 def __enter__(self) -> Request: 

493 return self 

494 

495 def __exit__( 

496 self, 

497 exc_type: type[BaseException] | None, 

498 exc_val: BaseException | None, 

499 exc_tb: TracebackType | None, 

500 ) -> None: 

501 self.close() 

502 

503 @cached_property 

504 def stream(self) -> t.IO[bytes]: 

505 """The WSGI input stream, wrapped so that it may be read safely and not 

506 past the ``Content-Length`` header or :attr:`max_content_length`. 

507 

508 Use :meth:`get_data` to get the full data as bytes or text. The 

509 :attr:`data` attribute will contain the full bytes only if they do not 

510 represent form data. The :attr:`form` and :attr:`files` attributes will 

511 contain the parsed form data in that case. 

512 

513 If the client sends ``Content-Length``, :attr:`max_content_length` can 

514 be checked immediately, or if that's not set the stream will be limited 

515 to ``Content-Length``. If the client does not send ``Content-Length``, 

516 it is not safe to read and an empty stream is returned. 

517 

518 However, the WSGI server can set ``environ["wsgi.input_terminated"]`` to 

519 indicate that it handles input without ``Content-Length``, such as by 

520 using non-blocking reads, buffering, and termination. This does not mean 

521 the stream might not be infinite, only that it is now safe to read. 

522 Therefore, you should still set :attr:`max_content_length`. 

523 

524 If the limit is reached before the underlying stream is exhausted, its 

525 remaining content cannot be read safely. Depending on how the server 

526 handles this, clients may show a "connection reset" failure instead of 

527 seeing the 413 response. 

528 

529 :raise .RequestEntityTooLarge: If :attr:`max_content_length` is exceeded. 

530 

531 .. versionchanged:: 2.3.2 

532 ``max_content_length`` is only applied to requests if the server 

533 sets ``wsgi.input_terminated``. 

534 

535 .. versionchanged:: 2.3 

536 Check ``max_content_length`` preemptively and while reading. 

537 

538 .. versionchanged:: 0.9 

539 The stream remains available (but consumed) if form parsing was 

540 accessed first. 

541 """ 

542 if self.shallow: 

543 raise RuntimeError( 

544 "This request was created with 'shallow=True', reading" 

545 " from the input stream is disabled." 

546 ) 

547 

548 stream: t.IO[bytes] = self.environ["wsgi.input"] 

549 

550 if ( 

551 self.content_length is not None 

552 and self.max_content_length is not None 

553 and self.content_length > self.max_content_length 

554 ): 

555 raise RequestEntityTooLarge() 

556 

557 # A WSGI server can set this to indicate that it terminates the input 

558 # stream. In that case the stream is safe without wrapping, or can 

559 # enforce a max length. 

560 if "wsgi.input_terminated" in self.environ: 

561 if self.max_content_length is not None: 

562 # If this is moved above, it can cause the stream to hang if a 

563 # read attempt is made when the client sends no data. For 

564 # example, the development server does not handle buffering 

565 # except for chunked encoding. 

566 return _LimitedStream(stream, self.max_content_length, is_max=True) # type: ignore[return-value] 

567 

568 return stream 

569 

570 # No limit given, stream can't be read safely, return empty. 

571 if self.content_length is None: 

572 return BytesIO() 

573 

574 return _LimitedStream(stream, self.content_length) # type: ignore[return-value] 

575 

576 @property 

577 def input_stream(self) -> t.IO[bytes]: 

578 """The raw WSGI input stream, without any safety checks. 

579 

580 This is dangerous to use. It does not guard against infinite streams or 

581 reading past :attr:`content_length` or :attr:`max_content_length`. 

582 

583 Use :attr:`stream` instead. 

584 

585 .. deprecated:: 3.2 

586 Will be removed in Werkzeug 4.0. Use ``environ["REMOTE_USER"]`` instead. 

587 """ 

588 import warnings 

589 

590 warnings.warn( 

591 "The 'input_stream' attribute is deprecated and will be removed in" 

592 " Werkzeug 4.0. Use 'stream' instead.", 

593 DeprecationWarning, 

594 stacklevel=2, 

595 ) 

596 return self.environ["wsgi.input"] # type: ignore[no-any-return] 

597 

598 @cached_property 

599 def data(self) -> bytes: 

600 """The raw data read from :attr:`stream`. Will be empty if the request 

601 represents form data. 

602 

603 Typically, you'll want to access :attr:`form`, :attr:`files`, or 

604 :attr:`json`. You only need this if the body is in another format. 

605 

606 To get the raw data even if it represents form data, use :meth:`get_data`. 

607 """ 

608 return self.get_data(parse_form_data=True) 

609 

610 _cached_data: bytes | None = None 

611 

612 @t.overload 

613 def get_data( 

614 self, 

615 cache: bool = True, 

616 as_text: t.Literal[False] = False, 

617 parse_form_data: bool = False, 

618 ) -> bytes: ... 

619 

620 @t.overload 

621 def get_data( 

622 self, 

623 cache: bool = True, 

624 as_text: t.Literal[True] = ..., 

625 parse_form_data: bool = False, 

626 ) -> str: ... 

627 

628 def get_data( 

629 self, cache: bool = True, as_text: bool = False, parse_form_data: bool = False 

630 ) -> bytes | str: 

631 """The raw data read from :attr:`stream`. 

632 

633 Typically, you'll want to access :attr:`form`, :attr:`files`, or 

634 :attr:`json`. You only need this if the body is in another format. 

635 

636 See :attr:`stream` for how the input is read safely. In summary, either 

637 the client must send the ``Content-Length`` header, or the WSGI server 

638 must handle terminating input. Otherwise, an empty stream is returned. 

639 Set :attr:`max_content_length` to prevent infinite streams, otherwise 

640 this call may block forever. 

641 

642 :param cache: Cache the result. Otherwise, subsequent calls will return 

643 empty. If you know you'll only access it once, disabling this is 

644 more efficient. 

645 :param as_text: Decode the bytes as UTF-8 and return a string. 

646 :param parse_form_data: Parse the body as form data if possible. This 

647 will then return empty, since the data is in :attr:`form` and 

648 :attr:`files`. :attr:`data` is a shortcut for this. 

649 :raise .RequestEntityTooLarge: If :attr:`max_content_length` is exceeded. 

650 

651 .. versionadded:: 0.9 

652 """ 

653 if (data := self._cached_data) is None: 

654 if parse_form_data: 

655 self._load_form_data() 

656 

657 data = self.stream.read() 

658 

659 if cache: 

660 self._cached_data = data 

661 

662 if as_text: 

663 return data.decode(errors="replace") 

664 

665 return data 

666 

667 @cached_property 

668 def form(self) -> ImmutableMultiDict[str, str]: 

669 """The parsed form text fields as an :class:`.ImmutableMultiDict`. File 

670 fields are in :attr:`files`, not here. 

671 

672 .. versionchanged:: 0.9 

673 Works for any method, not only ``POST`` and ``PUT``. 

674 """ 

675 self._load_form_data() 

676 return self.form 

677 

678 @cached_property 

679 def values(self) -> CombinedMultiDict[str, str]: 

680 """A :class:`werkzeug.datastructures.CombinedMultiDict` that 

681 combines :attr:`args` and :attr:`form`. 

682 

683 For GET requests, only ``args`` are present, not ``form``. 

684 

685 .. versionchanged:: 2.0 

686 For GET requests, only ``args`` are present, not ``form``. 

687 """ 

688 sources = [self.args] 

689 

690 if self.method != "GET": 

691 # GET requests can have a body, and some caching proxies 

692 # might not treat that differently than a normal GET 

693 # request, allowing form data to "invisibly" affect the 

694 # cache without indication in the query string / URL. 

695 sources.append(self.form) 

696 

697 args = [] 

698 

699 for d in sources: 

700 # TODO remove with parameter_storage_class 

701 if not isinstance(d, MultiDict): 

702 d = MultiDict(d) 

703 

704 args.append(d) 

705 

706 return CombinedMultiDict(args) 

707 

708 @cached_property 

709 def files(self) -> ImmutableMultiDict[str, FileStorage]: 

710 """The parsed form file fields as an :class:`.ImmutableMultiDict`. Text 

711 fields are in :attr:`form`, not here. 

712 

713 This will only be populated if the HTML form has the 

714 ``enctype=multipart/form-data`` attribute. 

715 

716 Each value is a :class:`.FileStorage` object. ``FileStorage`` is 

717 file-like, for example it has a ``read()`` method and is iterable. The 

718 :meth:`~.FileStorage.save` method can be used to save the data, along 

719 with the :func:`.secure_filename` function. 

720 """ 

721 self._load_form_data() 

722 return self.files 

723 

724 @property 

725 def script_root(self) -> str: 

726 """Alias for :attr:`self.root_path`. ``environ["SCRIPT_NAME"]`` 

727 without a trailing slash. 

728 """ 

729 return self.root_path 

730 

731 @cached_property 

732 def url_root(self) -> str: 

733 """Alias for :attr:`root_url`. The URL with scheme, host, and 

734 root path. For example, ``https://example.com/app/``. 

735 """ 

736 return self.root_url 

737 

738 @property 

739 def remote_user(self) -> str | None: 

740 """The ``REMOTE_USER`` CGI variable from :attr:`environ`. 

741 

742 .. deprecated:: 3.2 

743 Will be removed in Werkzeug 4.0. Use ``environ["REMOTE_USER"]`` instead. 

744 """ 

745 import warnings 

746 

747 warnings.warn( 

748 "The 'remote_user' attribute is deprecated and will be removed in" 

749 " Werkzeug 4.0. Use 'environ[\"REMOTE_USER\"]' instead.", 

750 DeprecationWarning, 

751 stacklevel=2, 

752 ) 

753 return self.environ.get("REMOTE_USER") 

754 

755 @property 

756 def is_multithread(self) -> str | None: 

757 """Indicates the WSGI server uses thread workers. 

758 

759 .. deprecated:: 3.2 

760 Will be removed in Werkzeug 4.0. Use 

761 ``environ["wsgi.multithread"]`` instead. 

762 """ 

763 import warnings 

764 

765 warnings.warn( 

766 "The 'is_multithread' attribute is deprecated and will be removed in" 

767 " Werkzeug 4.0. Use 'environ[\"wsgi.multithread\"]' instead.", 

768 DeprecationWarning, 

769 stacklevel=2, 

770 ) 

771 return self.environ["wsgi.multithread"] # type: ignore[no-any-return] 

772 

773 @property 

774 def is_multiprocess(self) -> str | None: 

775 """Indicates the WSGI server uses process workers. 

776 

777 .. deprecated:: 3.2 

778 Will be removed in Werkzeug 4.0. Use 

779 ``environ["wsgi.multiprocess"]`` instead. 

780 """ 

781 import warnings 

782 

783 warnings.warn( 

784 "The 'is_multiprocess' attribute is deprecated and will be removed in" 

785 " Werkzeug 4.0. Use 'environ[\"wsgi.multiprocess\"]' instead.", 

786 DeprecationWarning, 

787 stacklevel=2, 

788 ) 

789 return self.environ["wsgi.multiprocess"] # type: ignore[no-any-return] 

790 

791 @property 

792 def is_run_once(self) -> str | None: 

793 """Indicates the WSGI server process will start, handle one request, 

794 then stop. This may be the case for CGI. 

795 

796 .. deprecated:: 3.2 

797 Will be removed in Werkzeug 4.0. Use 

798 ``environ["wsgi.run_once"]`` instead. 

799 """ 

800 import warnings 

801 

802 warnings.warn( 

803 "The 'is_run_once' attribute is deprecated and will be removed in" 

804 " Werkzeug 4.0. Use 'environ[\"wsgi.run_once\"]' instead.", 

805 DeprecationWarning, 

806 stacklevel=2, 

807 ) 

808 return self.environ["wsgi.run_once"] # type: ignore[no-any-return] 

809 

810 # JSON 

811 

812 #: A module or other object that has ``dumps`` and ``loads`` 

813 #: functions that match the API of the built-in :mod:`json` module. 

814 json_module = json 

815 

816 @property 

817 def json(self) -> t.Any: 

818 """The parsed JSON data if :attr:`mimetype` indicates JSON 

819 (:mimetype:`application/json`, see :attr:`is_json`). 

820 

821 Calls :meth:`get_json` with default arguments. 

822 

823 If the request content type is not ``application/json``, this 

824 will raise a 415 Unsupported Media Type error. 

825 

826 .. versionchanged:: 2.3 

827 Raise a 415 error instead of 400. 

828 

829 .. versionchanged:: 2.1 

830 Raise a 400 error if the content type is incorrect. 

831 """ 

832 return self.get_json() 

833 

834 # Cached values for ``(silent=False, silent=True)``. Initialized 

835 # with sentinel values. 

836 _cached_json: tuple[t.Any, t.Any] = (Ellipsis, Ellipsis) 

837 

838 @t.overload 

839 def get_json( 

840 self, force: bool = ..., silent: t.Literal[False] = ..., cache: bool = ... 

841 ) -> t.Any: ... 

842 

843 @t.overload 

844 def get_json( 

845 self, force: bool = ..., silent: bool = ..., cache: bool = ... 

846 ) -> t.Any | None: ... 

847 

848 def get_json( 

849 self, force: bool = False, silent: bool = False, cache: bool = True 

850 ) -> t.Any | None: 

851 """Parse :attr:`data` as JSON. 

852 

853 If the mimetype does not indicate JSON 

854 (:mimetype:`application/json`, see :attr:`is_json`), or parsing 

855 fails, :meth:`on_json_loading_failed` is called and 

856 its return value is used as the return value. By default this 

857 raises a 415 Unsupported Media Type resp. 

858 

859 :param force: Ignore the mimetype and always try to parse JSON. 

860 :param silent: Silence mimetype and parsing errors, and 

861 return ``None`` instead. 

862 :param cache: Store the parsed JSON to return for subsequent 

863 calls. 

864 

865 .. versionchanged:: 2.3 

866 Raise a 415 error instead of 400. 

867 

868 .. versionchanged:: 2.1 

869 Raise a 400 error if the content type is incorrect. 

870 """ 

871 if cache and self._cached_json[silent] is not Ellipsis: 

872 return self._cached_json[silent] 

873 

874 if not (force or self.is_json): 

875 if not silent: 

876 return self.on_json_loading_failed(None) 

877 else: 

878 return None 

879 

880 data = self.get_data(cache=cache) 

881 

882 try: 

883 rv = self.json_module.loads(data) 

884 except ValueError as e: 

885 if silent: 

886 rv = None 

887 

888 if cache: 

889 normal_rv, _ = self._cached_json 

890 self._cached_json = (normal_rv, rv) 

891 else: 

892 rv = self.on_json_loading_failed(e) 

893 

894 if cache: 

895 _, silent_rv = self._cached_json 

896 self._cached_json = (rv, silent_rv) 

897 else: 

898 if cache: 

899 self._cached_json = (rv, rv) 

900 

901 return rv 

902 

903 def on_json_loading_failed(self, e: ValueError | None) -> t.Any: 

904 """Called if :meth:`get_json` fails and isn't silenced. 

905 

906 If this method returns a value, it is used as the return value 

907 for :meth:`get_json`. The default implementation raises 

908 :exc:`~werkzeug.exceptions.BadRequest`. 

909 

910 :param e: If parsing failed, this is the exception. It will be 

911 ``None`` if the content type wasn't ``application/json``. 

912 

913 .. versionchanged:: 2.3 

914 Raise a 415 error instead of 400. 

915 """ 

916 if e is not None: 

917 raise BadRequest(f"Failed to decode JSON object: {e}") 

918 

919 raise UnsupportedMediaType( 

920 "Did not attempt to load JSON data because the request" 

921 " Content-Type was not 'application/json'." 

922 ) 

923 

924 def wrap_file( 

925 self, file: t.IO[bytes], buffer_size: int = 128 * 1024 

926 ) -> cabc.Iterable[bytes]: 

927 """Wrap a file with ``environ["wsgi.file_wrapper"]``, to be sent in a 

928 :class:`.Response`. The WSGI server provides this if it has a way to 

929 send file data more efficiently. If it's not provided, uses a basic 

930 wrapper for consistent iteration. 

931 

932 You'll also want to set :attr:`.Response.direct_passthrough` to ``True`` 

933 to tell the response not to do its own iteration. 

934 

935 Use :attr:`send_file` instead of generating a file response manually. It 

936 will handle caching, range requests, wrapping, and more. 

937 

938 :param file: A file-like object in ``rb`` mode. 

939 :param buffer_size: Number of bytes to read for each iteration. Defaults 

940 to 128 KiB. 

941 

942 .. versionadded:: 3.2 

943 """ 

944 cls: wt.FileWrapper = self.environ.get("wsgi.file_wrapper", _FileWrapper) 

945 return cls(file, buffer_size)