mimicker 2.0.2__tar.gz → 2.0.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {mimicker-2.0.2 → mimicker-2.0.3}/PKG-INFO +30 -1
- {mimicker-2.0.2 → mimicker-2.0.3}/README.md +29 -0
- {mimicker-2.0.2 → mimicker-2.0.3}/mimicker/handler.py +15 -3
- {mimicker-2.0.2 → mimicker-2.0.3}/mimicker/route.py +3 -3
- {mimicker-2.0.2 → mimicker-2.0.3}/pyproject.toml +1 -1
- {mimicker-2.0.2 → mimicker-2.0.3}/LICENSE +0 -0
- {mimicker-2.0.2 → mimicker-2.0.3}/mimicker/__init__.py +0 -0
- {mimicker-2.0.2 → mimicker-2.0.3}/mimicker/mimicker.py +0 -0
- {mimicker-2.0.2 → mimicker-2.0.3}/mimicker/server.py +0 -0
- {mimicker-2.0.2 → mimicker-2.0.3}/mimicker/stub_group.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: mimicker
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.3
|
|
4
4
|
Summary: A lightweight HTTP mocking server for Python
|
|
5
5
|
License: MIT
|
|
6
6
|
Keywords: http,mocking,testing,mock-server,stubbing,ci-cd,http-server,testing-tools,stub-server,purepython
|
|
@@ -242,6 +242,33 @@ mimicker(8080).routes(
|
|
|
242
242
|
|
|
243
243
|
```
|
|
244
244
|
|
|
245
|
+
### Dynamic Responses with `response_func`
|
|
246
|
+
|
|
247
|
+
Mimicker allows dynamic responses based on the request data using `response_func`.
|
|
248
|
+
This feature enables you to build mock responses that adapt based on request parameters, headers, and body.
|
|
249
|
+
|
|
250
|
+
```python
|
|
251
|
+
from mimicker.mimicker import mimicker, post
|
|
252
|
+
|
|
253
|
+
# Available for use with response_func:
|
|
254
|
+
# kwargs.get("payload")
|
|
255
|
+
# kwargs.get("headers")
|
|
256
|
+
# kwargs.get("params")
|
|
257
|
+
|
|
258
|
+
def custom_response(**kwargs):
|
|
259
|
+
request_payload = kwargs.get("payload")
|
|
260
|
+
return 200, {"message": f"Hello {request_payload.get('name', 'Guest')}"}
|
|
261
|
+
|
|
262
|
+
mimicker(8080).routes(
|
|
263
|
+
post("/greet")
|
|
264
|
+
.response_func(custom_response)
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
# POST /greet with body {"name": "World"} -> {"message": "Hello World"}
|
|
268
|
+
# POST /greet with empty body -> {"message": "Hello Guest"}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
|
|
245
272
|
## Available Features:
|
|
246
273
|
|
|
247
274
|
* `get(path)`: Defines a `GET` endpoint.
|
|
@@ -253,6 +280,8 @@ mimicker(8080).routes(
|
|
|
253
280
|
* `.body(content)`: Defines the response `body`.
|
|
254
281
|
* `.status(code)`: Defines the response `status code`.
|
|
255
282
|
* `.headers(headers)`: Defines response `headers`.
|
|
283
|
+
* `.response_func(func)`: Defines a dynamic response function based on the request data.
|
|
284
|
+
|
|
256
285
|
|
|
257
286
|
## Requirements
|
|
258
287
|
Mimicker supports Python 3.7 and above.
|
|
@@ -220,6 +220,33 @@ mimicker(8080).routes(
|
|
|
220
220
|
|
|
221
221
|
```
|
|
222
222
|
|
|
223
|
+
### Dynamic Responses with `response_func`
|
|
224
|
+
|
|
225
|
+
Mimicker allows dynamic responses based on the request data using `response_func`.
|
|
226
|
+
This feature enables you to build mock responses that adapt based on request parameters, headers, and body.
|
|
227
|
+
|
|
228
|
+
```python
|
|
229
|
+
from mimicker.mimicker import mimicker, post
|
|
230
|
+
|
|
231
|
+
# Available for use with response_func:
|
|
232
|
+
# kwargs.get("payload")
|
|
233
|
+
# kwargs.get("headers")
|
|
234
|
+
# kwargs.get("params")
|
|
235
|
+
|
|
236
|
+
def custom_response(**kwargs):
|
|
237
|
+
request_payload = kwargs.get("payload")
|
|
238
|
+
return 200, {"message": f"Hello {request_payload.get('name', 'Guest')}"}
|
|
239
|
+
|
|
240
|
+
mimicker(8080).routes(
|
|
241
|
+
post("/greet")
|
|
242
|
+
.response_func(custom_response)
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
# POST /greet with body {"name": "World"} -> {"message": "Hello World"}
|
|
246
|
+
# POST /greet with empty body -> {"message": "Hello Guest"}
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
|
|
223
250
|
## Available Features:
|
|
224
251
|
|
|
225
252
|
* `get(path)`: Defines a `GET` endpoint.
|
|
@@ -231,6 +258,8 @@ mimicker(8080).routes(
|
|
|
231
258
|
* `.body(content)`: Defines the response `body`.
|
|
232
259
|
* `.status(code)`: Defines the response `status code`.
|
|
233
260
|
* `.headers(headers)`: Defines response `headers`.
|
|
261
|
+
* `.response_func(func)`: Defines a dynamic response function based on the request data.
|
|
262
|
+
|
|
234
263
|
|
|
235
264
|
## Requirements
|
|
236
265
|
Mimicker supports Python 3.7 and above.
|
|
@@ -28,21 +28,22 @@ class MimickerHandler(http.server.SimpleHTTPRequestHandler):
|
|
|
28
28
|
|
|
29
29
|
def _handle_request(self, method: str):
|
|
30
30
|
request_headers = {key.lower(): value for key, value in self.headers.items()}
|
|
31
|
+
request_body = self._get_request_body()
|
|
31
32
|
matched_stub, path_params = self.stub_matcher.match(
|
|
32
33
|
method, self.path, request_headers=request_headers
|
|
33
34
|
)
|
|
34
35
|
|
|
35
36
|
if matched_stub:
|
|
36
|
-
self._send_response(matched_stub, path_params)
|
|
37
|
+
self._send_response(matched_stub, path_params, request_body, request_headers)
|
|
37
38
|
else:
|
|
38
39
|
self._send_404_response(method)
|
|
39
40
|
|
|
40
|
-
def _send_response(self, matched_stub: Stub, path_params: Dict[str, str]):
|
|
41
|
+
def _send_response(self, matched_stub: Stub, path_params: Dict[str, str], request_body: Any, request_headers: Dict[str, str]):
|
|
41
42
|
status_code, delay, response, response_func, headers = matched_stub
|
|
42
43
|
if delay > 0:
|
|
43
44
|
sleep(delay)
|
|
44
45
|
if response_func:
|
|
45
|
-
status_code, response = response_func()
|
|
46
|
+
status_code, response = response_func(payload=request_body, headers=request_headers, params=path_params)
|
|
46
47
|
|
|
47
48
|
self.send_response(status_code)
|
|
48
49
|
self._set_headers(headers)
|
|
@@ -77,3 +78,14 @@ class MimickerHandler(http.server.SimpleHTTPRequestHandler):
|
|
|
77
78
|
def _format_response(response: dict, path_params: dict):
|
|
78
79
|
return {k: (v.format(**path_params) if isinstance(v, str) else v)
|
|
79
80
|
for k, v in response.items()}
|
|
81
|
+
|
|
82
|
+
def _get_request_body(self) -> Optional[dict]:
|
|
83
|
+
content_length = self.headers.get('content-length')
|
|
84
|
+
if content_length:
|
|
85
|
+
try:
|
|
86
|
+
length = int(content_length)
|
|
87
|
+
body = self.rfile.read(length).decode('utf-8')
|
|
88
|
+
return json.loads(body) if body else None
|
|
89
|
+
except (ValueError, json.JSONDecodeError):
|
|
90
|
+
return None
|
|
91
|
+
return None
|
|
@@ -21,7 +21,7 @@ class Route:
|
|
|
21
21
|
self._delay = 0.
|
|
22
22
|
self._status = 200
|
|
23
23
|
self._headers: List[Tuple[str, str]] = []
|
|
24
|
-
self._response_func: Optional[Callable[
|
|
24
|
+
self._response_func: Optional[Callable[..., Tuple[int, Any]]] = None
|
|
25
25
|
|
|
26
26
|
escaped_path = re.escape(path)
|
|
27
27
|
parameterized_path = re.sub(r'\\{(\w+)\\}',
|
|
@@ -81,12 +81,12 @@ class Route:
|
|
|
81
81
|
self._headers = headers
|
|
82
82
|
return self
|
|
83
83
|
|
|
84
|
-
def response_func(self, func: Callable[
|
|
84
|
+
def response_func(self, func: Callable[..., Tuple[int, Any]]):
|
|
85
85
|
"""
|
|
86
86
|
Sets a custom response function for dynamic responses.
|
|
87
87
|
|
|
88
88
|
Args:
|
|
89
|
-
func (Callable[
|
|
89
|
+
func (Callable[..., Tuple[int, Any]]): A function that returns (status_code, response_body).
|
|
90
90
|
|
|
91
91
|
Returns:
|
|
92
92
|
Route: The current Route instance (for method chaining).
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|