1# --------------------------------------------------------------------------
2#
3# Copyright (c) Microsoft Corporation. All rights reserved.
4#
5# The MIT License (MIT)
6#
7# Permission is hereby granted, free of charge, to any person obtaining a copy
8# of this software and associated documentation files (the ""Software""), to
9# deal in the Software without restriction, including without limitation the
10# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
11# sell copies of the Software, and to permit persons to whom the Software is
12# furnished to do so, subject to the following conditions:
13#
14# The above copyright notice and this permission notice shall be included in
15# all copies or substantial portions of the Software.
16#
17# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23# IN THE SOFTWARE.
24#
25# --------------------------------------------------------------------------
26
27import abc
28import copy
29import logging
30
31from typing import (
32 Generic,
33 TypeVar,
34 Union,
35 Any,
36 Optional,
37 Awaitable,
38 Dict,
39)
40
41from azure.core.pipeline import PipelineRequest, PipelineResponse
42
43HTTPResponseType = TypeVar("HTTPResponseType")
44HTTPRequestType = TypeVar("HTTPRequestType")
45
46_LOGGER = logging.getLogger(__name__)
47
48
49class HTTPPolicy(abc.ABC, Generic[HTTPRequestType, HTTPResponseType]):
50 """An HTTP policy ABC.
51
52 Use with a synchronous pipeline.
53 """
54
55 next: "HTTPPolicy[HTTPRequestType, HTTPResponseType]"
56 """Pointer to the next policy or a transport (wrapped as a policy). Will be set at pipeline creation."""
57
58 @abc.abstractmethod
59 def send(self, request: PipelineRequest[HTTPRequestType]) -> PipelineResponse[HTTPRequestType, HTTPResponseType]:
60 """Abstract send method for a synchronous pipeline. Mutates the request.
61
62 Context content is dependent on the HttpTransport.
63
64 :param request: The pipeline request object
65 :type request: ~azure.core.pipeline.PipelineRequest
66 :return: The pipeline response object.
67 :rtype: ~azure.core.pipeline.PipelineResponse
68 """
69
70
71class SansIOHTTPPolicy(Generic[HTTPRequestType, HTTPResponseType]):
72 """Represents a sans I/O policy.
73
74 SansIOHTTPPolicy is a base class for policies that only modify or
75 mutate a request based on the HTTP specification, and do not depend
76 on the specifics of any particular transport. SansIOHTTPPolicy
77 subclasses will function in either a Pipeline or an AsyncPipeline,
78 and can act either before the request is done, or after.
79 You can optionally make these methods coroutines (or return awaitable objects)
80 but they will then be tied to AsyncPipeline usage.
81 """
82
83 def on_request(self, request: PipelineRequest[HTTPRequestType]) -> Union[None, Awaitable[None]]:
84 """Is executed before sending the request from next policy.
85
86 :param request: Request to be modified before sent from next policy.
87 :type request: ~azure.core.pipeline.PipelineRequest
88 """
89
90 def on_response(
91 self,
92 request: PipelineRequest[HTTPRequestType],
93 response: PipelineResponse[HTTPRequestType, HTTPResponseType],
94 ) -> Union[None, Awaitable[None]]:
95 """Is executed after the request comes back from the policy.
96
97 :param request: Request to be modified after returning from the policy.
98 :type request: ~azure.core.pipeline.PipelineRequest
99 :param response: Pipeline response object
100 :type response: ~azure.core.pipeline.PipelineResponse
101 """
102
103 def on_exception(
104 self,
105 request: PipelineRequest[HTTPRequestType], # pylint: disable=unused-argument
106 ) -> None:
107 """Is executed if an exception is raised while executing the next policy.
108
109 This method is executed inside the exception handler.
110
111 :param request: The Pipeline request object
112 :type request: ~azure.core.pipeline.PipelineRequest
113 """
114 return
115
116
117class RequestHistory(Generic[HTTPRequestType, HTTPResponseType]):
118 """A container for an attempted request and the applicable response.
119
120 This is used to document requests/responses that resulted in redirected/retried requests.
121
122 :param http_request: The request.
123 :type http_request: ~azure.core.pipeline.transport.HttpRequest
124 :param http_response: The HTTP response.
125 :type http_response: ~azure.core.pipeline.transport.HttpResponse
126 :param Exception error: An error encountered during the request, or None if the response was received successfully.
127 :param dict context: The pipeline context.
128 """
129
130 def __init__(
131 self,
132 http_request: HTTPRequestType,
133 http_response: Optional[HTTPResponseType] = None,
134 error: Optional[Exception] = None,
135 context: Optional[Dict[str, Any]] = None,
136 ) -> None:
137 self.http_request: HTTPRequestType = copy.deepcopy(http_request)
138 self.http_response: Optional[HTTPResponseType] = http_response
139 self.error: Optional[Exception] = error
140 self.context: Optional[Dict[str, Any]] = context