Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ install-dev-requirements:
pip install -U pip hatch

install-test-requirements:
pip install .[test]
pip install -U .[test]

services-up:
docker-compose up -d
Expand Down
5 changes: 3 additions & 2 deletions mocket/mockhttp.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,13 +160,14 @@ class Entry(MocketEntry):
def __init__(self, uri, method, responses, match_querystring=True):
uri = urlsplit(uri)

if not uri.port:
port = uri.port
if not port:
if uri.scheme == "https":
port = 443
else:
port = 80

super(Entry, self).__init__((uri.hostname, uri.port or port), responses)
super(Entry, self).__init__((uri.hostname, port), responses)
self.schema = uri.scheme
self.path = uri.path
self.query = uri.query
Expand Down
156 changes: 80 additions & 76 deletions mocket/plugins/pook_mock_engine.py
Original file line number Diff line number Diff line change
@@ -1,76 +1,80 @@
import platform

if not platform.python_version().startswith("3.11."):
# it looks like `pook` is not compatible with Python 3.11
from pook.engine import MockEngine
from pook.interceptors.base import BaseInterceptor

from mocket.mocket import Mocket
from mocket.mockhttp import Entry, Response

class MocketPookEntry(Entry):
pook_request = None
pook_engine = None

def can_handle(self, data):
can_handle = super(MocketPookEntry, self).can_handle(data)

if can_handle:
self.pook_engine.match(self.pook_request)
return can_handle

@classmethod
def single_register(
cls, method, uri, body="", status=200, headers=None, match_querystring=True
):
entry = cls(
uri,
method,
Response(body=body, status=status, headers=headers),
match_querystring=match_querystring,
)
Mocket.register(entry)
return entry

class MocketInterceptor(BaseInterceptor):
@staticmethod
def activate():
Mocket.disable()
Mocket.enable()

@staticmethod
def disable():
Mocket.disable()

class MocketEngine(MockEngine):
def __init__(self, engine):
def mocket_mock_fun(*args, **kwargs):
mock = self.pook_mock_fun(*args, **kwargs)

request = mock._request
method = request.method
url = request.rawurl

response = mock._response
body = response._body
status = response._status
headers = response._headers

entry = MocketPookEntry.single_register(
method, url, body, status, headers
)
entry.pook_engine = self.engine
entry.pook_request = request

return mock

# Store plugins engine
self.engine = engine
# Store HTTP client interceptors
self.interceptors = []
# Self-register MocketInterceptor
self.add_interceptor(MocketInterceptor)

# mocking pook.mock()
self.pook_mock_fun = self.engine.mock
self.engine.mock = mocket_mock_fun
from pook.engine import MockEngine
from pook.interceptors.base import BaseInterceptor

from mocket.mocket import Mocket
from mocket.mockhttp import Entry, Response


class MocketPookEntry(Entry):
pook_request = None
pook_engine = None

def can_handle(self, data):
can_handle = super(MocketPookEntry, self).can_handle(data)

if can_handle:
self.pook_engine.match(self.pook_request)
return can_handle

@classmethod
def single_register(
cls,
method,
uri,
body="",
status=200,
headers=None,
match_querystring=True,
exception=None,
):
entry = cls(
uri,
method,
[Response(body=body, status=status, headers=headers)],
match_querystring=match_querystring,
)
Mocket.register(entry)
return entry


class MocketInterceptor(BaseInterceptor):
@staticmethod
def activate():
Mocket.disable()
Mocket.enable()

@staticmethod
def disable():
Mocket.disable()


class MocketEngine(MockEngine):
def __init__(self, engine):
def mocket_mock_fun(*args, **kwargs):
mock = self.pook_mock_fun(*args, **kwargs)

request = mock._request
method = request.method
url = request.rawurl

response = mock._response
body = response._body
status = response._status
headers = response._headers

entry = MocketPookEntry.single_register(method, url, body, status, headers)
entry.pook_engine = self.engine
entry.pook_request = request

return mock

# Store plugins engine
self.engine = engine
# Store HTTP client interceptors
self.interceptors = []
# Self-register MocketInterceptor
self.add_interceptor(MocketInterceptor)

# mocking pook.mock()
self.pook_mock_fun = self.engine.mock
self.engine.mock = mocket_mock_fun
48 changes: 22 additions & 26 deletions tests/main/test_pook.py
Original file line number Diff line number Diff line change
@@ -1,33 +1,29 @@
import platform
import pook
import requests

if not platform.python_version().startswith("3.11."):
# it looks like `pook` is not compatible with Python 3.11
import pook
import requests
from mocket.plugins.pook_mock_engine import MocketEngine

from mocket.plugins.pook_mock_engine import MocketEngine
pook.set_mock_engine(MocketEngine)

pook.set_mock_engine(MocketEngine)

@pook.on
def test_pook_engine():
@pook.on
def test_pook_engine():
url = "http://twitter.com/api/1/foobar"
status = 404
response_json = {"error": "foo"}

url = "http://twitter.com/api/1/foobar"
status = 404
response_json = {"error": "foo"}
mock = pook.get(
url,
headers={"content-type": "application/json"},
reply=status,
response_json=response_json,
)
mock.persist()

mock = pook.get(
url,
headers={"content-type": "application/json"},
reply=status,
response_json=response_json,
)
mock.persist()
requests.get(url)
assert mock.calls == 1

requests.get(url)
assert mock.calls == 1

resp = requests.get(url)
assert resp.status_code == status
assert resp.json() == response_json
assert mock.calls == 2
resp = requests.get(url)
assert resp.status_code == status
assert resp.json() == response_json
assert mock.calls == 2
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
{
"httpbin.local": {
"80": {
"03bc7d1e37b2615ce150043ddae0066d": {
"request": "GET /ip HTTP/1.1\r\nHost: httpbin.local\r\nuser-agent: Fake-User-Agent\r\nAccept-Encoding: gzip, deflate\r\nAccept: */*\r\nConnection: keep-alive\r\n\r\n",
"response": "48 54 54 50 2F 31 2E 31 20 32 30 30 20 4F 4B 0D 0A 58 2D 50 6F 77 65 72 65 64 2D 42 79 3A 20 45 78 70 72 65 73 73 0D 0A 73 65 72 76 65 72 3A 20 67 75 6E 69 63 6F 72 6E 2F 31 39 2E 39 2E 30 0D 0A 64 61 74 65 3A 20 53 61 74 2C 20 31 37 20 44 65 63 20 32 30 32 32 20 31 34 3A 31 31 3A 31 37 20 47 4D 54 0D 0A 63 6F 6E 6E 65 63 74 69 6F 6E 3A 20 6B 65 65 70 2D 61 6C 69 76 65 0D 0A 63 6F 6E 74 65 6E 74 2D 74 79 70 65 3A 20 61 70 70 6C 69 63 61 74 69 6F 6E 2F 6A 73 6F 6E 0D 0A 63 6F 6E 74 65 6E 74 2D 6C 65 6E 67 74 68 3A 20 32 39 0D 0A 61 63 63 65 73 73 2D 63 6F 6E 74 72 6F 6C 2D 61 6C 6C 6F 77 2D 6F 72 69 67 69 6E 3A 20 2A 0D 0A 61 63 63 65 73 73 2D 63 6F 6E 74 72 6F 6C 2D 61 6C 6C 6F 77 2D 63 72 65 64 65 6E 74 69 61 6C 73 3A 20 74 72 75 65 0D 0A 0D 0A 7B 0A 20 20 22 6F 72 69 67 69 6E 22 3A 20 22 31 37 32 2E 32 31 2E 30 2E 33 22 0A 7D 0A"
"0b717b72090e760066708581e9024a2e": {
"request": "GET /gzip HTTP/1.1\r\nHost: httpbin.local\r\nuser-agent: Fake-User-Agent\r\nAccept-Encoding: gzip, deflate, zstd\r\nAccept: */*\r\nConnection: keep-alive\r\n\r\n",
"response": "48 54 54 50 2F 31 2E 31 20 32 30 30 20 4F 4B 0D 0A 58 2D 50 6F 77 65 72 65 64 2D 42 79 3A 20 45 78 70 72 65 73 73 0D 0A 73 65 72 76 65 72 3A 20 67 75 6E 69 63 6F 72 6E 2F 31 39 2E 39 2E 30 0D 0A 64 61 74 65 3A 20 53 75 6E 2C 20 32 34 20 44 65 63 20 32 30 32 33 20 31 39 3A 35 35 3A 35 32 20 47 4D 54 0D 0A 63 6F 6E 6E 65 63 74 69 6F 6E 3A 20 6B 65 65 70 2D 61 6C 69 76 65 0D 0A 63 6F 6E 74 65 6E 74 2D 74 79 70 65 3A 20 61 70 70 6C 69 63 61 74 69 6F 6E 2F 6A 73 6F 6E 0D 0A 63 6F 6E 74 65 6E 74 2D 6C 65 6E 67 74 68 3A 20 31 38 39 0D 0A 63 6F 6E 74 65 6E 74 2D 65 6E 63 6F 64 69 6E 67 3A 20 67 7A 69 70 0D 0A 61 63 63 65 73 73 2D 63 6F 6E 74 72 6F 6C 2D 61 6C 6C 6F 77 2D 6F 72 69 67 69 6E 3A 20 2A 0D 0A 61 63 63 65 73 73 2D 63 6F 6E 74 72 6F 6C 2D 61 6C 6C 6F 77 2D 63 72 65 64 65 6E 74 69 61 6C 73 3A 20 74 72 75 65 0D 0A 0D 0A 1F 8B 08 00 C8 8C 88 65 02 FF 4D 8F 4D 0E C2 20 10 46 F7 3D 05 61 D9 B4 A8 6C 4C DC 35 A6 EA 01 F4 00 08 23 25 45 20 ED E8 A2 4D EF 2E D0 A4 71 F9 BD 79 F3 37 17 84 50 3D 99 10 40 D1 13 C1 E1 03 15 49 AC 03 A1 60 18 23 9B 63 8C A0 91 12 02 C6 4C CB 5D 49 B3 B4 D1 BA 75 D2 2B E3 74 2A A7 69 15 51 F0 B2 02 E3 B0 69 44 B5 E9 67 EF 1C 48 34 DE 25 B3 07 08 B5 B0 E6 0B 9B 70 F3 63 DE D1 21 86 A7 71 CC 7A 29 EC 56 7D 8C 30 D4 8D 06 97 9D 8B E8 A1 FE 43 D1 59 D6 E3 DF 80 9D 4F FF D0 6B 7B 5F BB A9 1F 8C 36 79 ED E1 C8 19 E7 6C CF 38 2D 96 E2 07 90 26 B9 E3 02 01 00 00"
},
"70109c06d1c4e826d2899eb7fe343854": {
"request": "GET /gzip HTTP/1.1\r\nHost: httpbin.local\r\nuser-agent: Fake-User-Agent\r\nAccept-Encoding: gzip, deflate\r\nAccept: */*\r\nConnection: keep-alive\r\n\r\n",
"response": "48 54 54 50 2F 31 2E 31 20 32 30 30 20 4F 4B 0D 0A 58 2D 50 6F 77 65 72 65 64 2D 42 79 3A 20 45 78 70 72 65 73 73 0D 0A 73 65 72 76 65 72 3A 20 67 75 6E 69 63 6F 72 6E 2F 31 39 2E 39 2E 30 0D 0A 64 61 74 65 3A 20 53 61 74 2C 20 31 37 20 44 65 63 20 32 30 32 32 20 31 34 3A 31 31 3A 31 37 20 47 4D 54 0D 0A 63 6F 6E 6E 65 63 74 69 6F 6E 3A 20 6B 65 65 70 2D 61 6C 69 76 65 0D 0A 63 6F 6E 74 65 6E 74 2D 74 79 70 65 3A 20 61 70 70 6C 69 63 61 74 69 6F 6E 2F 6A 73 6F 6E 0D 0A 63 6F 6E 74 65 6E 74 2D 6C 65 6E 67 74 68 3A 20 31 38 36 0D 0A 63 6F 6E 74 65 6E 74 2D 65 6E 63 6F 64 69 6E 67 3A 20 67 7A 69 70 0D 0A 61 63 63 65 73 73 2D 63 6F 6E 74 72 6F 6C 2D 61 6C 6C 6F 77 2D 6F 72 69 67 69 6E 3A 20 2A 0D 0A 61 63 63 65 73 73 2D 63 6F 6E 74 72 6F 6C 2D 61 6C 6C 6F 77 2D 63 72 65 64 65 6E 74 69 61 6C 73 3A 20 74 72 75 65 0D 0A 0D 0A 1F 8B 08 00 05 CE 9D 63 02 FF 4D 8F 41 0E C2 20 10 45 F7 3D 05 61 D9 14 B4 75 61 E2 AE 31 55 0F A0 07 40 18 29 29 02 A1 E8 C2 A6 77 17 68 52 5D CE 9B 37 7F 66 A6 02 21 2C 3F CA 39 10 F8 80 82 7F 41 85 12 EB 81 09 F0 63 64 53 2C 23 68 39 07 17 62 8D CB 4D 89 B3 B4 52 D2 19 6E 85 32 32 B5 53 5A 85 04 3C 34 0B B0 8A 47 6B 0C F0 A0 AC 49 CE 00 E0 08 D3 EA FD 13 2E 76 CC E9 7D 08 EE AE 0C D5 96 33 BD 76 6F 23 78 D2 4A 30 D9 39 B1 01 C8 1F 8A CE BC 9C FD 84 D0 DB F4 09 3E 77 D7 65 1A 5B AF A4 CA 6B EB 7D 43 9B 9A 6E E9 0E 17 73 F1 05 61 37 56 13 FC 00 00 00"
"e2843e7232537a417f14a0cdaf97730e": {
"request": "GET /ip HTTP/1.1\r\nHost: httpbin.local\r\nuser-agent: Fake-User-Agent\r\nAccept-Encoding: gzip, deflate, zstd\r\nAccept: */*\r\nConnection: keep-alive\r\n\r\n",
"response": "48 54 54 50 2F 31 2E 31 20 32 30 30 20 4F 4B 0D 0A 58 2D 50 6F 77 65 72 65 64 2D 42 79 3A 20 45 78 70 72 65 73 73 0D 0A 73 65 72 76 65 72 3A 20 67 75 6E 69 63 6F 72 6E 2F 31 39 2E 39 2E 30 0D 0A 64 61 74 65 3A 20 53 75 6E 2C 20 32 34 20 44 65 63 20 32 30 32 33 20 31 39 3A 35 35 3A 35 32 20 47 4D 54 0D 0A 63 6F 6E 6E 65 63 74 69 6F 6E 3A 20 6B 65 65 70 2D 61 6C 69 76 65 0D 0A 63 6F 6E 74 65 6E 74 2D 74 79 70 65 3A 20 61 70 70 6C 69 63 61 74 69 6F 6E 2F 6A 73 6F 6E 0D 0A 63 6F 6E 74 65 6E 74 2D 6C 65 6E 67 74 68 3A 20 32 39 0D 0A 61 63 63 65 73 73 2D 63 6F 6E 74 72 6F 6C 2D 61 6C 6C 6F 77 2D 6F 72 69 67 69 6E 3A 20 2A 0D 0A 61 63 63 65 73 73 2D 63 6F 6E 74 72 6F 6C 2D 61 6C 6C 6F 77 2D 63 72 65 64 65 6E 74 69 61 6C 73 3A 20 74 72 75 65 0D 0A 0D 0A 7B 0A 20 20 22 6F 72 69 67 69 6E 22 3A 20 22 31 37 32 2E 32 32 2E 30 2E 32 22 0A 7D 0A"
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
{
"httpbin.local": {
"80": {
"03bc7d1e37b2615ce150043ddae0066d": {
"request": "GET /ip HTTP/1.1\r\nHost: httpbin.local\r\nuser-agent: Fake-User-Agent\r\nAccept-Encoding: gzip, deflate\r\nAccept: */*\r\nConnection: keep-alive\r\n\r\n",
"response": "48 54 54 50 2F 31 2E 31 20 32 30 30 20 4F 4B 0D 0A 58 2D 50 6F 77 65 72 65 64 2D 42 79 3A 20 45 78 70 72 65 73 73 0D 0A 73 65 72 76 65 72 3A 20 67 75 6E 69 63 6F 72 6E 2F 31 39 2E 39 2E 30 0D 0A 64 61 74 65 3A 20 53 61 74 2C 20 31 37 20 44 65 63 20 32 30 32 32 20 31 34 3A 31 31 3A 31 37 20 47 4D 54 0D 0A 63 6F 6E 6E 65 63 74 69 6F 6E 3A 20 6B 65 65 70 2D 61 6C 69 76 65 0D 0A 63 6F 6E 74 65 6E 74 2D 74 79 70 65 3A 20 61 70 70 6C 69 63 61 74 69 6F 6E 2F 6A 73 6F 6E 0D 0A 63 6F 6E 74 65 6E 74 2D 6C 65 6E 67 74 68 3A 20 32 39 0D 0A 61 63 63 65 73 73 2D 63 6F 6E 74 72 6F 6C 2D 61 6C 6C 6F 77 2D 6F 72 69 67 69 6E 3A 20 2A 0D 0A 61 63 63 65 73 73 2D 63 6F 6E 74 72 6F 6C 2D 61 6C 6C 6F 77 2D 63 72 65 64 65 6E 74 69 61 6C 73 3A 20 74 72 75 65 0D 0A 0D 0A 7B 0A 20 20 22 6F 72 69 67 69 6E 22 3A 20 22 31 37 32 2E 32 31 2E 30 2E 33 22 0A 7D 0A"
"0b717b72090e760066708581e9024a2e": {
"request": "GET /gzip HTTP/1.1\r\nHost: httpbin.local\r\nuser-agent: Fake-User-Agent\r\nAccept-Encoding: gzip, deflate, zstd\r\nAccept: */*\r\nConnection: keep-alive\r\n\r\n",
"response": "48 54 54 50 2F 31 2E 31 20 32 30 30 20 4F 4B 0D 0A 58 2D 50 6F 77 65 72 65 64 2D 42 79 3A 20 45 78 70 72 65 73 73 0D 0A 73 65 72 76 65 72 3A 20 67 75 6E 69 63 6F 72 6E 2F 31 39 2E 39 2E 30 0D 0A 64 61 74 65 3A 20 53 75 6E 2C 20 32 34 20 44 65 63 20 32 30 32 33 20 31 39 3A 35 39 3A 32 31 20 47 4D 54 0D 0A 63 6F 6E 6E 65 63 74 69 6F 6E 3A 20 6B 65 65 70 2D 61 6C 69 76 65 0D 0A 63 6F 6E 74 65 6E 74 2D 74 79 70 65 3A 20 61 70 70 6C 69 63 61 74 69 6F 6E 2F 6A 73 6F 6E 0D 0A 63 6F 6E 74 65 6E 74 2D 6C 65 6E 67 74 68 3A 20 31 38 39 0D 0A 63 6F 6E 74 65 6E 74 2D 65 6E 63 6F 64 69 6E 67 3A 20 67 7A 69 70 0D 0A 61 63 63 65 73 73 2D 63 6F 6E 74 72 6F 6C 2D 61 6C 6C 6F 77 2D 6F 72 69 67 69 6E 3A 20 2A 0D 0A 61 63 63 65 73 73 2D 63 6F 6E 74 72 6F 6C 2D 61 6C 6C 6F 77 2D 63 72 65 64 65 6E 74 69 61 6C 73 3A 20 74 72 75 65 0D 0A 0D 0A 1F 8B 08 00 99 8D 88 65 02 FF 4D 8F 4D 0E C2 20 10 46 F7 3D 05 61 D9 B4 A8 6C 4C DC 35 A6 EA 01 F4 00 08 23 25 45 20 ED E8 A2 4D EF 2E D0 A4 71 F9 BD 79 F3 37 17 84 50 3D 99 10 40 D1 13 C1 E1 03 15 49 AC 03 A1 60 18 23 9B 63 8C A0 91 12 02 C6 4C CB 5D 49 B3 B4 D1 BA 75 D2 2B E3 74 2A A7 69 15 51 F0 B2 02 E3 B0 69 44 B5 E9 67 EF 1C 48 34 DE 25 B3 07 08 B5 B0 E6 0B 9B 70 F3 63 DE D1 21 86 A7 71 CC 7A 29 EC 56 7D 8C 30 D4 8D 06 97 9D 8B E8 A1 FE 43 D1 59 D6 E3 DF 80 9D 4F FF D0 6B 7B 5F BB A9 1F 8C 36 79 ED E1 C8 19 E7 6C CF 38 2D 96 E2 07 90 26 B9 E3 02 01 00 00"
},
"70109c06d1c4e826d2899eb7fe343854": {
"request": "GET /gzip HTTP/1.1\r\nHost: httpbin.local\r\nuser-agent: Fake-User-Agent\r\nAccept-Encoding: gzip, deflate\r\nAccept: */*\r\nConnection: keep-alive\r\n\r\n",
"response": "48 54 54 50 2F 31 2E 31 20 32 30 30 20 4F 4B 0D 0A 58 2D 50 6F 77 65 72 65 64 2D 42 79 3A 20 45 78 70 72 65 73 73 0D 0A 73 65 72 76 65 72 3A 20 67 75 6E 69 63 6F 72 6E 2F 31 39 2E 39 2E 30 0D 0A 64 61 74 65 3A 20 53 61 74 2C 20 31 37 20 44 65 63 20 32 30 32 32 20 31 34 3A 31 31 3A 31 37 20 47 4D 54 0D 0A 63 6F 6E 6E 65 63 74 69 6F 6E 3A 20 6B 65 65 70 2D 61 6C 69 76 65 0D 0A 63 6F 6E 74 65 6E 74 2D 74 79 70 65 3A 20 61 70 70 6C 69 63 61 74 69 6F 6E 2F 6A 73 6F 6E 0D 0A 63 6F 6E 74 65 6E 74 2D 6C 65 6E 67 74 68 3A 20 31 38 36 0D 0A 63 6F 6E 74 65 6E 74 2D 65 6E 63 6F 64 69 6E 67 3A 20 67 7A 69 70 0D 0A 61 63 63 65 73 73 2D 63 6F 6E 74 72 6F 6C 2D 61 6C 6C 6F 77 2D 6F 72 69 67 69 6E 3A 20 2A 0D 0A 61 63 63 65 73 73 2D 63 6F 6E 74 72 6F 6C 2D 61 6C 6C 6F 77 2D 63 72 65 64 65 6E 74 69 61 6C 73 3A 20 74 72 75 65 0D 0A 0D 0A 1F 8B 08 00 05 CE 9D 63 02 FF 4D 8F 41 0E C2 20 10 45 F7 3D 05 61 D9 14 B4 75 61 E2 AE 31 55 0F A0 07 40 18 29 29 02 A1 E8 C2 A6 77 17 68 52 5D CE 9B 37 7F 66 A6 02 21 2C 3F CA 39 10 F8 80 82 7F 41 85 12 EB 81 09 F0 63 64 53 2C 23 68 39 07 17 62 8D CB 4D 89 B3 B4 52 D2 19 6E 85 32 32 B5 53 5A 85 04 3C 34 0B B0 8A 47 6B 0C F0 A0 AC 49 CE 00 E0 08 D3 EA FD 13 2E 76 CC E9 7D 08 EE AE 0C D5 96 33 BD 76 6F 23 78 D2 4A 30 D9 39 B1 01 C8 1F 8A CE BC 9C FD 84 D0 DB F4 09 3E 77 D7 65 1A 5B AF A4 CA 6B EB 7D 43 9B 9A 6E E9 0E 17 73 F1 05 61 37 56 13 FC 00 00 00"
"e2843e7232537a417f14a0cdaf97730e": {
"request": "GET /ip HTTP/1.1\r\nHost: httpbin.local\r\nuser-agent: Fake-User-Agent\r\nAccept-Encoding: gzip, deflate, zstd\r\nAccept: */*\r\nConnection: keep-alive\r\n\r\n",
"response": "48 54 54 50 2F 31 2E 31 20 32 30 30 20 4F 4B 0D 0A 58 2D 50 6F 77 65 72 65 64 2D 42 79 3A 20 45 78 70 72 65 73 73 0D 0A 73 65 72 76 65 72 3A 20 67 75 6E 69 63 6F 72 6E 2F 31 39 2E 39 2E 30 0D 0A 64 61 74 65 3A 20 53 75 6E 2C 20 32 34 20 44 65 63 20 32 30 32 33 20 31 39 3A 35 39 3A 32 31 20 47 4D 54 0D 0A 63 6F 6E 6E 65 63 74 69 6F 6E 3A 20 6B 65 65 70 2D 61 6C 69 76 65 0D 0A 63 6F 6E 74 65 6E 74 2D 74 79 70 65 3A 20 61 70 70 6C 69 63 61 74 69 6F 6E 2F 6A 73 6F 6E 0D 0A 63 6F 6E 74 65 6E 74 2D 6C 65 6E 67 74 68 3A 20 32 39 0D 0A 61 63 63 65 73 73 2D 63 6F 6E 74 72 6F 6C 2D 61 6C 6C 6F 77 2D 6F 72 69 67 69 6E 3A 20 2A 0D 0A 61 63 63 65 73 73 2D 63 6F 6E 74 72 6F 6C 2D 61 6C 6C 6F 77 2D 63 72 65 64 65 6E 74 69 61 6C 73 3A 20 74 72 75 65 0D 0A 0D 0A 7B 0A 20 20 22 6F 72 69 67 69 6E 22 3A 20 22 31 37 32 2E 32 32 2E 30 2E 32 22 0A 7D 0A"
}
}
}
Expand Down
Loading