Пример #1
0
    def read(self, request, vendor, name, version):

        operator = get_object_or_404(CatalogueResource, type=2, vendor=vendor, short_name=name, version=version)
        # For now, all operators are freely accessible/distributable
        # if not operator.is_available_for(request.user):
        #    return HttpResponseForbidden()

        mode = request.GET.get('mode', 'classic')

        key = get_operator_cache_key(operator, get_current_domain(request), mode)
        cached_response = cache.get(key)
        if cached_response is None:
            options = operator.json_description
            js_files = options['js_files']

            base_url = get_absolute_reverse_url('wirecloud.showcase_media', kwargs={
                'vendor': operator.vendor,
                'name': operator.short_name,
                'version': operator.version,
                'file_path': operator.template_uri
            }, request=request)

            xhtml = generate_xhtml_operator_code(js_files, base_url, request, process_requirements(options['requirements']), mode)
            cache_timeout = 31536000  # 1 year
            cached_response = CacheableData(xhtml, timeout=cache_timeout, content_type='application/xhtml+xml; charset=UTF-8')

            cache.set(key, cached_response, cache_timeout)

        return cached_response.get_response()
Пример #2
0
def get_widget_api_files(request):

    from wirecloud.platform.core.plugins import get_version_hash

    key = 'widget_api_files/%s?v=%s' % (get_current_domain(request),
                                        get_version_hash())
    widget_api_files = cache.get(key)

    if widget_api_files is None or settings.DEBUG is True:
        code = '''{% load compress %}{% load static from staticfiles %}{% compress js %}
        <script type="text/javascript" src="{% static "js/WirecloudAPI/WirecloudAPIBootstrap.js" %}"></script>
        <script type="text/javascript" src="{% static "js/WirecloudAPI/WirecloudWidgetAPI.js" %}"></script>
        <script type="text/javascript" src="{% static "js/WirecloudAPI/WirecloudAPICommon.js" %}"></script>
        {% endcompress %}'''

        result = Template(code).render(Context())
        doc = etree.parse(
            BytesIO(('<files>' + result + '</files>').encode('utf-8')),
            etree.XMLParser())

        files = [script.get('src') for script in doc.getroot()]
        files.reverse()
        widget_api_files = tuple([
            get_absolute_static_url(file, request=request, versioned=True)
            for file in files
        ])
        cache.set(key, widget_api_files)

    return list(widget_api_files)
Пример #3
0
 def test_get_current_domain_forced(self):
     request = self._prepare_request_mock()
     with patch(self.get_current_site_import) as get_current_site_mock:
         with patch.multiple('wirecloud.commons.utils.http', socket=DEFAULT, get_current_scheme=DEFAULT) as mocks:
             mocks['get_current_scheme'].return_value = 'http'
             self.assertEqual(get_current_domain(request), 'myserver.com:8080')
             self.assertEqual(mocks['socket'].getfqdn.call_count, 0)
             self.assertEqual(get_current_site_mock.call_count, 0)
Пример #4
0
 def test_get_current_domain_forced_port(self):
     request = self._prepare_request_mock()
     with patch('django.contrib.sites.shortcuts.get_current_site') as get_current_site_mock:
         with patch.multiple('wirecloud.commons.utils.http', socket=DEFAULT, get_current_scheme=DEFAULT, _servername=None) as mocks:
             get_current_site_mock.return_value = self._prepare_site_mock()
             mocks['get_current_scheme'].return_value = 'http'
             self.assertEqual(get_current_domain(request), 'site.example.com:81')
             self.assertEqual(mocks['socket'].getfqdn.call_count, 0)
Пример #5
0
 def test_get_current_domain_fallback_https_custom_port(self):
     request = self._prepare_request_mock()
     with patch('django.contrib.sites.models.get_current_site') as get_current_site_mock:
         with patch.multiple('wirecloud.commons.utils.http', socket=DEFAULT, get_current_scheme=DEFAULT) as mocks:
             get_current_site_mock.side_effect = Exception
             mocks['socket'].getfqdn.return_value = 'example.com'
             mocks['get_current_scheme'].return_value = 'http'
             self.assertEqual(get_current_domain(request), 'fqdn.example.com:8443')
Пример #6
0
 def test_get_current_domain_fallback_https_custom_port(self):
     request = self._prepare_request_mock()
     with patch('django.contrib.sites.shortcuts.get_current_site') as get_current_site_mock:
         with patch.multiple('wirecloud.commons.utils.http', socket=DEFAULT, get_current_scheme=DEFAULT, _servername=None) as mocks:
             get_current_site_mock.side_effect = Exception
             mocks['socket'].getfqdn.return_value = 'example.com'
             mocks['get_current_scheme'].return_value = 'http'
             self.assertEqual(get_current_domain(request), 'example.com:8443')
Пример #7
0
 def test_get_current_domain_forced_port(self):
     request = self._prepare_request_mock()
     with patch('django.contrib.sites.models.get_current_site') as get_current_site_mock:
         with patch.multiple('wirecloud.commons.utils.http', socket=DEFAULT, get_current_scheme=DEFAULT) as mocks:
             get_current_site_mock.return_value = self._prepare_site_mock()
             mocks['get_current_scheme'].return_value = 'http'
             self.assertEqual(get_current_domain(request), 'site.example.com:81')
             self.assertEqual(mocks['socket'].getfqdn.call_count, 0)
Пример #8
0
 def test_get_current_domain_fallback_https(self):
     request = self._prepare_request_mock()
     with patch(self.get_current_site_import) as get_current_site_mock:
         with patch.multiple('wirecloud.commons.utils.http',
                             socket=DEFAULT,
                             get_current_scheme=DEFAULT) as mocks:
             get_current_site_mock.side_effect = Exception
             mocks['socket'].getfqdn.return_value = 'fqdn.example.com'
             mocks['get_current_scheme'].return_value = 'https'
             self.assertEqual(get_current_domain(request),
                              'fqdn.example.com')
Пример #9
0
 def test_get_current_domain_forced_domain(self):
     request = self._prepare_request_mock()
     with patch(self.get_current_site_import) as get_current_site_mock:
         with patch.multiple('wirecloud.commons.utils.http',
                             socket=DEFAULT,
                             get_current_scheme=DEFAULT) as mocks:
             get_current_site_mock.return_value = self._prepare_site_mock()
             mocks['get_current_scheme'].return_value = 'http'
             self.assertEqual(get_current_domain(request),
                              'forced.example.com:8000')
             self.assertEqual(mocks['socket'].getfqdn.call_count, 0)
Пример #10
0
 def test_get_current_domain_forced(self):
     request = self._prepare_request_mock()
     with patch('django.contrib.sites.models.get_current_site'
                ) as get_current_site_mock:
         with patch.multiple('wirecloud.commons.utils.http',
                             socket=DEFAULT,
                             get_current_scheme=DEFAULT) as mocks:
             mocks['get_current_scheme'].return_value = 'http'
             self.assertEqual(get_current_domain(request),
                              'myserver.com:8080')
             self.assertEqual(mocks['socket'].getfqdn.call_count, 0)
             self.assertEqual(get_current_site_mock.call_count, 0)
Пример #11
0
    def read(self, request, vendor, name, version):

        widget = get_object_or_404(
            Widget, resource__vendor=vendor, resource__short_name=name, resource__version=version
        )
        if not widget.is_available_for(request.user):
            raise Http403()

        # check if the xhtml code has been cached
        if widget.xhtml.cacheable:

            cache_key = widget.xhtml.get_cache_key(get_current_domain(request))
            cache_entry = cache.get(cache_key)
            if cache_entry is not None:
                response = HttpResponse(cache_entry["code"], mimetype="%s; charset=UTF-8" % cache_entry["content_type"])
                patch_cache_headers(response, cache_entry["timestamp"], cache_entry["timeout"])
                return response

        # process xhtml
        xhtml = widget.xhtml

        content_type = xhtml.content_type
        if not content_type:
            content_type = "text/html"

        force_base = False
        base_url = xhtml.url
        if not base_url.startswith(("http://", "https://")):
            base_url = get_absolute_reverse_url(
                "wirecloud_showcase.media", args=(base_url.split("/", 4)), request=request
            )
            force_base = True

        code = xhtml.code
        if not xhtml.cacheable or code == "":
            try:
                if xhtml.url.startswith(("http://", "https://")):
                    code = downloader.download_http_content(urljoin(base_url, xhtml.url), user=request.user)
                else:
                    code = downloader.download_http_content(
                        "file://" + os.path.join(showcase_utils.wgt_deployer.root_dir, xhtml.url), user=request.user
                    )

            except Exception, e:
                # FIXME: Send the error or use the cached original code?
                msg = _("XHTML code is not accessible: %(errorMsg)s") % {"errorMsg": e.message}
                return HttpResponse(get_xml_error_response(msg), mimetype="application/xml; charset=UTF-8")
Пример #12
0
    def read(self, request, vendor, name, version):

        operator = get_object_or_404(CatalogueResource,
                                     type=2,
                                     vendor=vendor,
                                     short_name=name,
                                     version=version)
        # For now, all operators are freely accessible/distributable
        #if not operator.is_available_for(request.user):
        #    return HttpResponseForbidden()

        mode = request.GET.get('mode', 'classic')

        key = get_operator_cache_key(operator, get_current_domain(request),
                                     mode)
        cached_response = cache.get(key)
        if cached_response is None:
            options = json.loads(operator.json_description)
            js_files = options['js_files']

            base_url = operator.template_uri
            if not base_url.startswith(('http://', 'https://')):
                base_url = get_absolute_reverse_url('wirecloud.showcase_media',
                                                    kwargs={
                                                        'vendor':
                                                        operator.vendor,
                                                        'name':
                                                        operator.short_name,
                                                        'version':
                                                        operator.version,
                                                        'file_path':
                                                        operator.template_uri
                                                    },
                                                    request=request)

            xhtml = generate_xhtml_operator_code(
                js_files, base_url, request,
                process_requirements(options['requirements']), mode)
            cache_timeout = 31536000  # 1 year
            cached_response = CacheableData(
                xhtml,
                timeout=cache_timeout,
                content_type='application/xhtml+xml; charset=UTF-8')

            cache.set(key, cached_response, cache_timeout)

        return cached_response.get_response()
Пример #13
0
    def read(self, request, vendor, name, version):

        resource = get_object_or_404(CatalogueResource.objects.select_related('widget__xhtml'), vendor=vendor, short_name=name, version=version)
        if not resource.is_available_for(request.user):
            raise Http403()

        if resource.resource_type() != 'widget':
            raise Http404()

        widget_info = json.loads(resource.json_description)

        # check if the xhtml code has been cached
        if widget_info['code_cacheable'] is True:

            cache_key = resource.widget.xhtml.get_cache_key(get_current_domain(request))
            cache_entry = cache.get(cache_key)
            if cache_entry is not None:
                response = HttpResponse(cache_entry['code'], mimetype=cache_entry['mimetype'])
                patch_cache_headers(response, cache_entry['timestamp'], cache_entry['timeout'])
                return response

        # process xhtml
        xhtml = resource.widget.xhtml
        content_type = widget_info.get('code_content_type', 'text/html')
        charset = widget_info.get('code_charset', 'utf-8')

        force_base = False
        base_url = xhtml.url
        if not base_url.startswith(('http://', 'https://')):
            base_url = get_absolute_reverse_url('wirecloud_showcase.media', args=(base_url.split('/', 4)), request=request)
            force_base = True

        code = xhtml.code
        if not xhtml.cacheable or code == '':
            try:
                if xhtml.url.startswith(('http://', 'https://')):
                    code = downloader.download_http_content(urljoin(base_url, xhtml.url), user=request.user)
                else:
                    code = downloader.download_http_content('file://' + os.path.join(showcase_utils.wgt_deployer.root_dir, url2pathname(xhtml.url)), user=request.user)

            except Exception, e:
                msg = _("XHTML code is not accessible: %(errorMsg)s") % {'errorMsg': e.message}
                return build_error_response(request, 502, msg)
Пример #14
0
def get_widget_api_files(request):

    from wirecloud.platform.core.plugins import get_version_hash

    key = 'widget_api_files/%s?v=%s' % (get_current_domain(request), get_version_hash())
    widget_api_files = cache.get(key)

    if widget_api_files is None or settings.DEBUG is True:
        code = '''{% load compress %}{% load static from staticfiles %}{% compress js %}
        <script type="text/javascript" src="{% static "js/WirecloudAPI/WirecloudAPIBootstrap.js" %}"></script>
        <script type="text/javascript" src="{% static "js/WirecloudAPI/WirecloudWidgetAPI.js" %}"></script>
        <script type="text/javascript" src="{% static "js/WirecloudAPI/WirecloudAPICommon.js" %}"></script>
        {% endcompress %}'''

        result = Template(code).render(Context({}))
        doc = etree.parse(BytesIO(('<files>' + result + '</files>').encode('utf-8')), etree.XMLParser())

        files = [script.get('src') for script in doc.getroot()]
        files.reverse()
        widget_api_files = tuple([get_absolute_static_url(file, request=request, versioned=True) for file in files])
        cache.set(key, widget_api_files)

    return list(widget_api_files)
Пример #15
0
    def do_request(self, request, url, method, request_data):

        url = iri_to_uri(url)

        request_data.update({
            "method": method,
            "url": url,
            "original-request": request,
        })

        request_data.setdefault("data", None)
        request_data.setdefault("headers", {})
        request_data.setdefault("cookies", SimpleCookie())
        request_data.setdefault("user", request.user)

        # Request creation
        proto, host, cgi, param, query = urlparse(url)[:5]

        # Build the Via header
        protocolVersion = self.protocolRE.match(request.META['SERVER_PROTOCOL'])
        if protocolVersion is not None:
            protocolVersion = protocolVersion.group(1)
        else:
            protocolVersion = '1.1'

        via_header = "%s %s (Wirecloud-python-Proxy/1.1)" % (protocolVersion, get_current_domain(request))
        if 'via' in request_data['headers']:
            request_data['headers']['via'] += ', ' + via_header
        else:
            request_data['headers']['via'] = via_header

        # XFF headers
        if 'x-forwarded-for' in request_data['headers']:
            request_data['headers']['x-forwarded-for'] += ', ' + request.META['REMOTE_ADDR']
        else:
            request_data['headers']['x-forwarded-for'] = request.META['REMOTE_ADDR']

        # Pass proxy processors to the new request
        try:
            for processor in get_request_proxy_processors():
                processor.process_request(request_data)
        except ValidationError as e:
            return e.get_response(request)

        # Cookies
        cookie_header_content = ', '.join([request_data['cookies'][key].OutputString() for key in request_data['cookies']])
        if cookie_header_content != '':
            request_data['headers']['Cookie'] = cookie_header_content

        # Seems that Django or WSGI provides default values for the
        # Content-Length and Content-Type headers, so we are not able to detect
        # if the request provided them :(
        if str(request_data['headers'].get('content-length', '0')).strip() == '0':
            request_data['data'] = None
            if 'content-type' in request_data['headers']:
                del request_data['headers']['content-type']

        # Open the request
        try:
            res = requests.request(request_data['method'], request_data['url'], headers=request_data['headers'], data=request_data['data'], stream=True, verify=getattr(settings, 'WIRECLOUD_HTTPS_VERIFY', True))
        except requests.exceptions.Timeout as e:
            return build_error_response(request, 504, _('Gateway Timeout'), details=six.text_type(e))
        except requests.exceptions.SSLError as e:
            return build_error_response(request, 502, _('SSL Error'), details=six.text_type(e))
        except (requests.exceptions.ConnectionError, requests.exceptions.HTTPError, requests.exceptions.TooManyRedirects) as e:
            return build_error_response(request, 504, _('Connection Error'), details=six.text_type(e))

        # Build a Django response
        response = StreamingHttpResponse(res.raw.stream(4096, decode_content=False), status=res.status_code, reason=res.reason)

        # Add all the headers received from the response
        for header in res.headers:

            header_lower = header.lower()
            if header_lower == 'set-cookie':

                for cookie in res.cookies:
                    response.set_cookie(cookie.name, value=cookie.value, expires=cookie.expires, path=cookie.path)

            elif header_lower == 'via':

                via_header = via_header + ', ' + res.headers[header]

            elif is_valid_response_header(header_lower):
                response[header] = res.headers[header]

        # Pass proxy processors to the response
        for processor in get_response_proxy_processors():
            response = processor.process_response(request_data, response)

        response['Via'] = via_header

        return response
Пример #16
0
    def do_request(self, request, url, method, workspace):

        url = iri_to_uri(url)

        request_data = {
            "method": method,
            "url": url,
            "data": None,
            "headers": {},
            "cookies": SimpleCookie(),
            "user": request.user,
            "workspace": workspace,
            "original-request": request,
        }

        # Request creation
        proto, host, cgi, param, query = urlparse(url)[:5]

        # Extract headers from META
        if 'HTTP_TRANSFER_ENCODING' in request.META:
            return build_error_response(
                request, 422,
                "Wirecloud doesn't support requests using the Transfer-Encoding header"
            )

        for header in request.META.items():
            header_name = header[0].lower()
            if header_name == 'content_type' and header[1]:
                request_data['headers']["content-type"] = header[1]

            elif header_name == 'content_length' and header[1]:
                # Only take into account request body if the request has a
                # Content-Length header (we don't support chunked requests)
                request_data['data'] = request
                request_data['headers']['content-length'] = header[1]
                request_data['data'].len = int(header[1])

            elif header_name == 'cookie' or header_name == 'http_cookie':

                cookie_parser = SimpleCookie(str(header[1]))

                del cookie_parser[str(settings.SESSION_COOKIE_NAME)]

                if str(settings.CSRF_COOKIE_NAME) in cookie_parser:
                    del cookie_parser[str(settings.CSRF_COOKIE_NAME)]

                request_data['cookies'].update(cookie_parser)

            elif self.http_headerRE.match(
                    header_name
            ) and not header_name in self.blacklisted_http_headers:

                fixed_name = header_name.replace("http_", "",
                                                 1).replace('_', '-')
                request_data['headers'][fixed_name] = header[1]

        # Build the Via header
        protocolVersion = self.protocolRE.match(
            request.META['SERVER_PROTOCOL'])
        if protocolVersion is not None:
            protocolVersion = protocolVersion.group(1)
        else:
            protocolVersion = '1.1'

        via_header = "%s %s (Wirecloud-python-Proxy/1.1)" % (
            protocolVersion, get_current_domain(request))
        if 'via' in request_data['headers']:
            request_data['headers']['via'] += ', ' + via_header
        else:
            request_data['headers']['via'] = via_header

        # XFF headers
        if 'x-forwarded-for' in request_data['headers']:
            request_data['headers'][
                'x-forwarded-for'] += ', ' + request.META['REMOTE_ADDR']
        else:
            request_data['headers']['x-forwarded-for'] = request.META[
                'REMOTE_ADDR']

        request_data['headers']['x-forwarded-host'] = host
        if 'x-forwarded-server' in request_data['headers']:
            del request_data['headers']['x-forwarded-server']

        # Pass proxy processors to the new request
        try:
            for processor in get_request_proxy_processors():
                processor.process_request(request_data)
        except ValidationError as e:
            return e.get_response(request)

        # Cookies
        cookie_header_content = ', '.join([
            cookie_parser[key].OutputString()
            for key in request_data['cookies']
        ])
        if cookie_header_content != '':
            request_data['headers']['Cookie'] = cookie_header_content

        # Open the request
        try:
            res = requests.request(request_data['method'],
                                   request_data['url'],
                                   headers=request_data['headers'],
                                   data=request_data['data'],
                                   stream=True,
                                   verify=getattr(settings,
                                                  'WIRECLOUD_HTTPS_VERIFY',
                                                  True))
        except requests.exceptions.Timeout as e:
            return build_error_response(request,
                                        504,
                                        _('Gateway Timeout'),
                                        details=six.text_type(e))
        except requests.exceptions.SSLError as e:
            return build_error_response(request,
                                        502,
                                        _('SSL Error'),
                                        details=six.text_type(e))
        except (requests.exceptions.ConnectionError,
                requests.exceptions.HTTPError,
                requests.exceptions.TooManyRedirects) as e:
            return build_error_response(request,
                                        504,
                                        _('Connection Error'),
                                        details=six.text_type(e))

        # Build a Django response
        response = StreamingHttpResponse(res.raw.stream(4096,
                                                        decode_content=False),
                                         status=res.status_code)
        if 'reason_phrase' in response:  # pragma: no cover
            # Currently only django 1.6+ supports custom reason phrases
            response.reason_phrase = res.reason_phrase

        # Add all the headers received from the response
        for header in res.headers:

            header_lower = header.lower()
            if header_lower == 'set-cookie':

                for cookie in res.cookies:
                    response.set_cookie(cookie.name,
                                        value=cookie.value,
                                        expires=cookie.expires,
                                        path=cookie.path)

            elif header_lower == 'via':

                via_header = via_header + ', ' + res.headers[header]

            elif is_valid_response_header(header_lower):
                response[header] = res.headers[header]

        # Pass proxy processors to the response
        for processor in get_response_proxy_processors():
            response = processor.process_response(request_data, response)

        response['Via'] = via_header

        return response
Пример #17
0
    def do_request(self, request, url, method, workspace):

        url = iri_to_uri(url)

        request_data = {
            "method": method,
            "url": url,
            "data": None,
            "headers": {},
            "cookies": SimpleCookie(),
            "user": request.user,
            "workspace": workspace,
            "original-request": request,
        }

        # Request creation
        proto, host, cgi, param, query = urlparse(url)[:5]

        # Extract headers from META
        if 'HTTP_TRANSFER_ENCODING' in request.META:
            return build_error_response(request, 500, "Wirecloud doesn't support requests using Transfer-Encodings")

        for header in request.META.items():
            header_name = header[0].lower()
            if header_name == 'content_type' and header[1]:
                request_data['headers']["content-type"] = header[1]

            elif header_name == 'content_length' and header[1]:
                # Only take into account request body if the request has a
                # Content-Length header (we don't support chunked requests)
                request_data['data'] = request
                request_data['headers']['content-length'] = header[1]
                request_data['data'].len = int(header[1])

            elif header_name == 'cookie' or header_name == 'http_cookie':

                cookie_parser = SimpleCookie(str(header[1]))

                del cookie_parser[str(settings.SESSION_COOKIE_NAME)]

                if str(settings.CSRF_COOKIE_NAME) in cookie_parser:
                    del cookie_parser[str(settings.CSRF_COOKIE_NAME)]

                request_data['cookies'].update(cookie_parser)

            elif self.http_headerRE.match(header_name) and not header_name in self.blacklisted_http_headers:

                fixed_name = header_name.replace("http_", "", 1).replace('_', '-')
                request_data['headers'][fixed_name] = header[1]

        # Build the Via header
        protocolVersion = self.protocolRE.match(request.META['SERVER_PROTOCOL'])
        if protocolVersion is not None:
            protocolVersion = protocolVersion.group(1)
        else:
            protocolVersion = '1.1'

        via_header = "%s %s (Wirecloud-python-Proxy/1.1)" % (protocolVersion, get_current_domain(request))
        if 'via' in request_data['headers']:
            request_data['headers']['via'] += ', ' + via_header
        else:
            request_data['headers']['via'] = via_header

        # XFF headers
        if 'x-forwarded-for' in request_data['headers']:
            request_data['headers']['x-forwarded-for'] += ', ' + request.META['REMOTE_ADDR']
        else:
            request_data['headers']['x-forwarded-for'] = request.META['REMOTE_ADDR']

        request_data['headers']['x-forwarded-host'] = host
        if 'x-forwarded-server' in request_data['headers']:
            del request_data['headers']['x-forwarded-server']

        # Pass proxy processors to the new request
        try:
            for processor in get_request_proxy_processors():
                processor.process_request(request_data)
        except ValidationError as e:
            return e.get_response(request)

        # Cookies
        cookie_header_content = ', '.join([cookie_parser[key].OutputString() for key in request_data['cookies']])
        if cookie_header_content != '':
            request_data['headers']['Cookie'] = cookie_header_content

        # Open the request
        try:
            res = requests.request(request_data['method'], request_data['url'], headers=request_data['headers'], data=request_data['data'], stream=True, verify=getattr(settings, 'WIRECLOUD_HTTPS_VERIFY', True))
        except requests.exceptions.Timeout as e:
            return build_error_response(request, 504, _('Gateway Timeout'), details=six.text_type(e))
        except requests.exceptions.SSLError as e:
            return build_error_response(request, 502, _('SSL Error'), details=six.text_type(e))
        except (requests.exceptions.ConnectionError, requests.exceptions.HTTPError, requests.exceptions.TooManyRedirects) as e:
            return build_error_response(request, 504, _('Connection Error'), details=six.text_type(e))

        # Build a Django response
        response = StreamingHttpResponse(res.raw.stream(4096, decode_content=False), status=res.status_code)
        if 'reason_phrase' in response:  # pragma: no cover
            # Currently only django 1.6+ supports custom reason phrases
            response.reason_phrase = res.reason_phrase

        # Add all the headers received from the response
        for header in res.headers:

            header_lower = header.lower()
            if header_lower == 'set-cookie':

                for cookie in res.cookies:
                    response.set_cookie(cookie.name, value=cookie.value, expires=cookie.expires, path=cookie.path)

            elif header_lower == 'via':

                via_header = via_header + ', ' + res.headers[header]

            elif is_valid_response_header(header_lower):
                response[header] = res.headers[header]

        # Pass proxy processors to the response
        for processor in get_response_proxy_processors():
            response = processor.process_response(request_data, response)

        response['Via'] = via_header

        return response
Пример #18
0
    def do_request(self, request, url, method):

        url = iri_to_uri(url)

        request_data = {
            "method": method,
            "url": url,
            "data": None,
            "headers": {},
            "cookies": Cookie.SimpleCookie(),
            "user": request.user,
            "original-request": request,
        }

        # Request creation
        proto, host, cgi, param, query = urlparse.urlparse(url)[:5]

        # Extract headers from META
        if 'HTTP_TRANSFER_ENCODING' in request.META:
            return build_error_response(request, 500, "Wirecloud doesn't support requests using Transfer-Encodings")

        for header in request.META.items():
            header_name = header[0].lower()
            if header_name == 'content_type' and header[1]:
                request_data['headers']["content-type"] = header[1]

            elif header_name == 'content_length' and header[1]:
                # Only take into account request body if the request has a
                # Content-Length header (we don't support chunked requests)
                request_data['data'] = request

                # It's better not propagate the Content-Length header as
                # request processors may change final data length. In addition
                # to this, the requests modules ignores the Content-Length
                # header and tries to obtain data length directly from the
                # data parameter. Therefore, providing this value in the len
                # attribute seems to be the best option
                request_data['data'].len = int(header[1])

            elif header_name == 'cookie' or header_name == 'http_cookie':

                cookie_parser = Cookie.SimpleCookie(str(header[1]))

                del cookie_parser[settings.SESSION_COOKIE_NAME]

                if settings.CSRF_COOKIE_NAME in cookie_parser:
                    del cookie_parser[settings.CSRF_COOKIE_NAME]

                request_data['cookies'].update(cookie_parser)

            elif self.http_headerRE.match(header_name) and not header_name in self.blacklisted_http_headers:

                fixed_name = header_name.replace("http_", "", 1).replace('_', '-')
                request_data['headers'][fixed_name] = header[1]

        # Build the Via header
        protocolVersion = self.protocolRE.match(request.META['SERVER_PROTOCOL'])
        if protocolVersion is not None:
            protocolVersion = protocolVersion.group(1)
        else:
            protocolVersion = '1.1'

        via_header = "%s %s (Wirecloud-python-Proxy/1.1)" % (protocolVersion, get_current_domain(request))
        if 'via' in request_data['headers']:
            request_data['headers']['via'] += ', ' + via_header
        else:
            request_data['headers']['via'] = via_header

        # XFF headers
        if 'x-forwarded-for' in request_data['headers']:
            request_data['headers']['x-forwarded-for'] += ', ' + request.META['REMOTE_ADDR']
        else:
            request_data['headers']['x-forwarded-for'] = request.META['REMOTE_ADDR']

        request_data['headers']['x-forwarded-host'] = host
        if 'x-forwarded-server' in request_data['headers']:
            del request_data['headers']['x-forwarded-server']

        # Pass proxy processors to the new request
        try:
            for processor in get_request_proxy_processors():
                processor.process_request(request_data)
        except ValidationError as e:
            return e.get_response()

        # Cookies
        cookie_header_content = ', '.join([cookie_parser[key].OutputString() for key in request_data['cookies']])
        if cookie_header_content != '':
            request_data['headers']['Cookie'] = cookie_header_content

        # Open the request
        try:
            res = requests.request(request_data['method'], request_data['url'], headers=request_data['headers'], data=request_data['data'], stream=True)
        except requests.exceptions.HTTPError:
            return HttpResponse(status=504)
        except requests.exceptions.ConnectionError:
            return HttpResponse(status=502)

        # Build a Django response
        response = StreamingHttpResponse(res.raw.stream(4096, decode_content=False))

        # Set status code to the response
        response.status_code = res.status_code

        # Add all the headers received from the response
        for header in res.headers:

            header_lower = header.lower()
            if header_lower == 'set-cookie':

                for cookie in res.cookies:
                    response.set_cookie(cookie.name, value=cookie.value, expires=cookie.expires, path=cookie.path)

            elif header_lower == 'via':

                via_header = via_header + ', ' + res.headers[header]

            elif is_valid_response_header(header_lower):
                response[header] = res.headers[header]

        # Pass proxy processors to the response
        for processor in get_response_proxy_processors():
            response = processor.process_response(request_data, response)

        response['Via'] = via_header

        return response
Пример #19
0
def process_widget_code(request, resource):

    mode = request.GET.get('mode', 'classic')
    theme = request.GET.get('theme', get_active_theme_name())
    widget_info = json.loads(resource.json_description)

    # check if the xhtml code has been cached
    if widget_info['contents']['cacheable'] is True:

        cache_key = resource.widget.xhtml.get_cache_key(get_current_domain(request), mode, theme)
        cache_entry = cache.get(cache_key)
        if cache_entry is not None:
            response = HttpResponse(cache_entry['code'], content_type=cache_entry['content_type'])
            patch_cache_headers(response, cache_entry['timestamp'], cache_entry['timeout'])
            return response

    # process xhtml
    xhtml = resource.widget.xhtml
    content_type = widget_info['contents'].get('contenttype', 'text/html')
    charset = widget_info['contents'].get('charset', 'utf-8')

    code = xhtml.code
    if not xhtml.cacheable or code == '':
        try:
            code = download_local_file(os.path.join(showcase_utils.wgt_deployer.root_dir, url2pathname(xhtml.url)))

        except Exception as e:
            if isinstance(e, IOError) and e.errno == errno.ENOENT:
                return build_response(request, 404, {'error_msg': _("Widget code not found"), 'details': "%s" % e}, WIDGET_ERROR_FORMATTERS)
            else:
                return build_response(request, 500, {'error_msg': _("Error reading widget code"), 'details': "%s" % e}, WIDGET_ERROR_FORMATTERS)
    else:
        # Code contents comes as unicode from persistence, we need bytes
        code = code.encode(charset)

    if xhtml.cacheable and (xhtml.code == '' or xhtml.code_timestamp is None):
        try:
            xhtml.code = code.decode(charset)
        except UnicodeDecodeError:
            msg = _('Widget code was not encoded using the specified charset (%(charset)s as stated in the widget description file).') % {'charset': charset}
            return build_response(request, 502, {'error_msg': msg}, WIDGET_ERROR_FORMATTERS)

        xhtml.code_timestamp = time.time() * 1000
        xhtml.save()

    try:
        code = fix_widget_code(code, content_type, request, charset, xhtml.use_platform_style, process_requirements(widget_info['requirements']), mode, theme)
    except UnicodeDecodeError:
        msg = _('Widget code was not encoded using the specified charset (%(charset)s as stated in the widget description file).') % {'charset': charset}
        return build_response(request, 502, {'error_msg': msg}, WIDGET_ERROR_FORMATTERS)
    except Exception as e:
        msg = _('Error processing widget code')
        return build_response(request, 502, {'error_msg': msg, 'details':"%s" % e}, WIDGET_ERROR_FORMATTERS)

    if xhtml.cacheable:
        cache_timeout = 31536000  # 1 year
        cache_entry = {
            'code': code,
            'content_type': '%s; charset=%s' % (content_type, charset),
            'timestamp': xhtml.code_timestamp,
            'timeout': cache_timeout,
        }
        cache.set(cache_key, cache_entry, cache_timeout)
    else:
        cache_timeout = 0

    response = HttpResponse(code, content_type='%s; charset=%s' % (content_type, charset))
    patch_cache_headers(response, xhtml.code_timestamp, cache_timeout)
    return response
Пример #20
0
    def read(self, request, vendor, name, version):

        resource = get_object_or_404(CatalogueResource.objects.select_related('widget__xhtml'), vendor=vendor, short_name=name, version=version)
        # For now, all widgets are freely accessible/distributable
        #if not resource.is_available_for(request.user):
        #    return build_error_response(request, 403, "Forbidden")

        if resource.resource_type() != 'widget':
            raise Http404()

        mode = request.GET.get('mode', 'classic')
        widget_info = json.loads(resource.json_description)

        # check if the xhtml code has been cached
        if widget_info['contents']['cacheable'] is True:

            cache_key = resource.widget.xhtml.get_cache_key(get_current_domain(request), mode)
            cache_entry = cache.get(cache_key)
            if cache_entry is not None:
                response = HttpResponse(cache_entry['code'], content_type=cache_entry['content_type'])
                patch_cache_headers(response, cache_entry['timestamp'], cache_entry['timeout'])
                return response

        # process xhtml
        xhtml = resource.widget.xhtml
        content_type = widget_info['contents'].get('contenttype', 'text/html')
        charset = widget_info['contents'].get('charset', 'utf-8')

        force_base = False
        base_url = xhtml.url
        if not base_url.startswith(('http://', 'https://')):
            # Newer versions of Django urlencode urls created using reverse
            # Fix double encoding
            base_url = urlunquote(base_url)
            base_url = get_absolute_reverse_url('wirecloud.showcase_media', args=(base_url.split('/', 3)), request=request)
            force_base = True

        code = xhtml.code
        if not xhtml.cacheable or code == '':
            try:
                if xhtml.url.startswith(('http://', 'https://')):
                    code = download_http_content(urljoin(base_url, xhtml.url), user=request.user)
                else:
                    code = download_local_file(os.path.join(showcase_utils.wgt_deployer.root_dir, url2pathname(xhtml.url)))

            except Exception as e:
                return build_response(request, 502, {'error_msg': _("(X)HTML code is not accessible"), 'details': "%s" % e}, WIDGET_ERROR_FORMATTERS)
        else:
            # Code contents comes as unicode from persistence, we need bytes
            code = code.encode(charset)

        if xhtml.cacheable and (xhtml.code == '' or xhtml.code_timestamp is None):
            try:
                xhtml.code = code.decode(charset)
            except UnicodeDecodeError:
                msg = _('Widget code was not encoded using the specified charset (%(charset)s as stated in the widget description file).') % {'charset': charset}
                return build_response(request, 502, {'error_msg': msg}, WIDGET_ERROR_FORMATTERS)

            xhtml.code_timestamp = time.time() * 1000
            xhtml.save()
        elif not xhtml.cacheable and xhtml.code != '':
            xhtml.code = ''
            xhtml.code_timestamp = None
            xhtml.save()

        try:
            code = fix_widget_code(code, base_url, content_type, request, charset, xhtml.use_platform_style, process_requirements(widget_info['requirements']), force_base, mode)
        except UnicodeDecodeError:
            msg = _('Widget code was not encoded using the specified charset (%(charset)s as stated in the widget description file).') % {'charset': charset}
            return build_response(request, 502, {'error_msg': msg}, WIDGET_ERROR_FORMATTERS)
        except Exception as e:
            msg = _('Error processing widget code')
            return build_response(request, 502, {'error_msg': msg, 'details':"%s" % e}, WIDGET_ERROR_FORMATTERS)

        if xhtml.cacheable:
            cache_timeout = 31536000  # 1 year
            cache_entry = {
                'code': code,
                'content_type': '%s; charset=%s' % (content_type, charset),
                'timestamp': xhtml.code_timestamp,
                'timeout': cache_timeout,
            }
            cache.set(cache_key, cache_entry, cache_timeout)
        else:
            cache_timeout = 0

        response = HttpResponse(code, content_type='%s; charset=%s' % (content_type, charset))
        patch_cache_headers(response, xhtml.code_timestamp, cache_timeout)
        return response
Пример #21
0
def process_widget_code(request, resource):

    mode = request.GET.get('mode', 'classic')
    theme = request.GET.get('theme', get_active_theme_name())
    widget_info = json.loads(resource.json_description)

    # check if the xhtml code has been cached
    if widget_info['contents']['cacheable'] is True:

        cache_key = resource.widget.xhtml.get_cache_key(
            get_current_domain(request), mode, theme)
        cache_entry = cache.get(cache_key)
        if cache_entry is not None:
            response = HttpResponse(cache_entry['code'],
                                    content_type=cache_entry['content_type'])
            patch_cache_headers(response, cache_entry['timestamp'],
                                cache_entry['timeout'])
            return response

    # process xhtml
    xhtml = resource.widget.xhtml
    content_type = widget_info['contents'].get('contenttype', 'text/html')
    charset = widget_info['contents'].get('charset', 'utf-8')

    code = xhtml.code
    if not xhtml.cacheable or code == '':
        try:
            code = download_local_file(
                os.path.join(showcase_utils.wgt_deployer.root_dir,
                             url2pathname(xhtml.url)))

        except Exception as e:
            if isinstance(e, IOError) and e.errno == errno.ENOENT:
                return build_response(request, 404, {
                    'error_msg': _("Widget code not found"),
                    'details': "%s" % e
                }, WIDGET_ERROR_FORMATTERS)
            else:
                return build_response(
                    request, 500, {
                        'error_msg': _("Error reading widget code"),
                        'details': "%s" % e
                    }, WIDGET_ERROR_FORMATTERS)
    else:
        # Code contents comes as unicode from persistence, we need bytes
        code = code.encode(charset)

    if xhtml.cacheable and (xhtml.code == '' or xhtml.code_timestamp is None):
        try:
            xhtml.code = code.decode(charset)
        except UnicodeDecodeError:
            msg = _(
                'Widget code was not encoded using the specified charset (%(charset)s as stated in the widget description file).'
            ) % {
                'charset': charset
            }
            return build_response(request, 502, {'error_msg': msg},
                                  WIDGET_ERROR_FORMATTERS)

        xhtml.code_timestamp = time.time() * 1000
        xhtml.save()

    try:
        code = fix_widget_code(
            code, content_type, request, charset, xhtml.use_platform_style,
            process_requirements(widget_info['requirements']), mode, theme)
    except UnicodeDecodeError:
        msg = _(
            'Widget code was not encoded using the specified charset (%(charset)s as stated in the widget description file).'
        ) % {
            'charset': charset
        }
        return build_response(request, 502, {'error_msg': msg},
                              WIDGET_ERROR_FORMATTERS)
    except Exception as e:
        msg = _('Error processing widget code')
        return build_response(request, 502, {
            'error_msg': msg,
            'details': "%s" % e
        }, WIDGET_ERROR_FORMATTERS)

    if xhtml.cacheable:
        cache_timeout = 31536000  # 1 year
        cache_entry = {
            'code': code,
            'content_type': '%s; charset=%s' % (content_type, charset),
            'timestamp': xhtml.code_timestamp,
            'timeout': cache_timeout,
        }
        cache.set(cache_key, cache_entry, cache_timeout)
    else:
        cache_timeout = 0

    response = HttpResponse(code,
                            content_type='%s; charset=%s' %
                            (content_type, charset))
    patch_cache_headers(response, xhtml.code_timestamp, cache_timeout)
    return response
Пример #22
0
    def read(self, request, vendor, name, version):

        resource = get_object_or_404(CatalogueResource.objects.select_related('widget__xhtml'), vendor=vendor, short_name=name, version=version)
        # For now, all widgets are freely accessible/distributable
        #if not resource.is_available_for(request.user):
        #    return build_error_response(request, 403, "Forbidden")

        if resource.resource_type() != 'widget':
            raise Http404()

        mode = request.GET.get('mode', 'classic')
        widget_info = json.loads(resource.json_description)

        # check if the xhtml code has been cached
        if widget_info['contents']['cacheable'] is True:

            cache_key = resource.widget.xhtml.get_cache_key(get_current_domain(request), mode)
            cache_entry = cache.get(cache_key)
            if cache_entry is not None:
                response = HttpResponse(cache_entry['code'], content_type=cache_entry['content_type'])
                patch_cache_headers(response, cache_entry['timestamp'], cache_entry['timeout'])
                return response

        # process xhtml
        xhtml = resource.widget.xhtml
        content_type = widget_info['contents'].get('contenttype', 'text/html')
        charset = widget_info['contents'].get('charset', 'utf-8')

        force_base = False
        base_url = xhtml.url
        if not base_url.startswith(('http://', 'https://')):
            # Newer versions of Django urlencode urls created using reverse
            # Fix double encoding
            base_url = urlunquote(base_url)
            base_url = get_absolute_reverse_url('wirecloud.showcase_media', args=(base_url.split('/', 4)), request=request)
            force_base = True

        code = xhtml.code
        if not xhtml.cacheable or code == '':
            try:
                if xhtml.url.startswith(('http://', 'https://')):
                    code = download_http_content(urljoin(base_url, xhtml.url), user=request.user)
                else:
                    code = download_local_file(os.path.join(showcase_utils.wgt_deployer.root_dir, url2pathname(xhtml.url)))

            except Exception as e:
                return build_response(request, 502, {'error_msg': _("(X)HTML code is not accessible"), 'details': "%s" % e}, WIDGET_ERROR_FORMATTERS)
        else:
            # Code contents comes as unicode from persistence, we need bytes
            code = code.encode(charset)

        if xhtml.cacheable and (xhtml.code == '' or xhtml.code_timestamp is None):
            try:
                xhtml.code = code.decode(charset)
            except UnicodeDecodeError:
                msg = _('Widget code was not encoded using the specified charset (%(charset)s as stated in the widget description file).') % {'charset': charset}
                return build_response(request, 502, {'error_msg': msg}, WIDGET_ERROR_FORMATTERS)

            xhtml.code_timestamp = time.time() * 1000
            xhtml.save()
        elif not xhtml.cacheable and xhtml.code != '':
            xhtml.code = ''
            xhtml.code_timestamp = None
            xhtml.save()

        try:
            code = fix_widget_code(code, base_url, content_type, request, charset, xhtml.use_platform_style, process_requirements(widget_info['requirements']), force_base, mode)
        except UnicodeDecodeError:
            msg = _('Widget code was not encoded using the specified charset (%(charset)s as stated in the widget description file).') % {'charset': charset}
            return build_response(request, 502, {'error_msg': msg}, WIDGET_ERROR_FORMATTERS)
        except Exception as e:
            msg = _('Error processing widget code')
            return build_response(request, 502, {'error_msg': msg, 'details':"%s" % e}, WIDGET_ERROR_FORMATTERS)

        if xhtml.cacheable:
            cache_timeout = 31536000  # 1 year
            cache_entry = {
                'code': code,
                'content_type': '%s; charset=%s' % (content_type, charset),
                'timestamp': xhtml.code_timestamp,
                'timeout': cache_timeout,
            }
            cache.set(cache_key, cache_entry, cache_timeout)
        else:
            cache_timeout = 0

        response = HttpResponse(code, content_type='%s; charset=%s' % (content_type, charset))
        patch_cache_headers(response, xhtml.code_timestamp, cache_timeout)
        return response
Пример #23
0
    def do_request(self, request, url, method, request_data):

        url = iri_to_uri(url)

        request_data.update({
            "method": method,
            "url": url,
            "original-request": request,
        })

        request_data.setdefault("data", None)
        request_data.setdefault("headers", {})
        request_data.setdefault("cookies", SimpleCookie())
        request_data.setdefault("user", request.user)

        # Request creation
        proto, host, cgi, param, query = urlparse(url)[:5]

        # Build the Via header
        protocolVersion = self.protocolRE.match(
            request.META['SERVER_PROTOCOL'])
        if protocolVersion is not None:
            protocolVersion = protocolVersion.group(1)
        else:
            protocolVersion = '1.1'

        via_header = "%s %s (Wirecloud-python-Proxy/1.1)" % (
            protocolVersion, get_current_domain(request))
        if 'via' in request_data['headers']:
            request_data['headers']['via'] += ', ' + via_header
        else:
            request_data['headers']['via'] = via_header

        # XFF headers
        if 'x-forwarded-for' in request_data['headers']:
            request_data['headers'][
                'x-forwarded-for'] += ', ' + request.META['REMOTE_ADDR']
        else:
            request_data['headers']['x-forwarded-for'] = request.META[
                'REMOTE_ADDR']

        # Pass proxy processors to the new request
        try:
            for processor in get_request_proxy_processors():
                processor.process_request(request_data)
        except ValidationError as e:
            return e.get_response(request)

        # Cookies
        cookie_header_content = ', '.join([
            request_data['cookies'][key].OutputString()
            for key in request_data['cookies']
        ])
        if cookie_header_content != '':
            request_data['headers']['Cookie'] = cookie_header_content

        # Seems that Django or WSGI provides default values for the
        # Content-Length and Content-Type headers, so we are not able to detect
        # if the request provided them :(
        if str(request_data['headers'].get('content-length',
                                           '0')).strip() == '0':
            request_data['data'] = None
            if 'content-type' in request_data['headers']:
                del request_data['headers']['content-type']

        # Open the request
        try:
            res = requests.request(request_data['method'],
                                   request_data['url'],
                                   headers=request_data['headers'],
                                   data=request_data['data'],
                                   stream=True,
                                   verify=getattr(settings,
                                                  'WIRECLOUD_HTTPS_VERIFY',
                                                  True))
        except requests.exceptions.Timeout as e:
            return build_error_response(request,
                                        504,
                                        _('Gateway Timeout'),
                                        details=str(e))
        except requests.exceptions.SSLError as e:
            return build_error_response(request,
                                        502,
                                        _('SSL Error'),
                                        details=str(e))
        except (requests.exceptions.ConnectionError,
                requests.exceptions.HTTPError,
                requests.exceptions.TooManyRedirects) as e:
            return build_error_response(request,
                                        504,
                                        _('Connection Error'),
                                        details=str(e))

        # Build a Django response
        response = StreamingHttpResponse(res.raw.stream(4096,
                                                        decode_content=False),
                                         status=res.status_code,
                                         reason=res.reason)

        # Add all the headers received from the response
        for header in res.headers:

            header_lower = header.lower()
            if header_lower == 'set-cookie':

                for cookie in res.cookies:
                    response.set_cookie(cookie.name,
                                        value=cookie.value,
                                        expires=cookie.expires,
                                        path=cookie.path)

            elif header_lower == 'via':

                via_header = via_header + ', ' + res.headers[header]

            elif is_valid_response_header(header_lower):
                response[header] = res.headers[header]

        # Pass proxy processors to the response
        for processor in get_response_proxy_processors():
            response = processor.process_response(request_data, response)

        response['Via'] = via_header

        return response