Exemplo n.º 1
0
    def request_resource(self, path, sub_id, req_hdrs):
        # Prepare resource request
        res_req = ResourceRequest(path, "subscribe", sub_id=sub_id)
        url = urlunparse((self._django_url.scheme, self._django_url.netloc, res_req.path, "", "", ""))
        res_req.prepare(client_headers=req_hdrs)
        http = urllib3.PoolManager()
        resp = http.urlopen("POST", url, body=res_req.to_json(), headers=res_req.get_headers())

        if resp.status == 200:
            # Check returned data has the requested content type
            Resource.validate_content_type(resp.headers.get("Content-Type", None))

            # Return Resource object
            res_json = resp.data.decode("utf-8")
            return Resource.from_json(res_json)
        else:
            raise ResourceError(resp.status)
Exemplo n.º 2
0
    def rt_request(self, request):
        """Handle a Django-RT internal API request."""

        # Check client IP is allowed
        if not settings.DEBUG and settings.RT_COURIER_IPS: 
            if request.META['REMOTE_ADDR'] not in settings.RT_COURIER_IPS:
                return HttpResponseForbidden()

        # Deserialize ResourceRequest from body and verify signature
        #! TODO since the request is still considered unauthorized at this point, add exception handling here for bad data:
        #! * utf-8 errors
        #! * json errors
        #! * data errors
        #! * bad signature
        body = request.body.decode('utf-8')
        res_req = ResourceRequest.from_json(body)
        res_req.path = self.rt_get_path(request)
        res_req.verify_signature()

        # Open Redis connection
        redis_conn = redis.StrictRedis(
            host=settings.RT_REDIS_HOST,
            port=settings.RT_REDIS_PORT,
            db=settings.RT_REDIS_DB,
            password=settings.RT_REDIS_PASSWORD
        )

        # Get subscription status
        sub_key = get_subscription_key(res_req.sub_id)
        sub_status = redis_conn.get(sub_key).decode('utf-8')
        if not sub_status:
            return HttpResponseBadRequest('Invalid subscription ID')

        if res_req.action == 'subscribe':
            # Handle subscription request

            # Check subscription has 'requested' status
            if sub_status != 'requested':
                return HttpResponseBadRequest('Invalid subscription ID')

            # Check subscription is allowed
            if self.rt_get_permission('subscribe', request) is not True:
                return HttpResponseForbidden()

            # Set subscription status to 'granted'
            result = redis_conn.set(sub_key, 'granted')
            assert result

            # Return Resource object
            res = self.rt_get_resource(request)
            return JsonResponse(res.serialize(),
                content_type=Resource.CONTENT_TYPE+'; charset=utf-8'
            )
        else:
            # Shouldn't ever land here
            assert False
Exemplo n.º 3
0
    def request_resource(self, path, request, sub_id):
        # Prepare resource request
        res_req = ResourceRequest(path, 'subscribe',
            sub_id=sub_id
        )
        res_req.prepare(client_headers=request.headers)

        # Build resource URL
        if self._django_url.scheme == 'http+unix':
            conn = aiohttp.UnixConnector(path=self._django_url.path)
            # aiohttp expects a hostname in the URL, even when requesting over a domain socket; correct host should be present in header
            url = urlunparse(('http', 'unknown', res_req.path, '', '', ''))
        else:
            conn = None
            url = urlunparse((self._django_url.scheme, self._django_url.netloc, res_req.path, '', '', ''))

        # Make request
        logger.debug('Requesting subscription from %s%s' % (url,
            ' over Unix socket %s' % (self._django_url.path,) if conn else '')
        )
        resp = yield from aiohttp.post(url,
            data=res_req.to_json().encode('utf-8'),
            headers=res_req.get_headers(),
            connector=conn
        )
        try:
            if resp.status == 200:
                # Check returned data has the requested content type
                Resource.validate_content_type(resp.headers.get('Content-Type', None))

                # Return Resource object
                res_json = yield from resp.text()
                return Resource.from_json(res_json)
            else:
                raise ResourceError(resp.status)
        finally:
            # Ensure response is closed
            yield from resp.release()
Exemplo n.º 4
0
    def request_resource(self, path, sub_id, req_hdrs):
        # Prepare resource request
        res_req = ResourceRequest(path, 'subscribe', sub_id=sub_id)
        url = urlunparse((self._django_url.scheme, self._django_url.netloc,
                          res_req.path, '', '', ''))
        res_req.prepare(client_headers=req_hdrs)
        http = urllib3.PoolManager()
        resp = http.urlopen('POST',
                            url,
                            body=res_req.to_json(),
                            headers=res_req.get_headers())

        if resp.status == 200:
            # Check returned data has the requested content type
            Resource.validate_content_type(
                resp.headers.get('Content-Type', None))

            # Return Resource object
            res_json = resp.data.decode('utf-8')
            return Resource.from_json(res_json)
        else:
            raise ResourceError(resp.status)
Exemplo n.º 5
0
    def request_resource(self, path, request, sub_id):
        # Prepare resource request
        res_req = ResourceRequest(path, 'subscribe', sub_id=sub_id)
        res_req.prepare(client_headers=request.headers)

        # Build resource URL
        if self._django_url.scheme == 'http+unix':
            conn = aiohttp.UnixConnector(path=self._django_url.path)
            # aiohttp expects a hostname in the URL, even when requesting over a domain socket; correct host should be present in header
            url = urlunparse(('http', 'unknown', res_req.path, '', '', ''))
        else:
            conn = None
            url = urlunparse((self._django_url.scheme, self._django_url.netloc,
                              res_req.path, '', '', ''))

        # Make request
        logger.debug('Requesting subscription from %s%s' %
                     (url, ' over Unix socket %s' %
                      (self._django_url.path, ) if conn else ''))
        resp = yield from aiohttp.post(url,
                                       data=res_req.to_json().encode('utf-8'),
                                       headers=res_req.get_headers(),
                                       connector=conn)
        try:
            if resp.status == 200:
                # Check returned data has the requested content type
                Resource.validate_content_type(
                    resp.headers.get('Content-Type', None))

                # Return Resource object
                res_json = yield from resp.text()
                return Resource.from_json(res_json)
            else:
                raise ResourceError(resp.status)
        finally:
            # Ensure response is closed
            yield from resp.release()