Skip to content

Commit f1bda61

Browse files
committed
Add support for loading data by POST in HTTP
It's supported by Groonga 4.0.3 or later.
1 parent 2e17efa commit f1bda61

2 files changed

Lines changed: 63 additions & 1 deletion

File tree

poyonga/client.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,15 @@
22
import struct
33
from ctypes.util import find_library
44
from ctypes import Structure, pointer, c_long, CDLL
5-
from urllib.request import urlopen
5+
from urllib.request import Request, urlopen
66
from urllib.error import HTTPError
77
from urllib.parse import urlencode
88

9+
try:
10+
import orjson as json
11+
except ImportError:
12+
import json
13+
914
from poyonga.result import GroongaResult, GroongaSelectResult
1015
from poyonga.const import GQTP_HEADER_SIZE
1116

@@ -99,8 +104,18 @@ def _call_gqtp(self, cmd, **kwargs):
99104
def _call_http(self, cmd, **kwargs):
100105
domain = [self.protocol, "://", self.host, ":", str(self.port), self.prefix_path]
101106
url = "".join(domain) + cmd
107+
post_data = None
102108
if kwargs:
109+
if cmd == "load" and "values" in kwargs:
110+
post_data = kwargs.pop("values")
103111
url = "".join([url, "?", urlencode(kwargs)])
112+
if post_data:
113+
content_type = "application/json"
114+
if isinstance(post_data, list):
115+
post_data = json.dumps(post_data, indent=True)
116+
if isinstance(post_data, str):
117+
post_data = post_data.encode()
118+
url = Request(url, post_data, {"content-type": content_type})
104119
try:
105120
_data = urlopen(url).read()
106121
except HTTPError as msg:

test/test_poyonga.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import io
12
import json
23
import struct
34
import unittest
@@ -24,6 +25,52 @@ def test_json_result_with_http(self, mock_urlopen):
2425
self.assertEqual(type(ret), GroongaResult)
2526
self.assertEqual(ret.status, 0)
2627

28+
@patch("poyonga.client.urlopen")
29+
def test_load_list(self, mock_urlopen):
30+
m = Mock()
31+
m.read.side_effect = ["[[0, 1337566253.89858, 0.000354], 1]"]
32+
mock_urlopen.return_value = m
33+
ret = self.g.call("load",
34+
table="Site",
35+
values=[{"_key": "groonga.org"}])
36+
self.assertEqual(ret.body, 1)
37+
request = mock_urlopen.call_args[0][0]
38+
self.assertEqual([{"_key": "groonga.org"}],
39+
json.loads(request.data))
40+
self.assertEqual({"Content-type": "application/json"},
41+
request.headers)
42+
43+
@patch("poyonga.client.urlopen")
44+
def test_load_json(self, mock_urlopen):
45+
m = Mock()
46+
m.read.side_effect = ["[[0, 1337566253.89858, 0.000354], 1]"]
47+
mock_urlopen.return_value = m
48+
ret = self.g.call("load",
49+
table="Site",
50+
values=json.dumps([{"_key": "groonga.org"}]))
51+
self.assertEqual(ret.body, 1)
52+
request = mock_urlopen.call_args[0][0]
53+
self.assertEqual([{"_key": "groonga.org"}],
54+
json.loads(request.data))
55+
self.assertEqual({"Content-type": "application/json"},
56+
request.headers)
57+
58+
@patch("poyonga.client.urlopen")
59+
def test_load_io(self, mock_urlopen):
60+
m = Mock()
61+
m.read.side_effect = ["[[0, 1337566253.89858, 0.000354], 1]"]
62+
mock_urlopen.return_value = m
63+
json_values = json.dumps([{"_key": "groonga.org"}])
64+
ret = self.g.call("load",
65+
table="Site",
66+
values=io.BytesIO(json_values.encode()))
67+
self.assertEqual(ret.body, 1)
68+
request = mock_urlopen.call_args[0][0]
69+
self.assertEqual([{"_key": "groonga.org"}],
70+
json.loads(request.data.read()))
71+
self.assertEqual({"Content-type": "application/json"},
72+
request.headers)
73+
2774

2875
class PoyongaGQTPTestCase(unittest.TestCase):
2976
def setUp(self):

0 commit comments

Comments
 (0)