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

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

176 statements  

1from __future__ import annotations 

2 

3import collections.abc as cabc 

4import functools 

5import json 

6import typing as t 

7from io import BytesIO 

8 

9from .._internal import _wsgi_decoding_dance 

10from ..datastructures import CombinedMultiDict 

11from ..datastructures import EnvironHeaders 

12from ..datastructures import FileStorage 

13from ..datastructures import ImmutableMultiDict 

14from ..datastructures import iter_multi_items 

15from ..datastructures import MultiDict 

16from ..exceptions import BadRequest 

17from ..exceptions import UnsupportedMediaType 

18from ..formparser import default_stream_factory 

19from ..formparser import FormDataParser 

20from ..sansio.request import Request as _SansIORequest 

21from ..utils import cached_property 

22from ..utils import environ_property 

23from ..wsgi import _get_server 

24from ..wsgi import get_input_stream 

25 

26if t.TYPE_CHECKING: 

27 from _typeshed.wsgi import WSGIApplication 

28 from _typeshed.wsgi import WSGIEnvironment 

29 

30 

31class Request(_SansIORequest): 

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

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

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

35 requests object is read-only. 

36 

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

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

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

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

41 :attr:`charset`. 

42 

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

44 contains information about the server configuration and client 

45 request. 

46 :param populate_request: Add this request object to the WSGI environ 

47 as ``environ['werkzeug.request']``. Can be useful when 

48 debugging. 

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

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

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

52 it unavailable to the final application. 

53 

54 .. versionchanged:: 3.0 

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

56 were removed. 

57 

58 .. versionchanged:: 2.1 

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

60 

61 .. versionchanged:: 2.1 

62 Remove the ``disable_data_descriptor`` attribute. 

63 

64 .. versionchanged:: 2.0 

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

66 class. 

67 

68 .. versionchanged:: 0.5 

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

70 """ 

71 

72 #: the maximum content length. This is forwarded to the form data 

73 #: parsing function (:func:`parse_form_data`). When set and the 

74 #: :attr:`form` or :attr:`files` attribute is accessed and the 

75 #: parsing fails because more than the specified value is transmitted 

76 #: a :exc:`~werkzeug.exceptions.RequestEntityTooLarge` exception is raised. 

77 #: 

78 #: .. versionadded:: 0.5 

79 max_content_length: int | None = None 

80 

81 #: the maximum form field size. This is forwarded to the form data 

82 #: parsing function (:func:`parse_form_data`). When set and the 

83 #: :attr:`form` or :attr:`files` attribute is accessed and the 

84 #: data in memory for post data is longer than the specified value a 

85 #: :exc:`~werkzeug.exceptions.RequestEntityTooLarge` exception is raised. 

86 #: 

87 #: .. versionadded:: 0.5 

88 max_form_memory_size: int | None = None 

89 

90 #: The maximum number of multipart parts to parse, passed to 

91 #: :attr:`form_data_parser_class`. Parsing form data with more than this 

92 #: many parts will raise :exc:`~.RequestEntityTooLarge`. 

93 #: 

94 #: .. versionadded:: 2.2.3 

95 max_form_parts = 1000 

96 

97 #: The form data parser that should be used. Can be replaced to customize 

98 #: the form date parsing. 

99 form_data_parser_class: type[FormDataParser] = FormDataParser 

100 

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

102 #: the WSGI server. 

103 environ: WSGIEnvironment 

104 

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

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

107 #: prevent modifying the stream from middleware. 

108 shallow: bool 

109 

110 def __init__( 

111 self, 

112 environ: WSGIEnvironment, 

113 populate_request: bool = True, 

114 shallow: bool = False, 

115 ) -> None: 

116 super().__init__( 

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

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

119 server=_get_server(environ), 

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

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

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

123 headers=EnvironHeaders(environ), 

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

125 ) 

126 self.environ = environ 

127 self.shallow = shallow 

128 

129 if populate_request and not shallow: 

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

131 

132 @classmethod 

133 def from_values(cls, *args: t.Any, **kwargs: t.Any) -> Request: 

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

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

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

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

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

139 support for cookies etc. 

140 

141 This accepts the same options as the 

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

143 

144 .. versionchanged:: 0.5 

145 This method now accepts the same arguments as 

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

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

148 

149 :return: request object 

150 """ 

151 from ..test import EnvironBuilder 

152 

153 builder = EnvironBuilder(*args, **kwargs) 

154 try: 

155 return builder.get_request(cls) 

156 finally: 

157 builder.close() 

158 

159 @classmethod 

160 def application(cls, f: t.Callable[[Request], WSGIApplication]) -> WSGIApplication: 

161 """Decorate a function as responder that accepts the request as 

162 the last argument. This works like the :func:`responder` 

163 decorator but the function is passed the request object as the 

164 last argument and the request object will be closed 

165 automatically:: 

166 

167 @Request.application 

168 def my_wsgi_app(request): 

169 return Response('Hello World!') 

170 

171 As of Werkzeug 0.14 HTTP exceptions are automatically caught and 

172 converted to responses instead of failing. 

173 

174 :param f: the WSGI callable to decorate 

175 :return: a new WSGI callable 

176 """ 

177 #: return a callable that wraps the -2nd argument with the request 

178 #: and calls the function with all the arguments up to that one and 

179 #: the request. The return value is then called with the latest 

180 #: two arguments. This makes it possible to use this decorator for 

181 #: both standalone WSGI functions as well as bound methods and 

182 #: partially applied functions. 

183 from ..exceptions import HTTPException 

184 

185 @functools.wraps(f) 

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

187 request = cls(args[-2]) 

188 with request: 

189 try: 

190 resp = f(*args[:-2] + (request,)) 

191 except HTTPException as e: 

192 resp = t.cast("WSGIApplication", e.get_response(args[-2])) 

193 return resp(*args[-2:]) 

194 

195 return t.cast("WSGIApplication", application) 

196 

197 def _get_file_stream( 

198 self, 

199 total_content_length: int | None, 

200 content_type: str | None, 

201 filename: str | None = None, 

202 content_length: int | None = None, 

203 ) -> t.IO[bytes]: 

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

205 

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

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

208 

209 The default implementation returns a temporary file if the total 

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

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

212 length matters. 

213 

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

215 data in the request combined. This value 

216 is guaranteed to be there. 

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

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

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

220 not provided because webbrowsers do not provide 

221 this value. 

222 """ 

223 return default_stream_factory( 

224 total_content_length=total_content_length, 

225 filename=filename, 

226 content_type=content_type, 

227 content_length=content_length, 

228 ) 

229 

230 @property 

231 def want_form_data_parsed(self) -> bool: 

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

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

234 

235 .. versionadded:: 0.8 

236 """ 

237 return bool(self.environ.get("CONTENT_TYPE")) 

238 

239 def make_form_data_parser(self) -> FormDataParser: 

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

241 :attr:`form_data_parser_class` with some parameters. 

242 

243 .. versionadded:: 0.8 

244 """ 

245 return self.form_data_parser_class( 

246 stream_factory=self._get_file_stream, 

247 max_form_memory_size=self.max_form_memory_size, 

248 max_content_length=self.max_content_length, 

249 max_form_parts=self.max_form_parts, 

250 cls=self.parameter_storage_class, 

251 ) 

252 

253 def _load_form_data(self) -> None: 

254 """Method used internally to retrieve submitted data. After calling 

255 this sets `form` and `files` on the request object to multi dicts 

256 filled with the incoming form data. As a matter of fact the input 

257 stream will be empty afterwards. You can also call this method to 

258 force the parsing of the form data. 

259 

260 .. versionadded:: 0.8 

261 """ 

262 # abort early if we have already consumed the stream 

263 if "form" in self.__dict__: 

264 return 

265 

266 if self.want_form_data_parsed: 

267 parser = self.make_form_data_parser() 

268 data = parser.parse( 

269 self._get_stream_for_parsing(), 

270 self.mimetype, 

271 self.content_length, 

272 self.mimetype_params, 

273 ) 

274 else: 

275 data = ( 

276 self.stream, 

277 self.parameter_storage_class(), 

278 self.parameter_storage_class(), 

279 ) 

280 

281 # inject the values into the instance dict so that we bypass 

282 # our cached_property non-data descriptor. 

283 d = self.__dict__ 

284 d["stream"], d["form"], d["files"] = data 

285 

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

287 """This is the same as accessing :attr:`stream` with the difference 

288 that if it finds cached data from calling :meth:`get_data` first it 

289 will create a new stream out of the cached data. 

290 

291 .. versionadded:: 0.9.3 

292 """ 

293 cached_data = getattr(self, "_cached_data", None) 

294 if cached_data is not None: 

295 return BytesIO(cached_data) 

296 return self.stream 

297 

298 def close(self) -> None: 

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

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

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

302 

303 .. versionadded:: 0.9 

304 """ 

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

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

307 value.close() 

308 

309 def __enter__(self) -> Request: 

310 return self 

311 

312 def __exit__(self, exc_type, exc_value, tb) -> None: # type: ignore 

313 self.close() 

314 

315 @cached_property 

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

317 """The WSGI input stream, with safety checks. This stream can only be consumed 

318 once. 

319 

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

321 attribute will contain the full bytes only if they do not represent form data. 

322 The :attr:`form` attribute will contain the parsed form data in that case. 

323 

324 Unlike :attr:`input_stream`, this stream guards against infinite streams or 

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

326 

327 If ``max_content_length`` is set, it can be enforced on streams if 

328 ``wsgi.input_terminated`` is set. Otherwise, an empty stream is returned. 

329 

330 If the limit is reached before the underlying stream is exhausted (such as a 

331 file that is too large, or an infinite stream), the remaining contents of the 

332 stream cannot be read safely. Depending on how the server handles this, clients 

333 may show a "connection reset" failure instead of seeing the 413 response. 

334 

335 .. versionchanged:: 2.3 

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

337 

338 .. versionchanged:: 0.9 

339 The stream is always set (but may be consumed) even if form parsing was 

340 accessed first. 

341 """ 

342 if self.shallow: 

343 raise RuntimeError( 

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

345 " from the input stream is disabled." 

346 ) 

347 

348 return get_input_stream( 

349 self.environ, max_content_length=self.max_content_length 

350 ) 

351 

352 input_stream = environ_property[t.IO[bytes]]( 

353 "wsgi.input", 

354 doc="""The raw WSGI input stream, without any safety checks. 

355 

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

357 past :attr:`content_length` or :attr:`max_content_length`. 

358 

359 Use :attr:`stream` instead. 

360 """, 

361 ) 

362 

363 @cached_property 

364 def data(self) -> bytes: 

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

366 represents form data. 

367 

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

369 """ 

370 return self.get_data(parse_form_data=True) 

371 

372 @t.overload 

373 def get_data( 

374 self, 

375 cache: bool = True, 

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

377 parse_form_data: bool = False, 

378 ) -> bytes: ... 

379 

380 @t.overload 

381 def get_data( 

382 self, 

383 cache: bool = True, 

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

385 parse_form_data: bool = False, 

386 ) -> str: ... 

387 

388 def get_data( 

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

390 ) -> bytes | str: 

391 """This reads the buffered incoming data from the client into one 

392 bytes object. By default this is cached but that behavior can be 

393 changed by setting `cache` to `False`. 

394 

395 Usually it's a bad idea to call this method without checking the 

396 content length first as a client could send dozens of megabytes or more 

397 to cause memory problems on the server. 

398 

399 Note that if the form data was already parsed this method will not 

400 return anything as form data parsing does not cache the data like 

401 this method does. To implicitly invoke form data parsing function 

402 set `parse_form_data` to `True`. When this is done the return value 

403 of this method will be an empty string if the form parser handles 

404 the data. This generally is not necessary as if the whole data is 

405 cached (which is the default) the form parser will used the cached 

406 data to parse the form data. Please be generally aware of checking 

407 the content length first in any case before calling this method 

408 to avoid exhausting server memory. 

409 

410 If `as_text` is set to `True` the return value will be a decoded 

411 string. 

412 

413 .. versionadded:: 0.9 

414 """ 

415 rv = getattr(self, "_cached_data", None) 

416 if rv is None: 

417 if parse_form_data: 

418 self._load_form_data() 

419 rv = self.stream.read() 

420 if cache: 

421 self._cached_data = rv 

422 if as_text: 

423 rv = rv.decode(errors="replace") 

424 return rv 

425 

426 @cached_property 

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

428 """The form parameters. By default an 

429 :class:`~werkzeug.datastructures.ImmutableMultiDict` 

430 is returned from this function. This can be changed by setting 

431 :attr:`parameter_storage_class` to a different type. This might 

432 be necessary if the order of the form data is important. 

433 

434 Please keep in mind that file uploads will not end up here, but instead 

435 in the :attr:`files` attribute. 

436 

437 .. versionchanged:: 0.9 

438 

439 Previous to Werkzeug 0.9 this would only contain form data for POST 

440 and PUT requests. 

441 """ 

442 self._load_form_data() 

443 return self.form 

444 

445 @cached_property 

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

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

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

449 

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

451 

452 .. versionchanged:: 2.0 

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

454 """ 

455 sources = [self.args] 

456 

457 if self.method != "GET": 

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

459 # might not treat that differently than a normal GET 

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

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

462 sources.append(self.form) 

463 

464 args = [] 

465 

466 for d in sources: 

467 if not isinstance(d, MultiDict): 

468 d = MultiDict(d) 

469 

470 args.append(d) 

471 

472 return CombinedMultiDict(args) 

473 

474 @cached_property 

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

476 """:class:`~werkzeug.datastructures.MultiDict` object containing 

477 all uploaded files. Each key in :attr:`files` is the name from the 

478 ``<input type="file" name="">``. Each value in :attr:`files` is a 

479 Werkzeug :class:`~werkzeug.datastructures.FileStorage` object. 

480 

481 It basically behaves like a standard file object you know from Python, 

482 with the difference that it also has a 

483 :meth:`~werkzeug.datastructures.FileStorage.save` function that can 

484 store the file on the filesystem. 

485 

486 Note that :attr:`files` will only contain data if the request method was 

487 POST, PUT or PATCH and the ``<form>`` that posted to the request had 

488 ``enctype="multipart/form-data"``. It will be empty otherwise. 

489 

490 See the :class:`~werkzeug.datastructures.MultiDict` / 

491 :class:`~werkzeug.datastructures.FileStorage` documentation for 

492 more details about the used data structure. 

493 """ 

494 self._load_form_data() 

495 return self.files 

496 

497 @property 

498 def script_root(self) -> str: 

499 """Alias for :attr:`self.root_path`. ``environ["SCRIPT_ROOT"]`` 

500 without a trailing slash. 

501 """ 

502 return self.root_path 

503 

504 @cached_property 

505 def url_root(self) -> str: 

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

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

508 """ 

509 return self.root_url 

510 

511 remote_user = environ_property[str]( 

512 "REMOTE_USER", 

513 doc="""If the server supports user authentication, and the 

514 script is protected, this attribute contains the username the 

515 user has authenticated as.""", 

516 ) 

517 is_multithread = environ_property[bool]( 

518 "wsgi.multithread", 

519 doc="""boolean that is `True` if the application is served by a 

520 multithreaded WSGI server.""", 

521 ) 

522 is_multiprocess = environ_property[bool]( 

523 "wsgi.multiprocess", 

524 doc="""boolean that is `True` if the application is served by a 

525 WSGI server that spawns multiple processes.""", 

526 ) 

527 is_run_once = environ_property[bool]( 

528 "wsgi.run_once", 

529 doc="""boolean that is `True` if the application will be 

530 executed only once in a process lifetime. This is the case for 

531 CGI for example, but it's not guaranteed that the execution only 

532 happens one time.""", 

533 ) 

534 

535 # JSON 

536 

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

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

539 json_module = json 

540 

541 @property 

542 def json(self) -> t.Any | None: 

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

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

545 

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

547 

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

549 will raise a 415 Unsupported Media Type error. 

550 

551 .. versionchanged:: 2.3 

552 Raise a 415 error instead of 400. 

553 

554 .. versionchanged:: 2.1 

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

556 """ 

557 return self.get_json() 

558 

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

560 # with sentinel values. 

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

562 

563 @t.overload 

564 def get_json( 

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

566 ) -> t.Any: ... 

567 

568 @t.overload 

569 def get_json( 

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

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

572 

573 def get_json( 

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

575 ) -> t.Any | None: 

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

577 

578 If the mimetype does not indicate JSON 

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

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

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

582 raises a 415 Unsupported Media Type resp. 

583 

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

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

586 return ``None`` instead. 

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

588 calls. 

589 

590 .. versionchanged:: 2.3 

591 Raise a 415 error instead of 400. 

592 

593 .. versionchanged:: 2.1 

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

595 """ 

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

597 return self._cached_json[silent] 

598 

599 if not (force or self.is_json): 

600 if not silent: 

601 return self.on_json_loading_failed(None) 

602 else: 

603 return None 

604 

605 data = self.get_data(cache=cache) 

606 

607 try: 

608 rv = self.json_module.loads(data) 

609 except ValueError as e: 

610 if silent: 

611 rv = None 

612 

613 if cache: 

614 normal_rv, _ = self._cached_json 

615 self._cached_json = (normal_rv, rv) 

616 else: 

617 rv = self.on_json_loading_failed(e) 

618 

619 if cache: 

620 _, silent_rv = self._cached_json 

621 self._cached_json = (rv, silent_rv) 

622 else: 

623 if cache: 

624 self._cached_json = (rv, rv) 

625 

626 return rv 

627 

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

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

630 

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

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

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

634 

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

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

637 

638 .. versionchanged:: 2.3 

639 Raise a 415 error instead of 400. 

640 """ 

641 if e is not None: 

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

643 

644 raise UnsupportedMediaType( 

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

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

647 )