@Override
        public URI getLocationURI(final HttpRequest request, final HttpResponse response, final HttpContext context) throws ProtocolException {
            URI result = super.getLocationURI(request, response, context);

            // HACK - some sites return a redirect with an explicit port number
            // that's the same as
            // the default port (e.g. 80 for http), and then when you use this
            // to make the next
            // request, the presence of the port in the domain triggers another
            // redirect, so you
            // fail with a circular redirect error. Avoid that by converting the
            // port number to
            // -1 in that case.
            //
            // Detailed scenario:
            // http://www.test.com/MyPage ->
            // http://www.test.com:80/MyRedirectedPage ->
            // http://www.test.com/MyRedirectedPage
            // We can save bandwidth:
            if (result.getScheme().equalsIgnoreCase("http") && (result.getPort() == 80)) {
                try {
                    result = new URI(result.getScheme(), result.getUserInfo(), result.getHost(), -1, result.getPath(), result.getQuery(), result.getFragment());
                } catch (URISyntaxException e) {
                    LOGGER.warn("Unexpected exception removing port from URI", e);
                }
            }

            // Keep track of the number of redirects.
            Integer count = (Integer) context.getAttribute(REDIRECT_COUNT_CONTEXT_KEY);
            if (count == null) {
                count = 0;
            }

            context.setAttribute(REDIRECT_COUNT_CONTEXT_KEY, count + 1);

            // Record the last permanent redirect
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == HttpStatus.SC_MOVED_PERMANENTLY) {
                context.setAttribute(PERM_REDIRECT_CONTEXT_KEY, result);
            }

            RedirectExceptionReason reason = null;

            if (_redirectMode == RedirectMode.FOLLOW_NONE) {
                switch (statusCode) {
                    case HttpStatus.SC_MOVED_TEMPORARILY:
                    reason = RedirectExceptionReason.TEMP_REDIRECT_DISALLOWED;
                        break;
                    case HttpStatus.SC_MOVED_PERMANENTLY:
                    reason = RedirectExceptionReason.PERM_REDIRECT_DISALLOWED;
                        break;
                    case HttpStatus.SC_TEMPORARY_REDIRECT:
                    reason = RedirectExceptionReason.TEMP_REDIRECT_DISALLOWED;
                        break;
                    case HttpStatus.SC_SEE_OTHER:
                    reason = RedirectExceptionReason.SEE_OTHER_DISALLOWED;
                        break;
                    default:
                }
            }

            if (_redirectMode == RedirectMode.FOLLOW_TEMP) {
                switch (statusCode) {
                    case HttpStatus.SC_MOVED_PERMANENTLY:
                    reason = RedirectExceptionReason.PERM_REDIRECT_DISALLOWED;
                        break;
                    case HttpStatus.SC_SEE_OTHER:
                    reason = RedirectExceptionReason.SEE_OTHER_DISALLOWED;
                        break;
                    default:
                }
            }

            if (reason != null)
                throw new MyRedirectException("RedirectMode disallowed redirect: " + _redirectMode, result, reason);

            return result;
        }
Handler to record last permanent redirect (if any) in context.
crawler-commons/src/main/java/achecrawler/crawler/crawlercommons/fetcher/http/SimpleHttpFetcher.java