Forward post with large content to compute

This commit is contained in:
Julien Duponchelle 2016-06-06 19:51:35 +02:00
parent d108fc6e94
commit 582e3c72ff
No known key found for this signature in database
GPG Key ID: CE8B29639E07F5E8
4 changed files with 29 additions and 21 deletions

View File

@ -268,15 +268,22 @@ class Compute:
def _run_http_query(self, method, path, data=None, timeout=10): def _run_http_query(self, method, path, data=None, timeout=10):
with aiohttp.Timeout(timeout): with aiohttp.Timeout(timeout):
url = self._getUrl(path) url = self._getUrl(path)
headers = {'content-type': 'application/json'} headers = {}
headers['content-type'] = 'application/json'
chunked = False
if data == {}: if data == {}:
data = None data = None
elif data is not None: elif data is not None:
if hasattr(data, '__json__'): if hasattr(data, '__json__'):
data = data.__json__() data = json.dumps(data.__json__())
data = json.dumps(data) # Stream the request
elif isinstance(data, aiohttp.streams.StreamReader):
chunked = True
headers['content-type'] = 'application/octet-stream'
else:
data = json.dumps(data)
response = yield from self._session.request(method, url, headers=headers, data=data, auth=self._auth) response = yield from self._session.request(method, url, headers=headers, data=data, auth=self._auth, chunked=chunked)
body = yield from response.read() body = yield from response.read()
if body: if body:
body = body.decode() body = body.decode()
@ -301,7 +308,7 @@ class Compute:
response.json = json.loads(body) response.json = json.loads(body)
except ValueError: except ValueError:
raise aiohttp.web.HTTPConflict(text="The server {} is not a GNS3 server".format(self._id)) raise aiohttp.web.HTTPConflict(text="The server {} is not a GNS3 server".format(self._id))
if response.json is None: else:
response.json = {} response.json = {}
return response return response

View File

@ -90,11 +90,11 @@ class ComputeHandler:
def get_forward(request, response): def get_forward(request, response):
controller = Controller.instance() controller = Controller.instance()
compute = controller.get_compute(request.match_info["compute_id"]) compute = controller.get_compute(request.match_info["compute_id"])
images = yield from compute.forward("GET", request.match_info["emulator"], request.match_info["action"]) res = yield from compute.forward("GET", request.match_info["emulator"], request.match_info["action"])
response.json(images) response.json(res)
@Route.post( @Route.post(
r"/computes/{compute_id}/{emulator}/{action}", r"/computes/{compute_id}/{emulator}/{action:.+}",
parameters={ parameters={
"compute_id": "Compute UUID" "compute_id": "Compute UUID"
}, },
@ -106,8 +106,8 @@ class ComputeHandler:
def post_forward(request, response): def post_forward(request, response):
controller = Controller.instance() controller = Controller.instance()
compute = controller.get_compute(request.match_info["compute_id"]) compute = controller.get_compute(request.match_info["compute_id"])
images = yield from compute.forward("POST", request.match_info["emulator"], request.match_info["action"], data=dict(request.json)) res = yield from compute.forward("POST", request.match_info["emulator"], request.match_info["action"], data=request.content)
response.json(images) response.json(res)
@Route.get( @Route.get(
r"/computes/{compute_id}", r"/computes/{compute_id}",

View File

@ -71,7 +71,7 @@ def test_compute_httpQuery(compute, async_run):
response.status = 200 response.status = 200
async_run(compute.post("/projects", {"a": "b"})) async_run(compute.post("/projects", {"a": "b"}))
mock.assert_called_with("POST", "https://example.com:84/v2/compute/projects", data='{"a": "b"}', headers={'content-type': 'application/json'}, auth=None) mock.assert_called_with("POST", "https://example.com:84/v2/compute/projects", data='{"a": "b"}', headers={'content-type': 'application/json'}, auth=None, chunked=False)
assert compute._auth is None assert compute._auth is None
@ -83,7 +83,7 @@ def test_compute_httpQueryAuth(compute, async_run):
compute.user = "root" compute.user = "root"
compute.password = "toor" compute.password = "toor"
async_run(compute.post("/projects", {"a": "b"})) async_run(compute.post("/projects", {"a": "b"}))
mock.assert_called_with("POST", "https://example.com:84/v2/compute/projects", data='{"a": "b"}', headers={'content-type': 'application/json'}, auth=compute._auth) mock.assert_called_with("POST", "https://example.com:84/v2/compute/projects", data='{"a": "b"}', headers={'content-type': 'application/json'}, auth=compute._auth, chunked=False)
assert compute._auth.login == "root" assert compute._auth.login == "root"
assert compute._auth.password == "toor" assert compute._auth.password == "toor"
@ -96,8 +96,8 @@ def test_compute_httpQueryNotConnected(compute, controller, async_run):
response.status = 200 response.status = 200
with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock: with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
async_run(compute.post("/projects", {"a": "b"})) async_run(compute.post("/projects", {"a": "b"}))
mock.assert_any_call("GET", "https://example.com:84/v2/compute/version", headers={'content-type': 'application/json'}, data=None, auth=None) mock.assert_any_call("GET", "https://example.com:84/v2/compute/version", headers={'content-type': 'application/json'}, data=None, auth=None, chunked=False)
mock.assert_any_call("POST", "https://example.com:84/v2/compute/projects", data='{"a": "b"}', headers={'content-type': 'application/json'}, auth=None) mock.assert_any_call("POST", "https://example.com:84/v2/compute/projects", data='{"a": "b"}', headers={'content-type': 'application/json'}, auth=None, chunked=False)
assert compute._connected assert compute._connected
assert compute.version == __version__ assert compute.version == __version__
controller.notification.emit.assert_called_with("compute.updated", compute.__json__()) controller.notification.emit.assert_called_with("compute.updated", compute.__json__())
@ -111,7 +111,7 @@ def test_compute_httpQueryNotConnectedInvalidVersion(compute, async_run):
with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock: with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
with pytest.raises(aiohttp.web.HTTPConflict): with pytest.raises(aiohttp.web.HTTPConflict):
async_run(compute.post("/projects", {"a": "b"})) async_run(compute.post("/projects", {"a": "b"}))
mock.assert_any_call("GET", "https://example.com:84/v2/compute/version", headers={'content-type': 'application/json'}, data=None, auth=None) mock.assert_any_call("GET", "https://example.com:84/v2/compute/version", headers={'content-type': 'application/json'}, data=None, auth=None, chunked=False)
def test_compute_httpQueryNotConnectedNonGNS3Server(compute, async_run): def test_compute_httpQueryNotConnectedNonGNS3Server(compute, async_run):
@ -122,7 +122,7 @@ def test_compute_httpQueryNotConnectedNonGNS3Server(compute, async_run):
with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock: with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
with pytest.raises(aiohttp.web.HTTPConflict): with pytest.raises(aiohttp.web.HTTPConflict):
async_run(compute.post("/projects", {"a": "b"})) async_run(compute.post("/projects", {"a": "b"}))
mock.assert_any_call("GET", "https://example.com:84/v2/compute/version", headers={'content-type': 'application/json'}, data=None, auth=None) mock.assert_any_call("GET", "https://example.com:84/v2/compute/version", headers={'content-type': 'application/json'}, data=None, auth=None, chunked=False)
def test_compute_httpQueryNotConnectedNonGNS3Server2(compute, async_run): def test_compute_httpQueryNotConnectedNonGNS3Server2(compute, async_run):
@ -133,7 +133,7 @@ def test_compute_httpQueryNotConnectedNonGNS3Server2(compute, async_run):
with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock: with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
with pytest.raises(aiohttp.web.HTTPConflict): with pytest.raises(aiohttp.web.HTTPConflict):
async_run(compute.post("/projects", {"a": "b"})) async_run(compute.post("/projects", {"a": "b"}))
mock.assert_any_call("GET", "https://example.com:84/v2/compute/version", headers={'content-type': 'application/json'}, data=None, auth=None) mock.assert_any_call("GET", "https://example.com:84/v2/compute/version", headers={'content-type': 'application/json'}, data=None, auth=None, chunked=False)
def test_compute_httpQueryError(compute, async_run): def test_compute_httpQueryError(compute, async_run):
@ -152,7 +152,7 @@ def test_compute_httpQuery_project(compute, async_run):
project = Project() project = Project()
async_run(compute.post("/projects", project)) async_run(compute.post("/projects", project))
mock.assert_called_with("POST", "https://example.com:84/v2/compute/projects", data=json.dumps(project.__json__()), headers={'content-type': 'application/json'}, auth=None) mock.assert_called_with("POST", "https://example.com:84/v2/compute/projects", data=json.dumps(project.__json__()), headers={'content-type': 'application/json'}, auth=None, chunked=False)
def test_connectNotification(compute, async_run): def test_connectNotification(compute, async_run):
@ -228,7 +228,7 @@ def test_forward_get(compute, async_run):
response.status = 200 response.status = 200
with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock: with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
async_run(compute.forward("GET", "qemu", "images")) async_run(compute.forward("GET", "qemu", "images"))
mock.assert_called_with("GET", "https://example.com:84/v2/compute/qemu/images", auth=None, data=None, headers={'content-type': 'application/json'}) mock.assert_called_with("GET", "https://example.com:84/v2/compute/qemu/images", auth=None, data=None, headers={'content-type': 'application/json'}, chunked=False)
def test_forward_post(compute, async_run): def test_forward_post(compute, async_run):
@ -236,4 +236,4 @@ def test_forward_post(compute, async_run):
response.status = 200 response.status = 200
with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock: with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
async_run(compute.forward("POST", "qemu", "img", data={"id": 42})) async_run(compute.forward("POST", "qemu", "img", data={"id": 42}))
mock.assert_called_with("POST", "https://example.com:84/v2/compute/qemu/img", auth=None, data='{"id": 42}', headers={'content-type': 'application/json'}) mock.assert_called_with("POST", "https://example.com:84/v2/compute/qemu/img", auth=None, data='{"id": 42}', headers={'content-type': 'application/json'}, chunked=False)

View File

@ -15,6 +15,7 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import unittest
from tests.utils import asyncio_patch from tests.utils import asyncio_patch
@ -209,4 +210,4 @@ def test_compute_create_img(http_controller, controller):
params = {"path": "/test"} params = {"path": "/test"}
with asyncio_patch("gns3server.controller.compute.Compute.forward", return_value=[]) as mock: with asyncio_patch("gns3server.controller.compute.Compute.forward", return_value=[]) as mock:
response = http_controller.post("/computes/my_compute/qemu/img", params) response = http_controller.post("/computes/my_compute/qemu/img", params)
mock.assert_called_with("POST", "qemu", "img", data={"path": "/test"}) mock.assert_called_with("POST", "qemu", "img", data=unittest.mock.ANY)