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)
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
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()
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)
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()