1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)# Copyright 2013 The Chromium Authors. All rights reserved.
2868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be
3868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)# found in the LICENSE file.
4868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)import httplib
6868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)import json
7868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class _Method(object):
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GET = 'GET'
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  POST = 'POST'
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DELETE = 'DELETE'
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class Command(object):
16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  NEW_SESSION = (_Method.POST, '/session')
17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GET_SESSION_CAPABILITIES = (_Method.GET, '/session/:sessionId')
18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  QUIT = (_Method.DELETE, '/session/:sessionId')
19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GET_CURRENT_WINDOW_HANDLE = (_Method.GET, '/session/:sessionId/window_handle')
20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GET_WINDOW_HANDLES = (_Method.GET, '/session/:sessionId/window_handles')
21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GET = (_Method.POST, '/session/:sessionId/url')
22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GET_ALERT = (_Method.GET, '/session/:sessionId/alert')
23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DISMISS_ALERT = (_Method.POST, '/session/:sessionId/dismiss_alert')
24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ACCEPT_ALERT = (_Method.POST, '/session/:sessionId/accept_alert')
25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GET_ALERT_TEXT = (_Method.GET, '/session/:sessionId/alert_text')
26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SET_ALERT_VALUE = (_Method.POST, '/session/:sessionId/alert_text')
27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GO_FORWARD = (_Method.POST, '/session/:sessionId/forward')
28868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GO_BACK = (_Method.POST, '/session/:sessionId/back')
29868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  REFRESH = (_Method.POST, '/session/:sessionId/refresh')
30868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXECUTE_SCRIPT = (_Method.POST, '/session/:sessionId/execute')
31868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXECUTE_ASYNC_SCRIPT = (_Method.POST, '/session/:sessionId/execute_async')
32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  LAUNCH_APP = (_Method.POST, '/session/:sessionId/chromium/launch_app')
33868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GET_CURRENT_URL = (_Method.GET, '/session/:sessionId/url')
34868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GET_TITLE = (_Method.GET, '/session/:sessionId/title')
35868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GET_PAGE_SOURCE = (_Method.GET, '/session/:sessionId/source')
36868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SCREENSHOT = (_Method.GET, '/session/:sessionId/screenshot')
37868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SET_BROWSER_VISIBLE = (_Method.POST, '/session/:sessionId/visible')
38868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IS_BROWSER_VISIBLE = (_Method.GET, '/session/:sessionId/visible')
39868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  FIND_ELEMENT = (_Method.POST, '/session/:sessionId/element')
40868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  FIND_ELEMENTS = (_Method.POST, '/session/:sessionId/elements')
41868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GET_ACTIVE_ELEMENT = (_Method.POST, '/session/:sessionId/element/active')
42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  FIND_CHILD_ELEMENT = (_Method.POST, '/session/:sessionId/element/:id/element')
43868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  FIND_CHILD_ELEMENTS = (
44868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      _Method.POST, '/session/:sessionId/element/:id/elements')
45868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  CLICK_ELEMENT = (_Method.POST, '/session/:sessionId/element/:id/click')
46868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  CLEAR_ELEMENT = (_Method.POST, '/session/:sessionId/element/:id/clear')
47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SUBMIT_ELEMENT = (_Method.POST, '/session/:sessionId/element/:id/submit')
48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GET_ELEMENT_TEXT = (_Method.GET, '/session/:sessionId/element/:id/text')
49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SEND_KEYS_TO_ELEMENT = (_Method.POST, '/session/:sessionId/element/:id/value')
50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  UPLOAD_FILE = (_Method.POST, '/session/:sessionId/file')
51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GET_ELEMENT_VALUE = (_Method.GET, '/session/:sessionId/element/:id/value')
52868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GET_ELEMENT_TAG_NAME = (_Method.GET, '/session/:sessionId/element/:id/name')
53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IS_ELEMENT_SELECTED = (
54868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      _Method.GET, '/session/:sessionId/element/:id/selected')
55868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IS_ELEMENT_ENABLED = (_Method.GET, '/session/:sessionId/element/:id/enabled')
56868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IS_ELEMENT_DISPLAYED = (
57868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      _Method.GET, '/session/:sessionId/element/:id/displayed')
58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  HOVER_OVER_ELEMENT = (_Method.POST, '/session/:sessionId/element/:id/hover')
59868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GET_ELEMENT_LOCATION = (
60868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      _Method.GET, '/session/:sessionId/element/:id/location')
61868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GET_ELEMENT_LOCATION_ONCE_SCROLLED_INTO_VIEW = (
62868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      _Method.GET, '/session/:sessionId/element/:id/location_in_view')
63868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GET_ELEMENT_SIZE = (_Method.GET, '/session/:sessionId/element/:id/size')
64868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GET_ELEMENT_ATTRIBUTE = (
65868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      _Method.GET, '/session/:sessionId/element/:id/attribute/:name')
66868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ELEMENT_EQUALS = (
67868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      _Method.GET, '/session/:sessionId/element/:id/equals/:other')
68868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GET_COOKIES = (_Method.GET, '/session/:sessionId/cookie')
69868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ADD_COOKIE = (_Method.POST, '/session/:sessionId/cookie')
70868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DELETE_ALL_COOKIES = (_Method.DELETE, '/session/:sessionId/cookie')
71868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DELETE_COOKIE = (_Method.DELETE, '/session/:sessionId/cookie/:name')
72868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SWITCH_TO_FRAME = (_Method.POST, '/session/:sessionId/frame')
73a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  SWITCH_TO_PARENT_FRAME = (_Method.POST, '/session/:sessionId/frame/parent')
74868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SWITCH_TO_WINDOW = (_Method.POST, '/session/:sessionId/window')
75868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GET_WINDOW_SIZE = (
76868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      _Method.GET, '/session/:sessionId/window/:windowHandle/size')
77868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GET_WINDOW_POSITION = (
78868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      _Method.GET, '/session/:sessionId/window/:windowHandle/position')
79868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SET_WINDOW_SIZE = (
80868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      _Method.POST, '/session/:sessionId/window/:windowHandle/size')
81868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SET_WINDOW_POSITION = (
82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      _Method.POST, '/session/:sessionId/window/:windowHandle/position')
83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  MAXIMIZE_WINDOW = (
84868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      _Method.POST, '/session/:sessionId/window/:windowHandle/maximize')
85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  CLOSE = (_Method.DELETE, '/session/:sessionId/window')
86868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DRAG_ELEMENT = (_Method.POST, '/session/:sessionId/element/:id/drag')
87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GET_ELEMENT_VALUE_OF_CSS_PROPERTY = (
88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      _Method.GET, '/session/:sessionId/element/:id/css/:propertyName')
89868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IMPLICITLY_WAIT = (
90868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      _Method.POST, '/session/:sessionId/timeouts/implicit_wait')
91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SET_SCRIPT_TIMEOUT = (
92868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      _Method.POST, '/session/:sessionId/timeouts/async_script')
93868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SET_TIMEOUT = (_Method.POST, '/session/:sessionId/timeouts')
94868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXECUTE_SQL = (_Method.POST, '/session/:sessionId/execute_sql')
95868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GET_LOCATION = (_Method.GET, '/session/:sessionId/location')
96868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SET_LOCATION = (_Method.POST, '/session/:sessionId/location')
97868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GET_STATUS = (_Method.GET, '/session/:sessionId/application_cache/status')
98868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IS_BROWSER_ONLINE = (_Method.GET, '/session/:sessionId/browser_connection')
99868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SET_BROWSER_ONLINE = (_Method.POST, '/session/:sessionId/browser_connection')
100868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GET_LOCAL_STORAGE_ITEM = (
101868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      _Method.GET, '/session/:sessionId/local_storage/key/:key')
102868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  REMOVE_LOCAL_STORAGE_ITEM = (
103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      _Method.DELETE, '/session/:sessionId/local_storage/key/:key')
104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GET_LOCAL_STORAGE_KEYS = (_Method.GET, '/session/:sessionId/local_storage')
105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SET_LOCAL_STORAGE_ITEM = (_Method.POST, '/session/:sessionId/local_storage')
106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  CLEAR_LOCAL_STORAGE = (_Method.DELETE, '/session/:sessionId/local_storage')
107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GET_LOCAL_STORAGE_SIZE = (
108868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      _Method.GET, '/session/:sessionId/local_storage/size')
109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GET_SESSION_STORAGE_ITEM = (
110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      _Method.GET, '/session/:sessionId/session_storage/key/:key')
111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  REMOVE_SESSION_STORAGE_ITEM = (
112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      _Method.DELETE, '/session/:sessionId/session_storage/key/:key')
113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GET_SESSION_STORAGE_KEY = (_Method.GET, '/session/:sessionId/session_storage')
114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SET_SESSION_STORAGE_ITEM = (
115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      _Method.POST, '/session/:sessionId/session_storage')
116868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  CLEAR_SESSION_STORAGE = (
117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      _Method.DELETE, '/session/:sessionId/session_storage')
118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GET_SESSION_STORAGE_SIZE = (
119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      _Method.GET, '/session/:sessionId/session_storage/size')
120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GET_SCREEN_ORIENTATION = (_Method.GET, '/session/:sessionId/orientation')
121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SET_SCREEN_ORIENTATION = (_Method.POST, '/session/:sessionId/orientation')
122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  MOUSE_CLICK = (_Method.POST, '/session/:sessionId/click')
123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  MOUSE_DOUBLE_CLICK = (_Method.POST, '/session/:sessionId/doubleclick')
124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  MOUSE_BUTTON_DOWN = (_Method.POST, '/session/:sessionId/buttondown')
125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  MOUSE_BUTTON_UP = (_Method.POST, '/session/:sessionId/buttonup')
126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  MOUSE_MOVE_TO = (_Method.POST, '/session/:sessionId/moveto')
127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SEND_KEYS_TO_ACTIVE_ELEMENT = (_Method.POST, '/session/:sessionId/keys')
128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  TOUCH_SINGLE_TAP = (_Method.POST, '/session/:sessionId/touch/click')
129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  TOUCH_DOWN = (_Method.POST, '/session/:sessionId/touch/down')
130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  TOUCH_UP = (_Method.POST, '/session/:sessionId/touch/up')
131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  TOUCH_MOVE = (_Method.POST, '/session/:sessionId/touch/move')
132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  TOUCH_SCROLL = (_Method.POST, '/session/:sessionId/touch/scroll')
133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  TOUCH_DOUBLE_TAP = (_Method.POST, '/session/:sessionId/touch/doubleclick')
134868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  TOUCH_LONG_PRESS = (_Method.POST, '/session/:sessionId/touch/longclick')
135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  TOUCH_FLICK = (_Method.POST, '/session/:sessionId/touch/flick')
136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GET_LOG = (_Method.POST, '/session/:sessionId/log')
137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GET_AVAILABLE_LOG_TYPES = (_Method.GET, '/session/:sessionId/log/types')
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  IS_AUTO_REPORTING = (_Method.GET, '/session/:sessionId/autoreport')
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SET_AUTO_REPORTING = (_Method.POST, '/session/:sessionId/autoreport')
140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GET_SESSION_LOGS = (_Method.POST, '/logs')
141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  STATUS = (_Method.GET, '/status')
142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  # Custom Chrome commands.
144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IS_LOADING = (_Method.GET, '/session/:sessionId/is_loading')
145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class CommandExecutor(object):
148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  def __init__(self, server_url):
149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    self._server_url = server_url
150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    port = int(server_url.split(':')[2].split('/')[0])
151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    self._http_client = httplib.HTTPConnection('127.0.0.1', port, timeout=30)
152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  def Execute(self, command, params):
154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    url_parts = command[1].split('/')
155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    substituted_parts = []
156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    for part in url_parts:
157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if part.startswith(':'):
158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        key = part[1:]
159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        substituted_parts += [params[key]]
160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        del params[key]
161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      else:
162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        substituted_parts += [part]
163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    body = None
165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if command[0] == _Method.POST:
166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      body = json.dumps(params)
167868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    self._http_client.request(command[0], '/'.join(substituted_parts), body)
168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    response = self._http_client.getresponse()
169868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if response.status == 303:
171868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      self._http_client.request(_Method.GET, response.getheader('location'))
172868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      response = self._http_client.getresponse()
173868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if response.status != 200:
174868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      raise RuntimeError('Server returned error: ' + response.reason)
175868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
176868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return json.loads(response.read())
177