summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--module/remote/create_apitypes.py9
-rw-r--r--module/remote/wsbackend/Server.py13
-rw-r--r--module/web/api_app.py54
-rw-r--r--pavement.py2
-rwxr-xr-xpyload.py1
-rw-r--r--tests/api/test_JSONBackend.py36
6 files changed, 71 insertions, 44 deletions
diff --git a/module/remote/create_apitypes.py b/module/remote/create_apitypes.py
index 7755b5c57..d596f07ac 100644
--- a/module/remote/create_apitypes.py
+++ b/module/remote/create_apitypes.py
@@ -3,19 +3,18 @@
import re
import inspect
-import sys
from os.path import abspath, dirname, join
path = dirname(abspath(__file__))
-module = join(path, "..", "..")
-
-sys.path.append(join(module, "lib"))
-sys.path.append(join(module, "remote"))
+root = abspath(join(path, "..", ".."))
from thrift.Thrift import TType
from thriftgen.pyload import ttypes
from thriftgen.pyload import Pyload
+# TODO: import and add version
+# from pyload import CURRENT_VERSION
+
type_map = {
TType.BOOL: 'bool',
TType.DOUBLE: 'float',
diff --git a/module/remote/wsbackend/Server.py b/module/remote/wsbackend/Server.py
index 9b52f5464..af5e1cf19 100644
--- a/module/remote/wsbackend/Server.py
+++ b/module/remote/wsbackend/Server.py
@@ -459,9 +459,18 @@ class WebSocketRequestHandler(CGIHTTPServer.CGIHTTPRequestHandler):
if self._options.is_executable_method is not None:
self.is_executable = self._options.is_executable_method
+ # OWN MODIFICATION
# This actually calls BaseRequestHandler.__init__.
- CGIHTTPServer.CGIHTTPRequestHandler.__init__(
- self, request, client_address, server)
+ try:
+ CGIHTTPServer.CGIHTTPRequestHandler.__init__(
+ self, request, client_address, server)
+ except socket.error, e:
+ # Broken pipe, let it pass
+ if e.errno != 32:
+ raise
+ self._logger.debug("WS: Broken pipe")
+
+
def parse_request(self):
"""Override BaseHTTPServer.BaseHTTPRequestHandler.parse_request.
diff --git a/module/web/api_app.py b/module/web/api_app.py
index 690cf73aa..e8042f3fb 100644
--- a/module/web/api_app.py
+++ b/module/web/api_app.py
@@ -27,11 +27,11 @@ def call_api(func, args=""):
add_header(response)
s = request.environ.get('beaker.session')
+ # Accepts standard http auth
auth = parse_auth(request.get_header('Authorization', ''))
- # TODO: session as GET
- if 'session' in request.POST:
+ if 'session' in request.POST or 'session' in request.GET:
# removes "' so it works on json strings
- s = s.get_by_id(remove_chars(request.POST['session'], "'\""))
+ s = s.get_by_id(remove_chars(request.params.get('session'), "'\""))
elif auth:
user = PYLOAD.checkAuth(auth[0], auth[1], request.environ.get('REMOTE_ADDR', None))
# if auth is correct create a pseudo session
@@ -44,47 +44,45 @@ def call_api(func, args=""):
if not PYLOAD.isAuthorized(func, api.user):
return HTTPError(401, dumps("Unauthorized"))
- args = args.split("/")[1:]
+ if not hasattr(PYLOAD.EXTERNAL, func) or func.startswith("_"):
+ print "Invalid API call", func
+ return HTTPError(404, dumps("Not Found"))
+
+ # TODO: possible encoding
+ # TODO Better error codes on invalid input
+
+ args = [loads(unquote(arg)) for arg in args.split("/")[1:]]
kwargs = {}
+ # accepts body as json dict
+ if request.json:
+ kwargs = request.json
+
+ # convert arguments from json to obj separately
for x, y in chain(request.GET.iteritems(), request.POST.iteritems()):
- if x == "session": continue
- kwargs[x] = unquote(y)
+ if not x or not y or x == "session": continue
+ kwargs[x] = loads(unquote(y))
try:
- return callApi(api, func, *args, **kwargs)
+ result = getattr(api, func)(*args, **kwargs)
+ # null is invalid json response
+ if result is None: result = True
+ return dumps(result)
+
except ExceptionObject, e:
return HTTPError(400, dumps(e))
except Exception, e:
print_exc()
return HTTPError(500, dumps({"error": e.message, "traceback": format_exc()}))
-# TODO Better error codes on invalid input
-
-def callApi(api, func, *args, **kwargs):
- if not hasattr(PYLOAD.EXTERNAL, func) or func.startswith("_"):
- print "Invalid API call", func
- return HTTPError(404, dumps("Not Found"))
-
- # TODO: accept same payload as WS backends, combine into json_converter
- # TODO: arguments as json dictionaries
- # TODO: encoding
- result = getattr(api, func)(*[loads(x) for x in args],
- **dict([(x, loads(y)) for x, y in kwargs.iteritems()]))
-
- # null is invalid json response
- if result is None: result = True
-
- return dumps(result)
-
-#post -> username, password
+@route("/api/login")
@route("/api/login", method="POST")
def login():
add_header(response)
- username = request.forms.get("username")
- password = request.forms.get("password")
+ username = request.params.get("username")
+ password = request.params.get("password")
user = PYLOAD.checkAuth(username, password, request.environ.get('REMOTE_ADDR', None))
diff --git a/pavement.py b/pavement.py
index 484501fab..b10ebfd0c 100644
--- a/pavement.py
+++ b/pavement.py
@@ -69,7 +69,7 @@ setup(
},
#setup_requires=["setuptools_hg"],
test_suite='nose.collector',
- tests_require=['nose', 'websocket-client >= 0.8.0'],
+ tests_require=['nose', 'websocket-client >= 0.8.0', 'requests >= 1.2.2'],
# scripts=['pyload', 'pyload-cli'],
entry_points={
'console_scripts': [
diff --git a/pyload.py b/pyload.py
index e6d095827..594b57838 100755
--- a/pyload.py
+++ b/pyload.py
@@ -22,7 +22,6 @@ CURRENT_VERSION = '0.4.9.9-dev'
import __builtin__
from getopt import getopt, GetoptError
-from imp import find_module
import logging
import logging.handlers
import os
diff --git a/tests/api/test_JSONBackend.py b/tests/api/test_JSONBackend.py
index b6509a52a..e99b97827 100644
--- a/tests/api/test_JSONBackend.py
+++ b/tests/api/test_JSONBackend.py
@@ -1,23 +1,47 @@
# -*- coding: utf-8 -*-
-from nose.tools import raises
+from nose.tools import raises, assert_equal
+
+from requests.auth import HTTPBasicAuth
+import requests
+
+import json
from module.remote.apitypes import Forbidden
from module.remote.JSONClient import JSONClient
+
class TestJSONBackend:
+ login = ("User", "pwhere")
def setUp(self):
self.client = JSONClient()
def test_login(self):
- self.client.login("User", "test")
+ self.client.login(*self.login)
self.client.getServerVersion()
self.client.logout()
def test_wronglogin(self):
ret = self.client.login("WrongUser", "wrongpw")
- assert ret == False
+ assert ret is False
+
+
+ def test_httpauth(self):
+ # cheap http auth
+ ret = requests.get(self.client.URL + "/getServerVersion", auth=HTTPBasicAuth(*self.login))
+ assert_equal(ret.status_code, 200)
+ assert ret.text
+
+ def test_jsonbody(self):
+ payload = {'section': 'webinterface', 'option': 'port'}
+ headers = {'content-type': 'application/json'}
+
+ ret = requests.get(self.client.URL + "/getConfigValue", headers=headers,
+ auth=HTTPBasicAuth(*self.login), data=json.dumps(payload))
+
+ assert_equal(ret.status_code, 200)
+ assert ret.text
@raises(Forbidden)
def test_access(self):
@@ -25,7 +49,5 @@ class TestJSONBackend:
@raises(AttributeError)
def test_unknown_method(self):
- self.client.login("User", "test")
- self.client.sdfdsg()
-
- # TODO: test raising of exceptions, also in WSBackend \ No newline at end of file
+ self.client.login(*self.login)
+ self.client.sdfdsg() \ No newline at end of file