<commit_before>from google.appengine.api import memcache
from google.appengine.api import taskqueue
from google.appengine.ext import db
from google.appengine.ext import deferred
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template

from mlabns.db import model
from mlabns.util import constants
from mlabns.util import message
from mlabns.util import lookup_query
from mlabns.util import resolver
from mlabns.util import util

import json
import logging
import time

def put_ping(query, time):
    ping = model.Ping(latitude = round(query.latitude, 2),
                      longitude = round(query.longitude, 2),
                      tool_id = query.tool_id,
                      address_family = query.address_family,
                      time = time)
    ping.put()

class LookupHandler(webapp.RequestHandler):
    """Routes GET requests to the appropriate SliverTools."""

    def post(self):
        """Not implemented."""
        return util.send_not_found(self)

    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)

        logging.info('Policy is %s', query.policy)
        lookup_resolver = resolver.new_resolver(query.policy)
        sliver_tool = lookup_resolver.answer_query(query)

        if sliver_tool is None:
            return util.send_not_found(self, query.response_format)

        if query.response_format == message.FORMAT_JSON:
            self.send_json_response(sliver_tool, query)
        elif query.response_format == message.FORMAT_HTML:
            self.send_html_response(sliver_tool, query)
        elif query.response_format == message.FORMAT_REDIRECT:
            self.send_redirect_response(sliver_tool, query)
        elif query.response_format == message.FORMAT_MAP:
            candidates = lookup_resolver.get_candidates(query)
            self.send_map_response(sliver_tool, 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 (e.g., npad)
            self.send_json_response(sliver_tool, query)

        # TODO (claudiu) Add a FORMAT_TYPE column in the BigQuery schema.
        self.log_request(query, sliver_tool)

    def send_json_response(self, sliver_tool, query):
        """Sends the response to the lookup request in json format.

        Args:
            sliver_tool: A SliverTool instance, representing the best sliver
                tool selected for this lookup request.
            query: A LookupQuery instance representing the user lookup request.
        """
        data = {}

        ip = []
        fqdn_annotation = ''

        logging.info('user_defined_af = %s', query.user_defined_af)
        if query.user_defined_af == message.ADDRESS_FAMILY_IPv4:
            ip = [sliver_tool.sliver_ipv4]
            fqdn_annotation = 'v4'
        elif query.user_defined_af == message.ADDRESS_FAMILY_IPv6:
            ip = [sliver_tool.sliver_ipv6]
            fqdn_annotation = 'v6'
        else:
            # If 'address_family' is not specified, the default is to
            # return both valid IP addresses (if both 'status_ipv4' and
            # 'status_ipv6' are 'online').
            # Although the update will only set the sliver as online if it
            # has a valid IP address, the resolver still returns it as
            # a candidate.
            if (sliver_tool.sliver_ipv4 != 'off' and
                sliver_tool.status_ipv4 == message.STATUS_ONLINE):
                ip.append(sliver_tool.sliver_ipv4)
            if (sliver_tool.sliver_ipv6 != 'off' and
                sliver_tool.status_ipv6 == message.STATUS_ONLINE):
                ip.append(sliver_tool.sliver_ipv6)

        fqdn_parts = sliver_tool.fqdn.split('.')
        fqdn_parts[2] += fqdn_annotation
        fqdn = '.'.join(fqdn_parts)

        if sliver_tool.http_port:
            data['url'] = 'http://' + fqdn + ':' + sliver_tool.http_port

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

        json_data = json.dumps(data)
        self.response.headers['Access-Control-Allow-Origin'] = '*'
        self.response.headers['Content-Type'] = 'application/json'
        self.response.out.write(json_data)

    def send_html_response(self, sliver_tool, query):
        """Sends the response to the lookup request in html format.

        Args:
            sliver_tool: A SliverTool instance, representing the best sliver
                tool selected for this lookup request.
            query: A LookupQuery instance representing the user lookup request.

        """
        records = []
        records.append(sliver_tool)
        values = {'records' : records}
        self.response.headers['Access-Control-Allow-Origin'] = '*'
        self.response.out.write(
            template.render(
                'mlabns/templates/lookup_response.html', values))

    def send_redirect_response(self, sliver_tool, query):
        """Sends an HTTP redirect (for web-based tools only).

        Args:
            sliver_tool: A SliverTool instance, representing the best sliver
                tool selected for this lookup request.
            query: A LookupQuery instance representing the user lookup request.

        """
        if sliver_tool.http_port:
            url = '' .join([
                'http://', sliver_tool.fqdn, ':', sliver_tool.http_port])
            return self.redirect(str(url))

        return util.send_not_found(self, 'html')

    def send_map_response(self, sliver_tool, query, candidates):
        """Shows the result of the query in a map.

        The map displays a set of markers representing the user location,
        all the available sites and a line connecting the user to the
        destination site.
<commit_msg>Redirect should support fqdn annotation.<commit_after>from google.appengine.api import memcache
from google.appengine.api import taskqueue
from google.appengine.ext import db
from google.appengine.ext import deferred
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template

from mlabns.db import model
from mlabns.util import constants
from mlabns.util import message
from mlabns.util import lookup_query
from mlabns.util import resolver
from mlabns.util import util

import json
import logging
import time

def put_ping(query, time):
    ping = model.Ping(latitude = round(query.latitude, 2),
                      longitude = round(query.longitude, 2),
                      tool_id = query.tool_id,
                      address_family = query.address_family,
                      time = time)
    ping.put()

class LookupHandler(webapp.RequestHandler):
    """Routes GET requests to the appropriate SliverTools."""

    def post(self):
        """Not implemented."""
        return util.send_not_found(self)

    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)

        logging.info('Policy is %s', query.policy)
        lookup_resolver = resolver.new_resolver(query.policy)
        sliver_tool = lookup_resolver.answer_query(query)

        if sliver_tool is None:
            return util.send_not_found(self, query.response_format)

        if query.response_format == message.FORMAT_JSON:
            self.send_json_response(sliver_tool, query)
        elif query.response_format == message.FORMAT_HTML:
            self.send_html_response(sliver_tool, query)
        elif query.response_format == message.FORMAT_REDIRECT:
            self.send_redirect_response(sliver_tool, query)
        elif query.response_format == message.FORMAT_MAP:
            candidates = lookup_resolver.get_candidates(query)
            self.send_map_response(sliver_tool, 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 (e.g., npad)
            self.send_json_response(sliver_tool, query)

        # TODO (claudiu) Add a FORMAT_TYPE column in the BigQuery schema.
        self.log_request(query, sliver_tool)

    def send_json_response(self, sliver_tool, query):
        """Sends the response to the lookup request in json format.

        Args:
            sliver_tool: A SliverTool instance, representing the best sliver
                tool selected for this lookup request.
            query: A LookupQuery instance representing the user lookup request.
        """
        data = {}

        ip = []

        logging.info('user_defined_af = %s', query.user_defined_af)
        if query.user_defined_af == message.ADDRESS_FAMILY_IPv4:
            ip = [sliver_tool.sliver_ipv4]
        elif query.user_defined_af == message.ADDRESS_FAMILY_IPv6:
            ip = [sliver_tool.sliver_ipv6]
        else:
            # If 'address_family' is not specified, the default is to
            # return both valid IP addresses (if both 'status_ipv4' and
            # 'status_ipv6' are 'online').
            # Although the update will only set the sliver as online if it
            # has a valid IP address, the resolver still returns it as
            # a candidate.
            if (sliver_tool.sliver_ipv4 != 'off' and
                sliver_tool.status_ipv4 == message.STATUS_ONLINE):
                ip.append(sliver_tool.sliver_ipv4)
            if (sliver_tool.sliver_ipv6 != 'off' and
                sliver_tool.status_ipv6 == message.STATUS_ONLINE):
                ip.append(sliver_tool.sliver_ipv6)

        if sliver_tool.http_port:
            data['url'] = ''.join([
                'http://', self._add_fqdn_annotation(query, sliver_tool.fqdn),
                ':', sliver_tool.http_port])

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

        json_data = json.dumps(data)
        self.response.headers['Access-Control-Allow-Origin'] = '*'
        self.response.headers['Content-Type'] = 'application/json'
        self.response.out.write(json_data)

    def send_html_response(self, sliver_tool, query):
        """Sends the response to the lookup request in html format.

        Args:
            sliver_tool: A SliverTool instance, representing the best sliver
                tool selected for this lookup request.
            query: A LookupQuery instance representing the user lookup request.

        """
        records = []
        records.append(sliver_tool)
        values = {'records' : records}
        self.response.headers['Access-Control-Allow-Origin'] = '*'
        self.response.out.write(
            template.render(
                'mlabns/templates/lookup_response.html', values))

    def send_redirect_response(self, sliver_tool, query):
        """Sends an HTTP redirect (for web-based tools only).

        Args:
            sliver_tool: A SliverTool instance, representing the best sliver
                tool selected for this lookup request.
            query: A LookupQuery instance representing the user lookup request.

        """
        if sliver_tool.http_port:
            url = ''.join([
                'http://', self._add_fqdn_annotation(query, sliver_tool.fqdn),
                ':', sliver_tool.http_port])
            return self.redirect(str(url))

        return util.send_not_found(self, 'html')

    def send_map_response(self, sliver_tool, query, candidates):
        """Shows the result of the query in a map.

        The map displays a set of markers representing the user location,
        all the available sites and a line connecting the user to the
        destination site.

{'fraction_non_alphanumeric': 0.08474309544417342, 'fraction_numerical': 0.0030686914784798175, 'mean_word_length': 2.366887417218543, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5194839', 'n_tokens_mistral': 3621, 'n_tokens_neox': 3533, 'n_words': 994}