|
1 | 1 | """OpenAPI core contrib requests requests module"""
|
| 2 | +from typing import Union |
2 | 3 | from werkzeug.datastructures import ImmutableMultiDict
|
| 4 | +from requests import Request, PreparedRequest |
| 5 | +from urllib.parse import urlparse, parse_qs |
3 | 6 |
|
4 | 7 | from openapi_core.validation.request.datatypes import (
|
5 | 8 | RequestParameters, OpenAPIRequest,
|
|
9 | 12 | class RequestsOpenAPIRequestFactory(object):
|
10 | 13 |
|
11 | 14 | @classmethod
|
12 |
| - def create(cls, request): |
| 15 | + def create(cls, request: Union[Request, PreparedRequest]) -> OpenAPIRequest: |
| 16 | + """ |
| 17 | + Converts a requests request to an OpenAPI one |
| 18 | +
|
| 19 | + Internally converts to a `PreparedRequest` first to parse the exact |
| 20 | + payload being sent |
| 21 | + """ |
| 22 | + if isinstance(request, Request): |
| 23 | + request = request.prepare() |
| 24 | + |
| 25 | + # Method |
13 | 26 | method = request.method.lower()
|
14 | 27 |
|
15 |
| - cookie = request.cookies or {} |
| 28 | + # Cookies |
| 29 | + if request._cookies is not None: |
| 30 | + # cookies are stored in a cookiejar object |
| 31 | + cookie = request._cookies.get_dict() |
| 32 | + else: |
| 33 | + cookie = {} |
| 34 | + |
| 35 | + # Preparing a request formats the URL with params, strip them out again |
| 36 | + o = urlparse(request.url) |
| 37 | + params = parse_qs(o.query) |
| 38 | + # extract the URL without query parameters |
| 39 | + url = o._replace(query=None).geturl() |
16 | 40 |
|
17 | 41 | # gets deduced by path finder against spec
|
18 | 42 | path = {}
|
19 | 43 |
|
20 |
| - mimetype = request.headers.get('Accept') or \ |
21 |
| - request.headers.get('Content-Type') |
| 44 | + # Order matters because all python requests issued from a session include |
| 45 | + # Accept */* which does not necessarily match the content type |
| 46 | + mimetype = request.headers.get('Content-Type') or \ |
| 47 | + request.headers.get('Accept') |
| 48 | + |
| 49 | + # Headers - request.headers is not an instance of dict, which is expected |
| 50 | + header = dict(request.headers) |
| 51 | + |
| 52 | + # Body |
| 53 | + # TODO: figure out if request._body_position is relevant |
| 54 | + body = request.body |
| 55 | + |
22 | 56 | parameters = RequestParameters(
|
23 |
| - query=ImmutableMultiDict(request.params), |
24 |
| - header=request.headers, |
| 57 | + query=ImmutableMultiDict(params), |
| 58 | + header=header, |
25 | 59 | cookie=cookie,
|
26 | 60 | path=path,
|
27 | 61 | )
|
28 | 62 | return OpenAPIRequest(
|
29 |
| - full_url_pattern=request.url, |
| 63 | + full_url_pattern=url, |
30 | 64 | method=method,
|
31 | 65 | parameters=parameters,
|
32 |
| - body=request.data, |
| 66 | + body=body, |
33 | 67 | mimetype=mimetype,
|
34 | 68 | )
|
0 commit comments