diff --git a/tests/test_authn.py b/tests/test_authn.py index c4e1e0f..49bc1e4 100644 --- a/tests/test_authn.py +++ b/tests/test_authn.py @@ -16,6 +16,7 @@ from oic.oauth2 import AccessTokenRequest from oic.utils.authn.user import UsernamePasswordMako from oic.utils.keyio import KeyBundle from oic.utils.keyio import rsa_load +from utils_for_tests import URLObject, _eq __author__ = 'rolandh' @@ -49,10 +50,6 @@ class SRV(object): pass -def _eq(l1, l2): - return set(l1) == set(l2) - - def test_1(): authn = UsernamePasswordMako(None, "login.mako", tl, PASSWD, "authorization_endpoint") @@ -79,7 +76,9 @@ def test_3(): authn = UsernamePasswordMako(srv, "login.mako", tl, PASSWD, "authorization_endpoint") response, success = authn.verify(parse_qs(form)) - assert response.message == "authorization_endpoint?query=foo&upm_answer=true" + url_in_response_msg = URLObject.create(response.message) + expected_url_obj = URLObject.create("authorization_endpoint?query=foo&upm_answer=true") + assert url_in_response_msg == expected_url_obj print len(response.headers) == 2 flag = 0 for param, val in response.headers: diff --git a/tests/test_keyio.py b/tests/test_keyio.py index 0655f03..cf9d917 100644 --- a/tests/test_keyio.py +++ b/tests/test_keyio.py @@ -12,6 +12,7 @@ from oic.utils.keyio import RSAKey from jwkest.jws import JWS, NoSuitableSigningKeys, WrongTypeOfKey +from utils_for_tests import _eq BASE_PATH = os.path.dirname(__file__) @@ -29,10 +30,6 @@ JWK1 = {"keys": [ ]} -def _eq(l1, l2): - return set(l1) == set(l2) - - def test_chain_1(): kc = KeyBundle([{"kty": "oct", "key": "supersecret", "use": "sig"}]) assert len(kc.get("oct")) == 1 diff --git a/tests/test_oauth2.py b/tests/test_oauth2.py index 194dbef..ba6cb31 100644 --- a/tests/test_oauth2.py +++ b/tests/test_oauth2.py @@ -25,10 +25,7 @@ from oic.utils.authn.client import BearerHeader from oic.utils.keyio import KeyBundle from pytest import raises - - -def _eq(l1, l2): - return set(l1) == set(l2) +from utils_for_tests import URLObject, _eq # ----------------- GRANT -------------------- @@ -343,7 +340,10 @@ class TestOAuthClient(): # default == "POST" assert uri == 'https://example.com/authz' print body - assert body == "state=hmm&redirect_uri=http%3A%2F%2Fclient.example.com%2Fauthz&response_type=code&client_id=1" + body_elts = body.split('&') + expected_body = "state=hmm&redirect_uri=http%3A%2F%2Fclient.example.com%2Fauthz&response_type=code&client_id=1" + expected_body_elts = expected_body.split('&') + assert set(body_elts) == set(expected_body_elts) assert h_args == {'headers': {'Content-type': 'application/x-www-form-urlencoded'}} assert cis.type() == "AuthorizationRequest" @@ -352,8 +352,9 @@ class TestOAuthClient(): self.client.authorization_endpoint = "https://example.com/authz" uri, body, h_args, cis = self.client.request_info(AuthorizationRequest, method="GET") - - assert uri == 'https://example.com/authz?redirect_uri=http%3A%2F%2Fclient.example.com%2Fauthz&response_type=code&client_id=1' + uri_obj = URLObject.create(uri) + expected_uri_obj = URLObject.create('https://example.com/authz?redirect_uri=http%3A%2F%2Fclient.example.com%2Fauthz&response_type=code&client_id=1') + assert uri_obj == expected_uri_obj assert body is None assert h_args == {} assert cis.type() == "AuthorizationRequest" @@ -363,8 +364,9 @@ class TestOAuthClient(): uri, body, h_args, cis = self.client.request_info( AuthorizationRequest, method="GET", request_args={"state": "init"}) - print uri - assert uri == 'https://example.com/authz?state=init&redirect_uri=http%3A%2F%2Fclient.example.com%2Fauthz&response_type=code&client_id=1' + uri_obj = URLObject.create(uri) + expected_uri_obj = URLObject.create('https://example.com/authz?state=init&redirect_uri=http%3A%2F%2Fclient.example.com%2Fauthz&response_type=code&client_id=1') + assert uri_obj == expected_uri_obj assert body is None assert h_args == {} assert cis.type() == "AuthorizationRequest" @@ -374,8 +376,10 @@ class TestOAuthClient(): uri, body, h_args, cis = self.client.request_info( AuthorizationRequest, method="GET", extra_args={"rock": "little"}) - print uri - assert uri == 'https://example.com/authz?redirect_uri=http%3A%2F%2Fclient.example.com%2Fauthz&response_type=code&client_id=1&rock=little' + + uri_obj = URLObject.create(uri) + expected_uri_obj = URLObject.create('https://example.com/authz?redirect_uri=http%3A%2F%2Fclient.example.com%2Fauthz&response_type=code&client_id=1&rock=little') + assert uri_obj == expected_uri_obj assert body is None assert h_args == {} assert cis.type() == "AuthorizationRequest" @@ -388,8 +392,9 @@ class TestOAuthClient(): request_args={"state": "init"}, extra_args={"rock": "little"}) - print uri - assert uri == 'https://example.com/authz?state=init&redirect_uri=http%3A%2F%2Fclient.example.com%2Fauthz&response_type=code&client_id=1&rock=little' + uri_obj = URLObject.create(uri) + expected_uri_obj = URLObject.create('https://example.com/authz?state=init&redirect_uri=http%3A%2F%2Fclient.example.com%2Fauthz&response_type=code&client_id=1&rock=little') + assert uri_obj == expected_uri_obj assert body is None assert h_args == {} assert cis.type() == "AuthorizationRequest" diff --git a/tests/test_oauth2_consumer.py b/tests/test_oauth2_consumer.py index ccd918f..2350c09 100644 --- a/tests/test_oauth2_consumer.py +++ b/tests/test_oauth2_consumer.py @@ -18,6 +18,8 @@ from oic.oauth2.message import TokenErrorResponse from oic.oauth2.consumer import AuthzError +from utils_for_tests import URLObject + #from oic.oauth2.message import # client_id=None, ca_certs=None,grant_expire_in=600, client_timeout=0, @@ -132,7 +134,9 @@ def test_consumer_begin(): url = "http://localhost:8088/authorization?%s" % urllib.urlencode(params) - assert loc == url + loc_obj = URLObject.create(loc) + url_obj = URLObject.create(url) + assert loc_obj == url_obj def test_consumer_handle_authorization_response(): @@ -265,11 +269,14 @@ def test_consumer_client_get_access_token_reques(): "urlencoded") url, body, http_args = cons.get_access_token_request(_state) - assert url == "http://localhost:8088/token" - print body - assert body == ("code=auth_grant&client_secret=secret0&" - "grant_type=authorization_code&client_id=number5&" - "redirect_uri=https%3A%2F%2Fwww.example.com%2Foic%2Fcb") + url_obj = URLObject.create(url) + expected_url_obj = URLObject.create("http://localhost:8088/token") + assert url_obj == expected_url_obj + body_splits = body.split('&') + expected_body_splits = "code=auth_grant&client_secret=secret0&" \ + "grant_type=authorization_code&client_id=number5&" \ + "redirect_uri=https%3A%2F%2Fwww.example.com%2Foic%2Fcb".split('&') + assert set(body_splits) == set(expected_body_splits) assert http_args == {'headers': { 'Content-type': 'application/x-www-form-urlencoded'}} diff --git a/tests/test_oauth2_message.py b/tests/test_oauth2_message.py index 32d42d3..774a183 100644 --- a/tests/test_oauth2_message.py +++ b/tests/test_oauth2_message.py @@ -1,10 +1,14 @@ __author__ = 'rohe0002' +import json + from oic.oauth2.message import * from jwkest.jwk import SYMKey from pytest import raises +from utils_for_tests import _eq + class Dummy_Message(Message): c_param = { @@ -16,10 +20,6 @@ class Dummy_Message(Message): "opt_json": SINGLE_OPTIONAL_JSON} -def _eq(l1, l2): - return set(l1) == set(l2) - - def test_authz_req_urlencoded_1(): ar = AuthorizationRequest(response_type=["code"], client_id="foobar") ue = ar.to_urlencoded() @@ -33,8 +33,9 @@ def test_authz_req_urlencoded_2(): state="cold") ue = ar.to_urlencoded() - print ue - assert ue == "state=cold&redirect_uri=http%3A%2F%2Ffoobar.example.com%2Foaclient&response_type=code&client_id=foobar" + ue_splits = ue.split('&') + expected_ue_splits = "state=cold&redirect_uri=http%3A%2F%2Ffoobar.example.com%2Foaclient&response_type=code&client_id=foobar".split('&') + assert _eq(ue_splits, expected_ue_splits) @@ -69,8 +70,9 @@ def test_authz_req_urlencoded_5(): scope=["foo", "bar"], state="cold") ue = ar.to_urlencoded() - print ue - assert ue == "scope=foo+bar&state=cold&redirect_uri=http%3A%2F%2Ffoobar.example.com%2Foaclient&response_type=code&client_id=foobar" + ue_splits = ue.split('&') + expected_ue_splits = "scope=foo+bar&state=cold&redirect_uri=http%3A%2F%2Ffoobar.example.com%2Foaclient&response_type=code&client_id=foobar".split('&') + assert _eq(ue_splits, expected_ue_splits) def test_authz_req_urlencoded_6(): @@ -119,9 +121,9 @@ def test_authz_req_json_1(): ar = AuthorizationRequest(response_type=["code"], client_id="foobar") - js = ar.serialize(method="json") - print js - assert js == '{"response_type": "code", "client_id": "foobar"}' + js_obj = json.loads(ar.serialize(method="json")) + expected_js_obj = {"response_type": "code", "client_id": "foobar"} + assert js_obj == expected_js_obj def test_authz_req_json_2(): @@ -130,9 +132,14 @@ def test_authz_req_json_2(): redirect_uri="http://foobar.example.com/oaclient", state="cold") - ue = ar.serialize(method="json") - print ue - assert ue == '{"state": "cold", "redirect_uri": "http://foobar.example.com/oaclient", "response_type": "code", "client_id": "foobar"}' + ue_obj = json.loads(ar.serialize(method="json")) + expected_ue_obj = { + "response_type": "code", + "state": "cold", + "redirect_uri": "http://foobar.example.com/oaclient", + "client_id": "foobar" + } + assert ue_obj == expected_ue_obj def test_authz_req_urlencoded_3(): @@ -141,9 +148,9 @@ def test_authz_req_urlencoded_3(): redirect_uri="https://client.example.com/cb", state="xyz") - ue = ar.serialize(method="json") - print ue - assert ue == '{"state": "xyz", "redirect_uri": "https://client.example.com/cb", "response_type": "token", "client_id": "s6BhdRkqt3"}' + ue_obj = json.loads(ar.serialize(method="json")) + expected_ue_obj = {"state": "xyz", "redirect_uri": "https://client.example.com/cb", "response_type": "token", "client_id": "s6BhdRkqt3"} + assert ue_obj == expected_ue_obj def test_authz_req_urlencoded_4(): @@ -225,8 +232,9 @@ def test_accesstokenreponse_1(): assert at atj = at.serialize(method="json") - print atj - assert atj == '{"token_type": "Bearer", "access_token": "SlAV32hkKG", "expires_in": 3600}' + atj_obj = json.loads(atj) + expected_atj_obj = {"token_type": "Bearer", "access_token": "SlAV32hkKG", "expires_in": 3600} + assert atj_obj == expected_atj_obj # AccessTokenRequest @@ -238,9 +246,10 @@ def test_extra(): assert atr query = atr.to_urlencoded() - print query - assert query == "code=SplxlOBeZQQYbYS6WxSbIA&redirect_uri=https%3A%2F" \ - "%2Fclient.example.com%2Fcb&grant_type=authorization_code&extra=foo" + query_splits = query.split('&') + expected_query_splits = "code=SplxlOBeZQQYbYS6WxSbIA&redirect_uri=https%3A%2F" \ + "%2Fclient.example.com%2Fcb&grant_type=authorization_code&extra=foo".split('&') + assert _eq(query_splits, expected_query_splits) atr2 = AccessTokenRequest().deserialize(query, "urlencoded") @@ -536,8 +545,9 @@ def test_multiple_response_types_urlencoded(): ar = AuthorizationRequest(response_type=["code", "token"], client_id="foobar") ue = ar.to_urlencoded() - print ue - assert ue == "response_type=code+token&client_id=foobar" + ue_splits = ue.split('&') + expected_ue_splits = "response_type=code+token&client_id=foobar".split('&') + assert _eq(ue_splits, expected_ue_splits) are = AuthorizationRequest().deserialize(ue, "urlencoded") assert _eq(are.keys(), ["response_type", "client_id"]) @@ -548,8 +558,9 @@ def test_multiple_scopes_urlencoded(): ar = AuthorizationRequest(response_type=["code", "token"], client_id="foobar", scope=["openid", "foxtrot"]) ue = ar.to_urlencoded() - print ue - assert ue == "scope=openid+foxtrot&response_type=code+token&client_id=foobar" + ue_splits = ue.split('&') + expected_ue_splits = "scope=openid+foxtrot&response_type=code+token&client_id=foobar".split('&') + assert _eq(ue_splits, expected_ue_splits) are = AuthorizationRequest().deserialize(ue, "urlencoded") assert _eq(are.keys(), ["response_type", "client_id", "scope"]) @@ -561,8 +572,9 @@ def test_multiple_response_types_json(): ar = AuthorizationRequest(response_type=["code", "token"], client_id="foobar") ue = ar.to_json() - print ue - assert ue == '{"response_type": "code token", "client_id": "foobar"}' + ue_obj = json.loads(ue) + expected_ue_obj = {"response_type": "code token", "client_id": "foobar"} + assert ue_obj == expected_ue_obj are = AuthorizationRequest().deserialize(ue, "json") print are.keys() @@ -574,8 +586,9 @@ def test_multiple_scopes_json(): ar = AuthorizationRequest(response_type=["code", "token"], client_id="foobar", scope=["openid", "foxtrot"]) ue = ar.to_json() - print ue - assert ue == '{"scope": "openid foxtrot", "response_type": "code token", "client_id": "foobar"}' + ue_obj = json.loads(ue) + expected_ue_obj = {"scope": "openid foxtrot", "response_type": "code token", "client_id": "foobar"} + assert ue_obj == expected_ue_obj are = AuthorizationRequest().deserialize(ue, "json") assert _eq(are.keys(), ["response_type", "client_id", "scope"]) diff --git a/tests/test_oauth2_provider.py b/tests/test_oauth2_provider.py index 6f56a41..57b43ec 100644 --- a/tests/test_oauth2_provider.py +++ b/tests/test_oauth2_provider.py @@ -15,6 +15,8 @@ from oic.utils import sdb from oic.oauth2.consumer import Consumer from oic.oauth2.provider import Provider +from utils_for_tests import _eq + CLIENT_CONFIG = { "client_id": "client1", "ca_certs": "/usr/local/etc/oic/ca_certs.txt", @@ -84,10 +86,6 @@ def content_type(headers): return "json" -def _eq(l1, l2): - return set(l1) == set(l2) - - def test_provider_init(): provider = Provider("pyoicserv", sdb.SessionDB(SERVER_INFO["issuer"]), CDB, AUTHN_BROKER, AUTHZ, verify_client) diff --git a/tests/test_oic.py b/tests/test_oic.py index 44329c5..2b0fe2e 100644 --- a/tests/test_oic.py +++ b/tests/test_oic.py @@ -44,11 +44,7 @@ from pytest import raises from fakeoicsrv import MyFakeOICServer - -def _eq(l1, l2): - s1 = set(l1) - s2 = set(l2) - return s1 == s2 +from utils_for_tests import _eq CLIENT_SECRET = "abcdefghijklmnop" diff --git a/tests/test_oic_consumer.py b/tests/test_oic_consumer.py index 6374e75..fff6200 100644 --- a/tests/test_oic_consumer.py +++ b/tests/test_oic_consumer.py @@ -20,6 +20,8 @@ from oic.utils.sdb import SessionDB from fakeoicsrv import MyFakeOICServer +from utils_for_tests import _eq + CLIENT_SECRET = "abcdefghijklmnop" CLIENT_ID = "client_1" @@ -91,10 +93,6 @@ def start_response(status=200, headers=None): return "status=%s, headers=%s" % (status, headers) -def _eq(l1, l2): - return set(l1) == set(l2) - - def test_clean_response(): atr = AccessTokenResponse(access_token="access_token", token_type="bearer", expires_in=600, diff --git a/tests/test_oic_message.py b/tests/test_oic_message.py index 5f156ef..e213310 100644 --- a/tests/test_oic_message.py +++ b/tests/test_oic_message.py @@ -12,9 +12,7 @@ from oic.oic.message import AddressClaim from oic.oic.message import address_deser from oic.oic.message import Claims - -def _eq(l1, l2): - return set(l1) == set(l2) +from utils_for_tests import _eq def test_ProviderConfigurationResponse(): @@ -300,11 +298,13 @@ def test_registration_request(): application_type="web", redirect_uris=["https://example.com/authz_cb"]) js = req.to_json() - print js - assert js == '{"redirect_uris": ["https://example.com/authz_cb"], "application_type": "web", "default_acr": "foo", "require_auth_time": true, "operation": "register", "default_max_age": 10}' + js_obj = json.loads(js) + expected_js_obj = {"redirect_uris": ["https://example.com/authz_cb"], "application_type": "web", "default_acr": "foo", "require_auth_time": True, "operation": "register", "default_max_age": 10} + assert js_obj == expected_js_obj ue = req.to_urlencoded() - print ue - assert ue == 'redirect_uris=https%3A%2F%2Fexample.com%2Fauthz_cb&application_type=web&default_acr=foo&require_auth_time=True&operation=register&default_max_age=10' + ue_splits = ue.split('&') + expected_ue_splits = 'redirect_uris=https%3A%2F%2Fexample.com%2Fauthz_cb&application_type=web&default_acr=foo&require_auth_time=True&operation=register&default_max_age=10'.split('&') + assert _eq(ue_splits, expected_ue_splits) if __name__ == "__main__": diff --git a/tests/test_oic_provider.py b/tests/test_oic_provider.py index 51111b8..1c86426 100644 --- a/tests/test_oic_provider.py +++ b/tests/test_oic_provider.py @@ -37,6 +37,7 @@ from oic.oic.consumer import Consumer from oic.oic.provider import Provider from oic.utils.time_util import epoch_in_a_while +from utils_for_tests import _eq __author__ = 'rohe0002' @@ -164,10 +165,6 @@ provider_init = Provider("pyoicserv", SessionDB(SERVER_INFO["issuer"]), CDB, keyjar=KEYJAR) -def _eq(l1, l2): - return set(l1) == set(l2) - - def test_server_init(): server = provider_init @@ -554,7 +551,9 @@ def test_userinfo_endpoint(): ident = OpenIDSchema().deserialize(resp3.message, "json") print ident.keys() assert _eq(ident.keys(), ['nickname', 'sub', 'name', 'email']) - assert ident["sub"] == hash(USERDB["username"]["sub"]+server.sdb.base_url) + print str(ident) + expected_sub = "%x" % hash(USERDB["username"]["sub"]+server.sdb.base_url) + assert ident["sub"] == expected_sub def test_check_session_endpoint(): diff --git a/tests/test_sdb.py b/tests/test_sdb.py index f7b967e..ea35cfd 100644 --- a/tests/test_sdb.py +++ b/tests/test_sdb.py @@ -11,6 +11,8 @@ from oic.utils.sdb import ExpiredToken from oic.oic.message import AuthorizationRequest from oic.oic.message import OpenIDRequest +from utils_for_tests import _eq + #from oic.oauth2 import message AREQ = AuthorizationRequest(response_type="code", client_id="client1", @@ -34,10 +36,6 @@ OAUTH2_AREQ = AuthorizationRequest(response_type="code", BASE_URL = "https://exampl.com/" -def _eq(l1, l2): - return set(l1) == set(l2) - - def test_token(): sdb = SessionDB(BASE_URL) sid = sdb.token.key(areq=AREQ) diff --git a/tests/test_stateless.py b/tests/test_stateless.py index 25f5bd8..b9fc8ac 100644 --- a/tests/test_stateless.py +++ b/tests/test_stateless.py @@ -1,12 +1,10 @@ from oic.utils.stateless import StateLess +from utils_for_tests import _eq + __author__ = 'roland' -def _eq(l1, l2): - return set(l1) == set(l2) - - def test_access_code(): keys = {"OCT": ["symmetric key123"]} st = StateLess(keys, enc_alg="A128KW", enc_method="A128CBC-HS256") diff --git a/tests/test_utils_for_tests.py b/tests/test_utils_for_tests.py new file mode 100644 index 0000000..7fc6019 --- /dev/null +++ b/tests/test_utils_for_tests.py @@ -0,0 +1,13 @@ +from utils_for_tests import URLObject + +__author__ = "@maennelpaennel" + +def test_utils_urlobject_init(): + url_1 = URLObject(host='host', resource='resource', arguments=set(['arguments'])) + url_2 = URLObject(host='host', resource='resource', arguments=set(['arguments'])) + assert url_1 == url_2 + +def test_utils_urlobject_set_by_string(): + url_1 = URLObject.create('this_is_a_host/this_is_a_resource?followed_by=args&and_more=args') + url_2 = URLObject(host='this_is_a_host', resource='this_is_a_resource', arguments=set(['followed_by=args', 'and_more=args'])) + assert url_1 == url_2 diff --git a/tests/test_x_claims.py b/tests/test_x_claims.py index 2c843bc..957d5b6 100644 --- a/tests/test_x_claims.py +++ b/tests/test_x_claims.py @@ -22,6 +22,7 @@ from oic.oic.claims_provider import UserClaimsResponse from oic.oic.claims_provider import UserClaimsRequest from oic.oic.claims_provider import ClaimsServer +from utils_for_tests import _eq #noinspection PyUnusedLocal def user_info(oicsrv, userdb, sub, client_id="", user_info_claims=None): @@ -92,10 +93,6 @@ USER2MODE = {"diana": "aggregate", # ============================================================================ -def _eq(l1, l2): - return set(l1) == set(l2) - - def test_1(): cc = ClaimsClient(client_id="client_1") cc.client_secret = "hemlig" diff --git a/tests/test_x_dynreg.py b/tests/test_x_dynreg.py index 9467927..626158f 100644 --- a/tests/test_x_dynreg.py +++ b/tests/test_x_dynreg.py @@ -14,6 +14,8 @@ from oic.oauth2.dynreg import RegistrationRequest from oic.oauth2.dynreg import ClientInfoResponse from oic.oauth2.dynreg import ClientRegistrationError +from utils_for_tests import _eq + CLIENT_CONFIG = { "client_id": "client1", "ca_certs": "/usr/local/etc/oic/ca_certs.txt", @@ -84,10 +86,6 @@ def content_type(headers): return "json" -def _eq(l1, l2): - return set(l1) == set(l2) - - def test_provider_init(): provider = Provider("pyoicserv", sdb.SessionDB(SERVER_INFO["issuer"]), CDB, AUTHN_BROKER, AUTHZ, diff --git a/tests/utils_for_tests.py b/tests/utils_for_tests.py new file mode 100644 index 0000000..de9a0d5 --- /dev/null +++ b/tests/utils_for_tests.py @@ -0,0 +1,56 @@ +__author__ = "@maennelpaennel" + +def _eq(l1, l2): + return set(l1) == set(l2) + + +class URLObject(object): + host = '' + resource = '' + arguments = set() + + @classmethod + def create(klass, address): + url_obj = klass() + url_obj.set_by_string(address) + return url_obj + + def __init__(self, host='', resource='', arguments=None): + self.host = host + self.resource = resource + self.arguments = arguments or set() + + def __eq__(self, other): + return self.host==other.host and self.resource==other.resource and self.arguments==other.arguments + + def set_by_string(self, address): + """ + address has the following format ":///?=&..." + """ + address_splits = address.split('?', 1) + if len(address_splits) == 1: + host_resource = address_splits[0] + arguments_str = '' + else: + host_resource = address_splits[0] + arguments_str = address_splits[1] + self.arguments = set(arguments_str.split('&')) + host_res_splits = host_resource.split('://', 1) + if len(host_res_splits) == 1: + host_resource = host_res_splits[0] + prefix = None + else: + host_resource = host_res_splits[0] + prefix = host_res_splits[1] + host_res_splits = host_resource.split('/', 1) + if len(host_res_splits) == 1: + host = None + resource = host_res_splits[0] + else: + host = host_res_splits[0] + resource = host_res_splits[1] + if host: + self.host = host + if prefix: + self.host = "%s://%s" % (prefix, host) + self.resource = resource