HTTPCLIENT-1248: make a copy of the original request when creating a redirect request for status 307

git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@1397085 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Oleg Kalnichevski 2012-10-11 14:36:52 +00:00
parent 46aca9def4
commit 53d1180530
4 changed files with 474 additions and 35 deletions

View File

@ -58,6 +58,7 @@ public abstract class HttpRequestBase extends AbstractHttpMessage
private Lock abortLock;
private volatile boolean aborted;
private ProtocolVersion version;
private URI uri;
private Cancellable cancellable;
@ -68,8 +69,15 @@ public abstract class HttpRequestBase extends AbstractHttpMessage
public abstract String getMethod();
/**
* @since 4.3
*/
public void setProtocolVersion(final ProtocolVersion version) {
this.version = version;
}
public ProtocolVersion getProtocolVersion() {
return HttpProtocolParams.getVersion(getParams());
return version != null ? version : HttpProtocolParams.getVersion(getParams());
}
/**
@ -240,6 +248,6 @@ public abstract class HttpRequestBase extends AbstractHttpMessage
@Override
public String toString() {
return getMethod() + " " + getURI() + " " + getProtocolVersion();
}
}
}

View File

@ -0,0 +1,273 @@
/*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.http.client.methods;
import java.net.URI;
import java.util.Locale;
import org.apache.http.Header;
import org.apache.http.HeaderIterator;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpRequest;
import org.apache.http.ProtocolVersion;
import org.apache.http.annotation.NotThreadSafe;
import org.apache.http.client.utils.CloneUtils;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.HeaderGroup;
import org.apache.http.params.HttpParams;
/**
* @since 4.3
*/
@NotThreadSafe
public class RequestBuilder {
private String method;
private ProtocolVersion version;
private URI uri;
private HeaderGroup headergroup;
private HttpEntity entity;
private HttpParams params;
RequestBuilder() {
super();
}
public static RequestBuilder create() {
return new RequestBuilder();
}
public static RequestBuilder copy(final HttpRequest request) {
return new RequestBuilder().doCopy(request);
}
public static RequestBuilder clone(final HttpRequest request) throws CloneNotSupportedException {
return new RequestBuilder().doCopy(CloneUtils.cloneObject(request));
}
private RequestBuilder doCopy(final HttpRequest request) {
if (request == null) {
return this;
}
method = request.getRequestLine().getMethod();
version = request.getRequestLine().getProtocolVersion();
if (request instanceof HttpUriRequest) {
uri = ((HttpUriRequest) request).getURI();
} else {
uri = URI.create(request.getRequestLine().getMethod());
}
if (headergroup == null) {
headergroup = new HeaderGroup();
}
headergroup.clear();
headergroup.setHeaders(request.getAllHeaders());
if (request instanceof HttpEntityEnclosingRequest) {
entity = ((HttpEntityEnclosingRequest) request).getEntity();
} else {
entity = null;
}
params = request.getParams();
return this;
}
public String getMethod() {
return method;
}
public RequestBuilder setMethod(final String method) {
this.method = method;
return this;
}
public ProtocolVersion getVersion() {
return version;
}
public RequestBuilder setVersion(final ProtocolVersion version) {
this.version = version;
return this;
}
public URI getUri() {
return uri;
}
public RequestBuilder setUri(final URI uri) {
this.uri = uri;
return this;
}
public RequestBuilder setUri(final String uri) {
this.uri = uri != null ? URI.create(uri) : null;
return this;
}
public Header getFirstHeader(final String name) {
return headergroup != null ? headergroup.getFirstHeader(name) : null;
}
public Header getLastHeader(final String name) {
return headergroup != null ? headergroup.getLastHeader(name) : null;
}
public Header[] getHeaders(final String name) {
return headergroup != null ? headergroup.getHeaders(name) : null;
}
public RequestBuilder addHeader(final Header header) {
if (headergroup == null) {
headergroup = new HeaderGroup();
}
headergroup.addHeader(header);
return this;
}
public RequestBuilder addHeader(final String name, final String value) {
if (headergroup == null) {
headergroup = new HeaderGroup();
}
this.headergroup.addHeader(new BasicHeader(name, value));
return this;
}
public RequestBuilder removeHeader(Header header) {
if (headergroup == null) {
headergroup = new HeaderGroup();
}
headergroup.removeHeader(header);
return this;
}
public RequestBuilder removeHeaders(final String name) {
if (name == null || headergroup == null) {
return this;
}
for (HeaderIterator i = headergroup.iterator(); i.hasNext(); ) {
Header header = i.nextHeader();
if (name.equalsIgnoreCase(header.getName())) {
i.remove();
}
}
return this;
}
public RequestBuilder setHeader(final Header header) {
if (headergroup != null) {
headergroup = new HeaderGroup();
}
this.headergroup.updateHeader(header);
return this;
}
public RequestBuilder setHeader(final String name, final String value) {
if (headergroup != null) {
headergroup = new HeaderGroup();
}
this.headergroup.updateHeader(new BasicHeader(name, value));
return this;
}
public HttpEntity getEntity() {
return entity;
}
public RequestBuilder setEntity(final HttpEntity entity) {
this.entity = entity;
return this;
}
public HttpParams getParams() {
return params;
}
public RequestBuilder setParams(final HttpParams params) {
this.params = params;
return this;
}
private String getMethodName() {
return this.method != null ? this.method.toUpperCase(Locale.US) :
(this.entity != null ? "POST" : "GET");
}
public HttpUriRequest build() {
HttpRequestBase result;
String methodName = getMethodName();
if (this.entity == null) {
InternalRequest request = new InternalRequest(methodName);
result = request;
} else {
InternalEntityEclosingRequest request = new InternalEntityEclosingRequest(methodName);
request.setEntity(this.entity);
result = request;
}
result.setProtocolVersion(this.version);
result.setURI(this.uri != null ? this.uri : URI.create("/"));
if (this.headergroup != null) {
result.setHeaders(this.headergroup.getAllHeaders());
}
if (this.params != null) {
result.setParams(this.params);
}
return result;
}
static class InternalRequest extends HttpRequestBase {
private final String method;
InternalRequest(final String method) {
super();
this.method = method;
}
@Override
public String getMethod() {
return this.method;
}
}
static class InternalEntityEclosingRequest extends HttpEntityEnclosingRequestBase {
private final String method;
InternalEntityEclosingRequest(final String method) {
super();
this.method = method;
}
@Override
public String getMethod() {
return this.method;
}
}
}

View File

@ -30,34 +30,26 @@ package org.apache.http.impl.client;
import java.net.URI;
import java.net.URISyntaxException;
import org.apache.http.annotation.Immutable;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.Header;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.ProtocolException;
import org.apache.http.annotation.Immutable;
import org.apache.http.client.CircularRedirectException;
import org.apache.http.client.RedirectStrategy;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpHead;
import org.apache.http.client.methods.HttpOptions;
import org.apache.http.client.methods.HttpPatch;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpTrace;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.client.params.ClientPNames;
import org.apache.http.client.utils.URIUtils;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.ExecutionContext;
import org.apache.http.protocol.HttpContext;
/**
* Default implementation of {@link RedirectStrategy}. This strategy honors the restrictions
@ -223,30 +215,11 @@ public class DefaultRedirectStrategy implements RedirectStrategy {
} else {
int status = response.getStatusLine().getStatusCode();
if (status == HttpStatus.SC_TEMPORARY_REDIRECT) {
if (method.equalsIgnoreCase(HttpPost.METHOD_NAME)) {
return copyEntity(new HttpPost(uri), request);
} else if (method.equalsIgnoreCase(HttpPut.METHOD_NAME)) {
return copyEntity(new HttpPut(uri), request);
} else if (method.equalsIgnoreCase(HttpDelete.METHOD_NAME)) {
return new HttpDelete(uri);
} else if (method.equalsIgnoreCase(HttpTrace.METHOD_NAME)) {
return new HttpTrace(uri);
} else if (method.equalsIgnoreCase(HttpOptions.METHOD_NAME)) {
return new HttpOptions(uri);
} else if (method.equalsIgnoreCase(HttpPatch.METHOD_NAME)) {
return copyEntity(new HttpPatch(uri), request);
}
return RequestBuilder.copy(request).setUri(uri).build();
} else {
return new HttpGet(uri);
}
return new HttpGet(uri);
}
}
private HttpUriRequest copyEntity(
final HttpEntityEnclosingRequestBase redirect, final HttpRequest original) {
if (original instanceof HttpEntityEnclosingRequest) {
redirect.setEntity(((HttpEntityEnclosingRequest) original).getEntity());
}
return redirect;
}
}

View File

@ -0,0 +1,185 @@
/*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.http.client.methods;
import java.net.URI;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpVersion;
import org.apache.http.entity.BasicHttpEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.message.BasicHeader;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import org.junit.Assert;
import org.junit.Test;
public class TestRequestBuilder {
@Test
public void testBasicGet() throws Exception {
HttpUriRequest request = RequestBuilder.create().build();
Assert.assertNotNull(request);
Assert.assertEquals("GET", request.getMethod());
Assert.assertEquals(URI.create("/"), request.getURI());
Assert.assertEquals(HttpVersion.HTTP_1_1, request.getProtocolVersion());
Assert.assertFalse(request instanceof HttpEntityEnclosingRequest);
}
@Test
public void testBasicWithEntity() throws Exception {
HttpEntity entity = new BasicHttpEntity();
HttpUriRequest request = RequestBuilder.create().setEntity(entity).build();
Assert.assertNotNull(request);
Assert.assertEquals("POST", request.getMethod());
Assert.assertEquals(URI.create("/"), request.getURI());
Assert.assertEquals(HttpVersion.HTTP_1_1, request.getProtocolVersion());
Assert.assertTrue(request instanceof HttpEntityEnclosingRequest);
Assert.assertSame(entity, ((HttpEntityEnclosingRequest) request).getEntity());
}
@Test
public void testGetWithEntity() throws Exception {
HttpEntity entity = new BasicHttpEntity();
HttpUriRequest request = RequestBuilder.create().setMethod("get").setEntity(entity).build();
Assert.assertNotNull(request);
Assert.assertEquals("GET", request.getMethod());
Assert.assertEquals(URI.create("/"), request.getURI());
Assert.assertEquals(HttpVersion.HTTP_1_1, request.getProtocolVersion());
Assert.assertTrue(request instanceof HttpEntityEnclosingRequest);
Assert.assertSame(entity, ((HttpEntityEnclosingRequest) request).getEntity());
}
@Test
public void testCopy() throws Exception {
HttpEntity entity = new StringEntity("stuff");
HttpParams params = new BasicHttpParams();
HttpUriRequest request = RequestBuilder.create()
.setMethod("put")
.setUri(URI.create("/stuff"))
.setVersion(HttpVersion.HTTP_1_0)
.addHeader("header1", "stuff")
.setHeader("header2", "more stuff")
.setEntity(entity)
.setParams(params)
.build();
Assert.assertNotNull(request);
Assert.assertEquals("PUT", request.getMethod());
Assert.assertEquals(URI.create("/stuff"), request.getURI());
Assert.assertEquals(HttpVersion.HTTP_1_0, request.getProtocolVersion());
Assert.assertTrue(request instanceof HttpEntityEnclosingRequest);
HttpUriRequest copy = RequestBuilder.copy(request).setUri("/other-stuff").build();
Assert.assertEquals("PUT", copy.getMethod());
Assert.assertEquals(URI.create("/other-stuff"), copy.getURI());
Assert.assertTrue(copy instanceof HttpEntityEnclosingRequest);
Assert.assertSame(entity, ((HttpEntityEnclosingRequest) copy).getEntity());
Assert.assertSame(params, copy.getParams());
}
@Test
public void testClone() throws Exception {
HttpEntity entity = new StringEntity("stuff");
HttpParams params = new BasicHttpParams();
HttpUriRequest request = RequestBuilder.create()
.setMethod("put")
.setUri(URI.create("/stuff"))
.setVersion(HttpVersion.HTTP_1_0)
.addHeader("header1", "stuff")
.setHeader("header2", "more stuff")
.setEntity(entity)
.setParams(params)
.build();
Assert.assertNotNull(request);
Assert.assertEquals("PUT", request.getMethod());
Assert.assertEquals(URI.create("/stuff"), request.getURI());
Assert.assertEquals(HttpVersion.HTTP_1_0, request.getProtocolVersion());
Assert.assertTrue(request instanceof HttpEntityEnclosingRequest);
HttpUriRequest clone = RequestBuilder.clone(request).setUri("/other-stuff").build();
Assert.assertEquals("PUT", clone.getMethod());
Assert.assertEquals(URI.create("/other-stuff"), clone.getURI());
Assert.assertTrue(clone instanceof HttpEntityEnclosingRequest);
Assert.assertNotNull(((HttpEntityEnclosingRequest) clone).getEntity());
Assert.assertNotSame(entity, ((HttpEntityEnclosingRequest) clone).getEntity());
Assert.assertNotNull(clone.getParams());
Assert.assertNotSame(params, clone.getParams());
}
@Test
public void testCopyNull() throws Exception {
HttpUriRequest copy = RequestBuilder.copy(null).setUri("/other-stuff").build();
Assert.assertEquals("GET", copy.getMethod());
Assert.assertEquals(URI.create("/other-stuff"), copy.getURI());
Assert.assertFalse(copy instanceof HttpEntityEnclosingRequest);
}
@Test
public void testGettersAndMutators() throws Exception {
HttpEntity entity = new StringEntity("stuff");
HttpParams params = new BasicHttpParams();
Header h1 = new BasicHeader("header1", "stuff");
Header h2 = new BasicHeader("header1", "more-stuff");
RequestBuilder builder = RequestBuilder.create()
.setMethod("put")
.setUri("/stuff")
.setVersion(HttpVersion.HTTP_1_0)
.addHeader(h1)
.addHeader(h2)
.setEntity(entity)
.setParams(params);
Assert.assertEquals("put", builder.getMethod());
Assert.assertEquals(URI.create("/stuff"), builder.getUri());
Assert.assertEquals(HttpVersion.HTTP_1_0, builder.getVersion());
Assert.assertSame(h1, builder.getFirstHeader("header1"));
Assert.assertSame(h2, builder.getLastHeader("header1"));
Assert.assertEquals(2, builder.getHeaders("header1").length);
Assert.assertSame(entity, builder.getEntity());
Assert.assertSame(params, builder.getParams());
builder.setMethod(null)
.setUri((String) null)
.setVersion(null)
.removeHeader(h1)
.removeHeaders("header1")
.removeHeader(h2)
.setEntity(null)
.setParams(null);
Assert.assertEquals(null, builder.getMethod());
Assert.assertEquals(null, builder.getUri());
Assert.assertEquals(null, builder.getVersion());
Assert.assertSame(null, builder.getFirstHeader("header1"));
Assert.assertSame(null, builder.getLastHeader("header1"));
Assert.assertEquals(0, builder.getHeaders("header1").length);
Assert.assertSame(null, builder.getEntity());
Assert.assertSame(null, builder.getParams());
}
}