Example #1
0
 def testSendNoContent(self):
     request = UtilTestCase.RequestMockup()
     util.send_no_content(request)
     self.assertEqual(request.response.status, 204)
     self.assertEqual(request.response.headers['Content-Type'],
                      'application/json')
     self.assertEqual(request.response.out.msg, '')
Example #2
0
    def get(self):
        """Handles an HTTP GET request.

        The URL must be in the following format:
        'http://mlab-ns.appspot.com/tool-name?query_string',
        where tool-name is one of the tools running on M-Lab.
        For more information about the URL and the supported arguments
        in the query string, see the design doc at http://goo.gl/48S22.
        """
        query = lookup_query.LookupQuery()
        query.initialize_from_http_request(self.request)

        # Check right away whether we should proxy this request.
        url = reverse_proxy.try_reverse_proxy_url(query,
                                                  datetime.datetime.now())
        if url:
            # NB: if sending the proxy url is unsuccessful, then fall through to
            # regular request handling.
            success = self.send_proxy_response(url)
            if success:
                logging.info('[reverse_proxy],true,%s', url)
                return

        logging.info('Policy is %s', query.policy)

        client_signature = query.calculate_client_signature()
        lookup_resolver = resolver.new_resolver(query.policy, client_signature)
        sliver_tools = lookup_resolver.answer_query(query)

        if sliver_tools is None:
            # NOTE: at this point, we know that either the query is invalid
            # (e.g. bad tool_id) or that a valid query has no capacity.
            if model.is_valid_tool(query.tool_id):
                # A.K.A. "no capacity".
                return util.send_no_content(self)
            else:
                # Invalid tool, so report "404 Not Found".
                return util.send_not_found(self, query.response_format)

        if query.response_format == message.FORMAT_JSON:
            self.send_json_response(sliver_tools, query)
        elif query.response_format == message.FORMAT_HTML:
            self.send_html_response(sliver_tools, query)
        elif query.response_format == message.FORMAT_REDIRECT:
            self.send_redirect_response(sliver_tools, query)
        elif query.response_format == message.FORMAT_BT:
            self.send_bt_response(sliver_tools, query)
        elif query.response_format == message.FORMAT_MAP:
            candidates = lookup_resolver.get_candidates(query)
            self.send_map_response(sliver_tools, query, candidates)
        else:
            # TODO (claudiu) Discuss what should be the default behaviour.
            # I think json it's OK since is valid for all tools, while
            # redirect only applies to web-based tools.

            self.send_json_response(sliver_tools, query)

        # At this point, the client has received a response but the server has
        # not closed the connection.
        self.log_location(query, sliver_tools)

        # TODO (claudiu) Add a FORMAT_TYPE column in the BigQuery schema.
        self.log_request(query, sliver_tools)
Example #3
0
    def send_json_response(self, sliver_tools, query):
        """Sends the response to the lookup request in json format.

        Args:
            sliver_tools: A list of SliverTool instances,
                representing the best sliver
                tool selected for this lookup request.
            query: A LookupQuery instance representing the user lookup request.
        """
        if type(sliver_tools) is not list:
            logging.error("Problem: sliver_tools is not a list.")
            return

        # We will respond with HTTP status 204 if len(sliver_tools) == 0
        array_response = False
        if len(sliver_tools) > 1:
            array_response = True

        tool = None
        json_data = ""
        for sliver_tool in sliver_tools:
            data = {}

            if tool == None:
                tool = model.get_tool_from_tool_id(sliver_tool.tool_id)

            if query.tool_address_family == message.ADDRESS_FAMILY_IPv4:
                ips = [sliver_tool.sliver_ipv4]
            elif query.tool_address_family == message.ADDRESS_FAMILY_IPv6:
                ips = [sliver_tool.sliver_ipv6]
            else:
                ips = []
                if sliver_tool.status_ipv4 == message.STATUS_ONLINE:
                    ips.append(sliver_tool.sliver_ipv4)
                if sliver_tool.status_ipv6 == message.STATUS_ONLINE:
                    ips.append(sliver_tool.sliver_ipv6)

            fqdn = fqdn_rewrite.rewrite(sliver_tool.fqdn,
                                        query.tool_address_family,
                                        sliver_tool.tool_id)
            if sliver_tool.http_port:
                data['url'] = _create_tool_url(fqdn, sliver_tool.http_port)
            if sliver_tool.server_port:
                data['port'] = sliver_tool.server_port

            data['fqdn'] = fqdn
            data['ip'] = ips
            data['site'] = sliver_tool.site_id
            data['city'] = sliver_tool.city
            data['country'] = sliver_tool.country

            if sliver_tool.tool_extra and tool.show_tool_extra:
                data['tool_extra'] = sliver_tool.tool_extra

            if json_data != "":
                json_data += ","
            json_data += json.dumps(data)

        if array_response:
            json_data = "[" + json_data + "]"
        if json_data:
            self.response.headers['Access-Control-Allow-Origin'] = '*'
            self.response.headers['Content-Type'] = 'application/json'
            self.response.out.write(json_data)
        else:
            util.send_no_content(self)