Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Keywords for TRACE and CONNECT HTTP methods #390

Merged
merged 15 commits into from
May 28, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions atests/http_server/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def view_headers():
return jsonify(get_dict('headers'))


@app.route("/anything", methods=["GET", "POST", "PUT", "DELETE", "PATCH", "TRACE"])
@app.route("/anything", methods=["GET", "POST", "PUT", "DELETE", "PATCH", "TRACE", "HEAD", "CONNECT"])
def view_anything(anything=None):
"""Returns anything passed in request data.
---
Expand Down Expand Up @@ -68,7 +68,7 @@ def view_anything(anything=None):


@app.route(
"/status/<codes>", methods=["GET", "POST", "PUT", "DELETE", "PATCH", "TRACE"]
"/status/<codes>", methods=["GET", "POST", "PUT", "DELETE", "PATCH", "TRACE", "HEAD", "CONNECT"]
)
def view_status_code(codes):
"""Return status code or random status code if more than one are given
Expand Down Expand Up @@ -118,7 +118,7 @@ def view_status_code(codes):
return status_code(code)


@app.route("/redirect-to", methods=["GET", "POST", "PUT", "DELETE", "PATCH", "TRACE"])
@app.route("/redirect-to", methods=["GET", "POST", "PUT", "DELETE", "PATCH", "TRACE", "HEAD", "CONNECT", "OPTIONS"])
def redirect_to():
"""302/3XX Redirects to the given URL.
---
Expand Down
28 changes: 26 additions & 2 deletions atests/test_redirect.robot
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,15 @@ Get Request Without Redirection
Options Request Without Redirection By Default
[Tags] options
${resp}= OPTIONS On Session ${GLOBAL_SESSION} url=/redirect-to?url=anything
Status Should Be OK ${resp}
Status Should Be 302 ${resp}
Length Should Be ${resp.history} 0

# TODO understand whether this is the right behavior or not
Options Request With Redirection
[Tags] options
${resp}= OPTIONS On Session ${GLOBAL_SESSION} url=/redirect-to?url=anything allow_redirects=${true}
Status Should Be OK ${resp}
Length Should Be ${resp.history} 0
Length Should Be ${resp.history} 1

Head Request With Redirection
[Tags] head
Expand Down Expand Up @@ -94,3 +94,27 @@ Put Request Without Redirection
[Tags] put
${resp}= PUT On Session ${GLOBAL_SESSION} url=/redirect-to?url=anything allow_redirects=${false}
Status Should be 302 ${resp}

CONNECT Request Without Redirection
[Tags] connect
${resp}= CONNECT On Session ${GLOBAL_SESSION} url=/redirect-to?url=anything allow_redirects=${false}
Status Should be 302 ${resp}
Length Should Be ${resp.history} 0

CONNECT Request With Redirection
[Tags] connect
${resp}= CONNECT On Session ${GLOBAL_SESSION} url=/redirect-to?url=anything allow_redirects=${true}
Status Should be OK ${resp}
Length Should Be ${resp.history} 1

TRACE Request Without Redirection
[Tags] trace
${resp}= TRACE On Session ${GLOBAL_SESSION} url=/redirect-to?url=anything allow_redirects=${false}
Status Should be 302 ${resp}
Length Should Be ${resp.history} 0

TRACE Request With Redirection
[Tags] trace
${resp}= TRACE On Session ${GLOBAL_SESSION} url=/redirect-to?url=anything allow_redirects=${true}
Status Should be OK ${resp}
Length Should Be ${resp.history} 1
12 changes: 11 additions & 1 deletion atests/test_requests.robot
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ Options Request On Existing Session

Options Request Check Allow Header
[Tags] options
${allow_header}= Create List POST HEAD PATCH GET TRACE DELETE OPTIONS PUT
${allow_header}= Create List GET POST PUT DELETE PATCH TRACE HEAD CONNECT OPTIONS
${resp}= OPTIONS ${HTTP_LOCAL_SERVER}/anything
Status Should Be OK ${resp}
${allow_response_header}= Get From Dictionary ${resp.headers} Allow
Expand All @@ -275,3 +275,13 @@ Options Request Expect A Success On Unauthorized Request
[Tags] options
${resp}= OPTIONS ${HTTP_LOCAL_SERVER}/status/401 expected_status=200
Status Should Be OK ${resp}

Connect Request
[Tags] connect
${resp}= CONNECT ${HTTP_LOCAL_SERVER}/anything
Status Should Be OK ${resp}

Trace Request
[Tags] trace
${resp}= TRACE ${HTTP_LOCAL_SERVER}/anything
Status Should Be OK ${resp}
12 changes: 11 additions & 1 deletion atests/test_requests_on_session.robot
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ Options Request On Existing Session

Options Request Check Allow Header
[Tags] options
${allow_header}= Create List POST HEAD PATCH GET TRACE DELETE OPTIONS PUT
${allow_header}= Create List POST HEAD PATCH GET TRACE DELETE OPTIONS PUT CONNECT
${resp}= OPTIONS On Session ${GLOBAL_SESSION} /anything
Status Should Be OK ${resp}
${allow_response_header}= Get From Dictionary ${resp.headers} Allow
Expand All @@ -273,3 +273,13 @@ Options Request Expect A Success On Unauthorized Request
[Tags] options
${resp}= OPTIONS On Session ${GLOBAL_SESSION} /status/401 expected_status=200
Status Should Be OK ${resp}

Connect Request On Existing Session
[Tags] connect
${resp}= CONNECT On Session ${GLOBAL_SESSION} /anything
Status Should Be OK ${resp}

Trace Request On Existing Session
[Tags] trace
${resp}= TRACE On Session ${GLOBAL_SESSION} /anything
Status Should Be OK ${resp}
104 changes: 66 additions & 38 deletions doc/RequestsLibrary.html

Large diffs are not rendered by default.

71 changes: 58 additions & 13 deletions src/RequestsLibrary/RequestsKeywords.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,14 @@ def _common_request(
**kwargs):

if session:
method_function = getattr(session, method)
request_function = getattr(session, "request")
else:
method_function = getattr(requests, method)
request_function = getattr(requests, "request")

self._capture_output()

resp = method_function(
resp = request_function(
method,
self._merge_url(session, uri),
timeout=self._get_timeout(kwargs.pop('timeout', None)),
cookies=kwargs.pop('cookies', self.cookies),
Expand Down Expand Up @@ -177,7 +178,7 @@ def session_less_get(self, url, params=None,
| ``files`` | Dictionary of file-like-objects (or ``{'name': file-tuple}``) for multipart encoding upload. ``file-tuple`` can be a 2-tuple ``('filename', fileobj)``, 3-tuple ``('filename', fileobj, 'content_type')`` or a 4-tuple ``('filename', fileobj, 'content_type', custom_headers)``, where ``'content-type'`` is a string defining the content type of the given file and ``custom_headers`` a dict-like object containing additional headers to add for the file. |
| ``auth`` | Auth tuple to enable Basic/Digest/Custom HTTP Auth. |
| ``timeout`` | How many seconds to wait for the server to send data before giving up, as a float, or a ``(connect timeout, read timeout)`` tuple. |
| ``allow_redirects`` | Boolean. Enable/disable (values ``${True}`` or ``${False}``) GET/OPTIONS/POST/PUT/PATCH/DELETE/HEAD redirection. Defaults to ``${True}``. |
| ``allow_redirects`` | Boolean. Enable/disable (values ``${True}`` or ``${False}``) GET/POST/PUT/DELETE/PATCH/TRACE/CONNECT redirection. Defaults to ``${True}``. |
| ``proxies`` | Dictionary mapping protocol or protocol and host to the URL of the proxy (e.g. {'http': 'foo.bar:3128', 'http://host.name': 'foo.bar:4012'}) |
| ``verify`` | Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use. Defaults to ``${True}``. Warning: if a session has been created with ``verify=${False}`` any other requests will not verify the SSL certificate. |
| ``stream`` | if ``${False}``, the response content will be immediately downloaded. |
Expand All @@ -187,7 +188,7 @@ def session_less_get(self, url, params=None,
https://requests.readthedocs.io/en/latest/api/

"""
response = self._common_request('get', None, url,
response = self._common_request('GET', None, url,
params=params, **kwargs)
self._check_status(expected_status, response, msg)
return response
Expand All @@ -214,7 +215,7 @@ def session_less_post(self, url, data=None, json=None,
Other optional requests arguments can be passed using ``**kwargs``
see the `GET` keyword for the complete list.
"""
response = self._common_request('post', None, url,
response = self._common_request('POST', None, url,
data=data, json=json, **kwargs)
self._check_status(expected_status, response, msg)
return response
Expand Down Expand Up @@ -242,15 +243,15 @@ def session_less_put(self, url, data=None, json=None,
see the `GET` keyword for the complete list.
"""

response = self._common_request("put", None, url,
response = self._common_request("PUT", None, url,
data=data, json=json, **kwargs)
self._check_status(expected_status, response, msg)
return response

@keyword('HEAD')
@warn_if_equal_symbol_in_url_session_less
def session_less_head(self, url,
expected_status=None, msg=None, **kwargs):
expected_status=None, msg=None, allow_redirects=False, **kwargs):
PaulBrandUWV marked this conversation as resolved.
Show resolved Hide resolved
"""
Sends a HEAD request.

Expand All @@ -268,7 +269,7 @@ def session_less_head(self, url,
Other optional requests arguments can be passed using ``**kwargs``
see the `GET` keyword for the complete list.
"""
response = self._common_request('head', None, url, **kwargs)
response = self._common_request('HEAD', None, url, allow_redirects=allow_redirects, **kwargs)
self._check_status(expected_status, response, msg)
return response

Expand All @@ -294,7 +295,7 @@ def session_less_patch(self, url, data=None, json=None,
Other optional requests arguments can be passed using ``**kwargs``
see the `GET` keyword for the complete list.
"""
response = self._common_request('patch', None, url,
response = self._common_request('PATCH', None, url,
data=data, json=json, **kwargs)
self._check_status(expected_status, response, msg)
return response
Expand All @@ -317,14 +318,14 @@ def session_less_delete(self, url,
Other optional requests arguments can be passed using ``**kwargs``
see the `GET` keyword for the complete list.
"""
response = self._common_request("delete", None, url, **kwargs)
response = self._common_request("DELETE", None, url, **kwargs)
self._check_status(expected_status, response, msg)
return response

@keyword('OPTIONS')
@warn_if_equal_symbol_in_url_session_less
def session_less_options(self, url,
expected_status=None, msg=None, **kwargs):
expected_status=None, msg=None, allow_redirects=False, **kwargs):
PaulBrandUWV marked this conversation as resolved.
Show resolved Hide resolved
"""
Sends a OPTIONS request.
PaulBrandUWV marked this conversation as resolved.
Show resolved Hide resolved

Expand All @@ -339,6 +340,50 @@ def session_less_options(self, url,
Other optional requests arguments can be passed using ``**kwargs``
see the `GET` keyword for the complete list.
"""
response = self._common_request("options", None, url, **kwargs)
response = self._common_request("OPTIONS", None, url, allow_redirects=allow_redirects, **kwargs)
self._check_status(expected_status, response, msg)
return response

@keyword('CONNECT')
@warn_if_equal_symbol_in_url_session_less
def session_less_connect(self, url,
expected_status=None, msg=None, **kwargs):
"""
Sends a CONNECT request.

The endpoint used to retrieve the resource is the ``url``.

By default this keyword fails if a status code with error values is returned in the response,
this behavior can be modified using the ``expected_status`` and ``msg`` parameters,
read more about it in `Status Should Be` keyword documentation.
In order to disable this implicit assert mechanism you can pass as ``expected_status`` the values ``any`` or
``anything``.

Other optional requests arguments can be passed using ``**kwargs``
see the `GET` keyword for the complete list.
"""
response = self._common_request("CONNECT", None, url, **kwargs)
self._check_status(expected_status, response, msg)
return response

@keyword('TRACE')
@warn_if_equal_symbol_in_url_session_less
def session_less_trace(self, url,
expected_status=None, msg=None, **kwargs):
"""
Sends a TRACE request.

The endpoint used to retrieve the resource is the ``url``.

By default this keyword fails if a status code with error values is returned in the response,
this behavior can be modified using the ``expected_status`` and ``msg`` parameters,
read more about it in `Status Should Be` keyword documentation.
In order to disable this implicit assert mechanism you can pass as ``expected_status`` the values ``any`` or
``anything``.

Other optional requests arguments can be passed using ``**kwargs``
see the `GET` keyword for the complete list.
"""
response = self._common_request("TRACE", None, url, **kwargs)
self._check_status(expected_status, response, msg)
return response
66 changes: 57 additions & 9 deletions src/RequestsLibrary/RequestsOnSessionKeywords.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def get_on_session(self, alias, url, params=None,
see the `GET` keyword for the complete list.
"""
session = self._cache.switch(alias)
response = self._common_request("get", session, url,
response = self._common_request("GET", session, url,
params=params, **kwargs)
self._check_status(expected_status, response, msg)
return response
Expand Down Expand Up @@ -57,7 +57,7 @@ def post_on_session(self, alias, url, data=None, json=None,
see the `GET` keyword for the complete list.
"""
session = self._cache.switch(alias)
response = self._common_request("post", session, url,
response = self._common_request("POST", session, url,
data=data, json=json, **kwargs)
self._check_status(expected_status, response, msg)
return response
Expand Down Expand Up @@ -86,7 +86,7 @@ def patch_on_session(self, alias, url, data=None, json=None,
see the `GET` keyword for the complete list.
"""
session = self._cache.switch(alias)
response = self._common_request("patch", session, url,
response = self._common_request("PATCH", session, url,
data=data, json=json, **kwargs)
self._check_status(expected_status, response, msg)
return response
Expand Down Expand Up @@ -115,7 +115,7 @@ def put_on_session(self, alias, url, data=None, json=None,
see the `GET` keyword for the complete list.
"""
session = self._cache.switch(alias)
response = self._common_request("put", session, url,
response = self._common_request("PUT", session, url,
data=data, json=json, **kwargs)
self._check_status(expected_status, response, msg)
return response
Expand All @@ -140,14 +140,14 @@ def delete_on_session(self, alias, url,
see the `GET` keyword for the complete list.
"""
session = self._cache.switch(alias)
response = self._common_request("delete", session, url, **kwargs)
response = self._common_request("DELETE", session, url, **kwargs)
self._check_status(expected_status, response, msg)
return response

@keyword("HEAD On Session")
@warn_if_equal_symbol_in_url_on_session
def head_on_session(self, alias, url,
expected_status=None, msg=None, **kwargs):
expected_status=None, msg=None, allow_redirects=False, **kwargs):
PaulBrandUWV marked this conversation as resolved.
Show resolved Hide resolved
"""
Sends a HEAD request on a previously created HTTP Session.

Expand All @@ -167,14 +167,14 @@ def head_on_session(self, alias, url,
see the `GET` keyword for the complete list.
"""
session = self._cache.switch(alias)
response = self._common_request("head", session, url, **kwargs)
response = self._common_request("HEAD", session, url, allow_redirects=allow_redirects, **kwargs)
self._check_status(expected_status, response, msg)
return response

@keyword("OPTIONS On Session")
@warn_if_equal_symbol_in_url_on_session
def options_on_session(self, alias, url,
expected_status=None, msg=None, **kwargs):
expected_status=None, msg=None, allow_redirects=False, **kwargs):
lucagiove marked this conversation as resolved.
Show resolved Hide resolved
"""
Sends a OPTIONS request on a previously created HTTP Session.

Expand All @@ -191,6 +191,54 @@ def options_on_session(self, alias, url,
see the `GET` keyword for the complete list.
"""
session = self._cache.switch(alias)
response = self._common_request("options", session, url, **kwargs)
response = self._common_request("OPTIONS", session, url, allow_redirects=allow_redirects, **kwargs)
self._check_status(expected_status, response, msg)
return response

@keyword("CONNECT On Session")
@warn_if_equal_symbol_in_url_on_session
def connect_on_session(self, alias, url,
expected_status=None, msg=None, **kwargs):
"""
Sends a CONNECT request on a previously created HTTP Session.

Session will be identified using the ``alias`` name.
The endpoint used to retrieve the resource is the ``url``.

By default this keyword fails if a status code with error values is returned in the response,
this behavior can be modified using the ``expected_status`` and ``msg`` parameters,
read more about it in `Status Should Be` keyword documentation.
In order to disable this implicit assert mechanism you can pass as ``expected_status`` the values ``any`` or
``anything``.

Other optional requests arguments can be passed using ``**kwargs``
see the `GET` keyword for the complete list.
"""
session = self._cache.switch(alias)
response = self._common_request("CONNECT", session, url, **kwargs)
self._check_status(expected_status, response, msg)
return response

@keyword("TRACE On Session")
@warn_if_equal_symbol_in_url_on_session
def trace_on_session(self, alias, url,
expected_status=None, msg=None, **kwargs):
"""
Sends a TRACE request on a previously created HTTP Session.

Session will be identified using the ``alias`` name.
The endpoint used to retrieve the resource is the ``url``.

By default this keyword fails if a status code with error values is returned in the response,
this behavior can be modified using the ``expected_status`` and ``msg`` parameters,
read more about it in `Status Should Be` keyword documentation.
In order to disable this implicit assert mechanism you can pass as ``expected_status`` the values ``any`` or
``anything``.

Other optional requests arguments can be passed using ``**kwargs``
see the `GET` keyword for the complete list.
"""
session = self._cache.switch(alias)
response = self._common_request("TRACE", session, url, **kwargs)
self._check_status(expected_status, response, msg)
return response
Loading
Loading