Java HttpClient重定向到URL时引发空格异常

Java HttpClient重定向到URL时引发空格异常,java,android,redirect,apache-httpclient-4.x,urlencode,Java,Android,Redirect,Apache Httpclient 4.x,Urlencode,我正在访问一个URL,该URL将我重定向到一个包含空格的URL。(使用HttpClient 4.x)如何防止引发错误(将空格替换为%20 not+) 08-06 02:45:56.486:WARN/System.err(655):org.apache.http.client.ClientProtocolException 08-06 02:45:56.493:WARN/System.err(655):位于org.apache.http.impl.client.AbstractHttpClient

我正在访问一个URL,该URL将我重定向到一个包含空格的URL。(使用HttpClient 4.x)如何防止引发错误(将空格替换为%20 not+)

08-06 02:45:56.486:WARN/System.err(655):org.apache.http.client.ClientProtocolException
08-06 02:45:56.493:WARN/System.err(655):位于org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:557)
08-06 02:45:56.534:WARN/System.err(655):位于org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:509)
08-06 02:45:56.603:WARN/System.err(655):在com.romcessed.romsearch.searchproviders.doperomconnector$DownloadROMTask.doInBackground(doperomconnector.java:636)
08-06 02:45:56.623:WARN/System.err(655):在com.romcessed.romsearch.searchproviders.doperomconnector$DownloadROMTask.doInBackground(doperomconnector.java:1)
08-06 02:45:56.643:WARN/System.err(655):在android.os.AsyncTask$2.call(AsyncTask.java:185)
08-06 02:45:56.663:WARN/System.err(655):位于java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
08-06 02:45:56.683:WARN/System.err(655):位于java.util.concurrent.FutureTask.run(FutureTask.java:137)
08-06 02:45:56.693:WARN/System.err(655):位于java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068)
08-06 02:45:56.713:WARN/System.err(655):位于java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561)
08-06 02:45:56.713:WARN/System.err(655):at java.lang.Thread.run(Thread.java:1096)
08-06 02:45:56.743:WARN/System.err(655):原因:org.apache.http.ProtocolException:无效的重定向URI:http://somewebsite.com/some 文件名为spaces.zip
08-06 02:45:56.787:WARN/System.err(655):位于org.apache.http.impl.client.DefaultRedirectHandler.getLocationURI(DefaultRedirectHandler.java:116)
08-06 02:45:56.803:WARN/System.err(655):位于org.apache.http.impl.client.DefaultRequestDirector.handleResponse(DefaultRequestDirector.java:892)
08-06 02:45:56.813:WARN/System.err(655):位于org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:457)
08-06 02:45:56.843:WARN/System.err(655):位于org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
08-06 02:45:56.843:警告/系统错误(655):。。。9更多
08-06 02:45:56.873:WARN/System.err(655):原因:java.net.URISyntaxException:索引处路径中的非法字符#:http://somewebsite.com/some 文件名为spaces.zip
08-06 02:45:56.913:WARN/System.err(655):位于java.net.URI$Helper.validatePath(URI.java:448)
08-06 02:45:56.923:WARN/System.err(655):位于java.net.URI$Helper.parseURI(URI.java:398)
08-06 02:45:56.953:WARN/System.err(655):位于java.net.URI$Helper.access$100(URI.java:302)
08-06 02:45:56.963:WARN/System.err(655):位于java.net.URI(URI.java:87)
08-06 02:45:56.993:WARN/System.err(655):位于org.apache.http.impl.client.DefaultRedirectHandler.getLocationURI(DefaultRedirectHandler.java:114)
08-06 02:45:57.013:警告/系统错误(655):。。。还有12个

或者用%20替换“+”

类似问题


Apache HTTP库允许您注册一个RedirectHandler对象,该对象将在重定向发生时被调用。您可以使用它拦截重定向并修复它

(也就是说,向您发送此重定向的网站已被破坏。您应该与他们联系并让他们知道。)

这是我的工作代码:)


另一个工作代码示例,它将根据


我建议创建自定义重定向策略

class CustomRedirectStrategy extends DefaultRedirectStrategy {
  // NOTE: Hack for bad redirects such as: http://www.healio.com/Rss/Allergy%20Immunology
  override def createLocationURI(location: String): URI = {
    try {
      super.createLocationURI(location)
    } catch {
      case ex: ProtocolException =>
        val url = new URL(location)
        val uri = new URI(url.getProtocol, url.getUserInfo, url.getHost, url.getPort, url.getPath, url.getQuery, url.getRef)
        uri
    }
  }
}
您可以通过
setRedirectStrategy
方法在客户端中设置

HttpAsyncClients.custom.setRedirectStrategy(new CustomRedirectStrategy).build

如果有人正在寻找2020年及以后的完整解决方案,请参见下文。扩展
DefaultRedirectStrategy
并重写创建重定向URI的方法,以将空间转换为
%20
序列

public class CleanUrlRedirectStrategy extends DefaultRedirectStrategy
{
    private static final Logger logger = LoggerFactory.getLogger( MethodHandles.lookup().lookupClass() );

    // Clean spaces in redirect URLs to prevent an IOException
    @Override
    protected URI createLocationURI( final @NotNull String orig ) throws ProtocolException
    {
        // Replace spaces
        Objects.requireNonNull( orig );
        var fixed = orig.replaceAll("\\s","%20"); // Not \\s+
        if ( ! orig.equals( fixed ) )
        {
            logger.debug( "Cleaned redirect URL from '{}' to '{}'", orig, fixed );
        }

        return super.createLocationURI( fixed );
    }
}


setRedirectHandler
现在被弃用,取而代之的是
RedirectStrategy
private download(){

    ...

    mHttpClient = new DefaultHttpClient(httpParams);

    mHttpClient.setRedirectHandler(new DefaultRedirectHandler() {
        @Override
        public boolean isRedirectRequested(HttpResponse httpResponse, HttpContext httpContext) {
            return super.isRedirectRequested(httpResponse, httpContext);
        }

        @Override
        public URI getLocationURI(HttpResponse httpResponse, HttpContext httpContext) throws ProtocolException {
            return sanitizeUrl(httpResponse.getFirstHeader("location").getValue());
        }
    });


}

private URI sanitizeUrl(String sanitizeURL) throws ProtocolException {

    URI uri = null;

    try {
        URL url = new URL(URLDecoder.decode(sanitizeURL, UTF_8));
        // https://stackoverflow.com/a/8962879/956415
        uri = new URI(url.getProtocol(), url.getUserInfo(), url.getHost(), url.getPort(), url.getPath(), url.getQuery(), url.getRef());
    } catch (URISyntaxException | MalformedURLException | UnsupportedEncodingException e) {
        throw new ProtocolException(e.getMessage(), e);
    }

    return uri;
}
class CustomRedirectStrategy extends DefaultRedirectStrategy {
  // NOTE: Hack for bad redirects such as: http://www.healio.com/Rss/Allergy%20Immunology
  override def createLocationURI(location: String): URI = {
    try {
      super.createLocationURI(location)
    } catch {
      case ex: ProtocolException =>
        val url = new URL(location)
        val uri = new URI(url.getProtocol, url.getUserInfo, url.getHost, url.getPort, url.getPath, url.getQuery, url.getRef)
        uri
    }
  }
}
HttpAsyncClients.custom.setRedirectStrategy(new CustomRedirectStrategy).build
public class CleanUrlRedirectStrategy extends DefaultRedirectStrategy
{
    private static final Logger logger = LoggerFactory.getLogger( MethodHandles.lookup().lookupClass() );

    // Clean spaces in redirect URLs to prevent an IOException
    @Override
    protected URI createLocationURI( final @NotNull String orig ) throws ProtocolException
    {
        // Replace spaces
        Objects.requireNonNull( orig );
        var fixed = orig.replaceAll("\\s","%20"); // Not \\s+
        if ( ! orig.equals( fixed ) )
        {
            logger.debug( "Cleaned redirect URL from '{}' to '{}'", orig, fixed );
        }

        return super.createLocationURI( fixed );
    }
}
var httpClient = HttpClientBuilder
    .create()
    .setRedirectStrategy( new CleanUrlRedirectStrategy() )
    .build();