core/src/main/java/com/digitalpebble/stormcrawler/protocol/HttpRobotRulesParser.java
@Override
    public BaseRobotRules getRobotRulesSet(Protocol http, URL url) {

        String cacheKey = getCacheKey(url);

        // check in the error cache first
        BaseRobotRules robotRules = ERRORCACHE.getIfPresent(cacheKey);
        if (robotRules != null) {
            return robotRules;
        }

        // now try the proper cache
        robotRules = CACHE.getIfPresent(cacheKey);
        if (robotRules != null) {
            return robotRules;
        }

        boolean cacheRule = true;
        URL redir = null;

        String keyredir = null;

        LOG.debug("Cache miss {} for {}", cacheKey, url);
        List<Integer> bytesFetched = new LinkedList<>();
        try {
            ProtocolResponse response = http.getProtocolOutput(new URL(url,
                    "/robots.txt").toString(), Metadata.empty);
            int code = response.getStatusCode();
            bytesFetched.add(response.getContent() != null ? response
                    .getContent().length : 0);
            // try one level of redirection ?
            if (code == 301 || code == 302 || code == 307 || code == 308) {
                String redirection = response.getMetadata().getFirstValue(
                        HttpHeaders.LOCATION);
                if (StringUtils.isNotBlank(redirection)) {
                    if (!redirection.startsWith("http")) {
                        // RFC says it should be absolute, but apparently it
                        // isn't
                        redir = new URL(url, redirection);
                    } else {
                        redir = new URL(redirection);
                    }
                    // try from the cache
                    keyredir = getCacheKey(redir);
                    if (cacheKey.equalsIgnoreCase(keyredir)) {
                        keyredir = null;
                    } else {
                        RobotRules cachedRediRobotRules = CACHE
                                .getIfPresent(keyredir);
                        if (cachedRediRobotRules != null) {
                            // cache also for the redirected host
                            // but only if the robots.txt file is at the root
                            if (redir.getPath().equals("/robots.txt")) {
                                LOG.debug(
                                        "Caching robots for {} under key {} in cache",
                                        redir, keyredir);
                                CACHE.put(keyredir, cachedRediRobotRules);
                            }
                            return cachedRediRobotRules;
                        }
                    }

                    response = http.getProtocolOutput(redir.toString(),
                            Metadata.empty);
                    code = response.getStatusCode();
                    bytesFetched.add(response.getContent() != null ? response
                            .getContent().length : 0);
                }
            }
            if (code == 200) // found rules: parse them
            {
                String ct = response.getMetadata().getFirstValue(
                        HttpHeaders.CONTENT_TYPE);
                robotRules = parseRules(url.toString(), response.getContent(),
                        ct, agentNames);
            } else if ((code == 403) && (!allowForbidden)) {
                robotRules = FORBID_ALL_RULES; // use forbid all
            } else if (code >= 500) {
                cacheRule = false;
                robotRules = EMPTY_RULES;
            } else
                robotRules = EMPTY_RULES; // use default rules
        } catch (Throwable t) {
            LOG.info("Couldn't get robots.txt for {} : {}", url, t.toString());
            cacheRule = false;
            robotRules = EMPTY_RULES;
        }

        Cache<String, RobotRules> cacheToUse = CACHE;
        String cacheName = "success";
        if (!cacheRule) {
            cacheToUse = ERRORCACHE;
            cacheName = "error";
        }

        RobotRules cached = new RobotRules(robotRules);

        LOG.debug("Caching robots for {} under key {} in cache {}", url,
                cacheKey, cacheName);
        cacheToUse.put(cacheKey, cached);

        // cache robot for redirections
        // get here only if the target has not been found in the cache
        if (keyredir != null) {
            // cache also for the redirected host
            // but only if the robots.txt file is at the root
            if (redir.getPath().equals("/robots.txt")) {
                LOG.debug("Caching robots for {} under key {} in cache {}",
                        redir, keyredir, cacheName);
                cacheToUse.put(keyredir, cached);
            }
        }

        RobotRules live = new RobotRules(robotRules);
        live.setContentLengthFetched(Ints.toArray(bytesFetched));
        return live;
    }
@Override
    public BaseRobotRules getRobotRulesSet(Protocol http, URL url) {

        String cacheKey = getCacheKey(url);

        // check in the error cache first
        BaseRobotRules robotRules = ERRORCACHE.getIfPresent(cacheKey);
        if (robotRules != null) {
            return robotRules;
        }

        // now try the proper cache
        robotRules = CACHE.getIfPresent(cacheKey);
        if (robotRules != null) {
            return robotRules;
        }

        boolean cacheRule = true;
        URL redir = null;

        String keyredir = null;

        LOG.debug("Cache miss {} for {}", cacheKey, url);
        List<Integer> bytesFetched = new LinkedList<>();
        try {
            ProtocolResponse response = http.getProtocolOutput(new URL(url,
                    "/robots.txt").toString(), Metadata.empty);
            int code = response.getStatusCode();
            bytesFetched.add(response.getContent() != null ? response
                    .getContent().length : 0);
            // try one level of redirection ?
            if (code == 301 || code == 302 || code == 307 || code == 308) {
                String redirection = response.getMetadata().getFirstValue(
                        HttpHeaders.LOCATION);
                if (StringUtils.isNotBlank(redirection)) {
                    if (!redirection.startsWith("http")) {
                        // RFC says it should be absolute, but apparently it
                        // isn't
                        redir = new URL(url, redirection);
                    } else {
                        redir = new URL(redirection);
                    }
                    // try from the cache
                    keyredir = getCacheKey(redir);
                    if (cacheKey.equalsIgnoreCase(keyredir)) {
                        keyredir = null;
                    } else {
                        RobotRules cachedRediRobotRules = CACHE
                                .getIfPresent(keyredir);
                        if (cachedRediRobotRules != null) {
                            // cache also for the redirected host
                            // but only if the robots.txt file is at the root
                            if (redir.getPath().equals("/robots.txt")) {
                                LOG.debug(
                                        "Caching robots for {} under key {} in cache",
                                        redir, keyredir);
                                CACHE.put(keyredir, cachedRediRobotRules);
                            }
                            return cachedRediRobotRules;
                        }
                    }

                    response = http.getProtocolOutput(redir.toString(),
                            Metadata.empty);
                    code = response.getStatusCode();
                    bytesFetched.add(response.getContent() != null ? response
                            .getContent().length : 0);
                }
            }
            if (code == 200) // found rules: parse them
            {
                String ct = response.getMetadata().getFirstValue(
                        HttpHeaders.CONTENT_TYPE);
                robotRules = parseRules(url.toString(), response.getContent(),
                        ct, agentNames);
            } else if ((code == 403) && (!allowForbidden)) {
                robotRules = FORBID_ALL_RULES; // use forbid all
            } else if (code >= 500) {
                cacheRule = false;
                robotRules = EMPTY_RULES;
            } else
                robotRules = EMPTY_RULES; // use default rules
        } catch (Throwable t) {
            LOG.info("Couldn't get robots.txt for {} : {}", url, t.toString());
            cacheRule = false;
            robotRules = EMPTY_RULES;
        }

        Cache<String, RobotRules> cacheToUse = CACHE;
        String cacheName = "success";
        if (!cacheRule) {
            cacheToUse = ERRORCACHE;
            cacheName = "error";
        }

        RobotRules cached = new RobotRules(robotRules);

        LOG.debug("Caching robots for {} under key {} in cache {}", url,
                cacheKey, cacheName);
        cacheToUse.put(cacheKey, cached);

        // cache robot for redirections
        // get here only if the target has not been found in the cache
        if (keyredir != null) {
            // cache also for the redirected host
            // but only if the robots.txt file is at the root
            if (redir.getPath().equals("/robots.txt")) {
                LOG.debug("Caching robots for {} under key {} in cache {}",
                        redir, keyredir, cacheName);
                cacheToUse.put(keyredir, cached);
            }
        }

        RobotRules live = new RobotRules(robotRules);
        live.setContentLengthFetched(Ints.toArray(bytesFetched));
        return live;
    }
@ Override public BaseRobotRules getRobotRulesSet ( Protocol http , URL url ) { String cacheKey = getCacheKey ( url ) ; // check in the error cache first BaseRobotRules robotRules = ERRORCACHE . getIfPresent ( cacheKey ) ; if ( robotRules != null ) { return robotRules ; } // now try the proper cache robotRules = CACHE . getIfPresent ( cacheKey ) ; if ( robotRules != null ) { return robotRules ; } boolean cacheRule = true ; URL redir = null ; String keyredir = null ; LOG . debug ( "Cache miss {} for {}" , cacheKey , url ) ; List < Integer > bytesFetched = new LinkedList <> ( ) ; try { ProtocolResponse response = http . getProtocolOutput ( new URL ( url , "/robots.txt" ) . toString ( ) , Metadata . empty ) ; int code = response . getStatusCode ( ) ; bytesFetched . add ( response . getContent ( ) != null ? response . getContent ( ) . length : 0 ) ; // try one level of redirection ? if ( code == 301 || code == 302 || code == 307 || code == 308 ) { String redirection = response . getMetadata ( ) . getFirstValue ( HttpHeaders . LOCATION ) ; if ( StringUtils . isNotBlank ( redirection ) ) { if ( ! redirection . startsWith ( "http" ) ) { // RFC says it should be absolute, but apparently it // isn't redir = new URL ( url , redirection ) ; } else { redir = new URL ( redirection ) ; } // try from the cache keyredir = getCacheKey ( redir ) ; if ( cacheKey . equalsIgnoreCase ( keyredir ) ) { keyredir = null ; } else { RobotRules cachedRediRobotRules = CACHE . getIfPresent ( keyredir ) ; if ( cachedRediRobotRules != null ) { // cache also for the redirected host // but only if the robots.txt file is at the root if ( redir . getPath ( ) . equals ( "/robots.txt" ) ) { LOG . debug ( "Caching robots for {} under key {} in cache" , redir , keyredir ) ; CACHE . put ( keyredir , cachedRediRobotRules ) ; } return cachedRediRobotRules ; } } response = http . getProtocolOutput ( redir . toString ( ) , Metadata . empty ) ; code = response . getStatusCode ( ) ; bytesFetched . add ( response . getContent ( ) != null ? response . getContent ( ) . length : 0 ) ; } } if ( code == 200 ) // found rules: parse them { String ct = response . getMetadata ( ) . getFirstValue ( HttpHeaders . CONTENT_TYPE ) ; robotRules = parseRules ( url . toString ( ) , response . getContent ( ) , ct , agentNames ) ; } else if ( ( code == 403 ) && ( ! allowForbidden ) ) { robotRules = FORBID_ALL_RULES ; // use forbid all } else if ( code >= 500 ) { cacheRule = false ; robotRules = EMPTY_RULES ; } else robotRules = EMPTY_RULES ; // use default rules } catch ( Throwable t ) { LOG . info ( "Couldn't get robots.txt for {} : {}" , url , t . toString ( ) ) ; cacheRule = false ; robotRules = EMPTY_RULES ; } Cache < String , RobotRules > cacheToUse = CACHE ; String cacheName = "success" ; if ( ! cacheRule ) { cacheToUse = ERRORCACHE ; cacheName = "error" ; } RobotRules cached = new RobotRules ( robotRules ) ; LOG . debug ( "Caching robots for {} under key {} in cache {}" , url , cacheKey , cacheName ) ; cacheToUse . put ( cacheKey , cached ) ; // cache robot for redirections // get here only if the target has not been found in the cache if ( keyredir != null ) { // cache also for the redirected host // but only if the robots.txt file is at the root if ( redir . getPath ( ) . equals ( "/robots.txt" ) ) { LOG . debug ( "Caching robots for {} under key {} in cache {}" , redir , keyredir , cacheName ) ; cacheToUse . put ( keyredir , cached ) ; } } RobotRules live = new RobotRules ( robotRules ) ; live . setContentLengthFetched ( Ints . toArray ( bytesFetched ) ) ; return live ; }
Get the rules from robots.txt which applies for the given {@code url}.
Robot rules are cached for a unique combination of host, protocol, and
port. If no rules are found in the cache, a HTTP request is send to fetch
{{protocol://host:port/robots.txt}}. The robots.txt is then parsed and
the rules are cached to avoid re-fetching and re-parsing it again.

@param http
The {@link Protocol} object
@param url
URL robots.txt applies to

@return {@link BaseRobotRules} holding the rules from robots.txt
Get the rules from robots . txt which applies for the given { @code url } . Robot rules are cached for a unique combination of host protocol and port . If no rules are found in the cache a HTTP request is send to fetch {{ protocol : // host : port / robots . txt }} . The robots . txt is then parsed and the rules are cached to avoid re - fetching and re - parsing it again .