diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index bd7a94293..6d6bfbd15 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -4,6 +4,9 @@ Changes for 4.4-alpha1 Changelog: ------------------- +* [HTTPCLIENT-1474] Fixed broken entity enclosing requests in HC Fluent. + Contributed by Oleg Kalnichevski + * [HTTPCLIENT-1403] Pluggable content decoders. Contributed by Oleg Kalnichevski diff --git a/fluent-hc/src/main/java/org/apache/http/client/fluent/InternalEntityEnclosingHttpRequest.java b/fluent-hc/src/main/java/org/apache/http/client/fluent/InternalEntityEnclosingHttpRequest.java new file mode 100644 index 000000000..6e0b4d64a --- /dev/null +++ b/fluent-hc/src/main/java/org/apache/http/client/fluent/InternalEntityEnclosingHttpRequest.java @@ -0,0 +1,63 @@ +/* + * ==================================================================== + * 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 + * . + * + */ + +package org.apache.http.client.fluent; + +import java.net.URI; + +import org.apache.http.Header; +import org.apache.http.HttpEntity; +import org.apache.http.HttpEntityEnclosingRequest; +import org.apache.http.annotation.NotThreadSafe; +import org.apache.http.protocol.HTTP; + +@NotThreadSafe +class InternalEntityEnclosingHttpRequest extends InternalHttpRequest implements HttpEntityEnclosingRequest { + + private HttpEntity entity; + + public InternalEntityEnclosingHttpRequest(final String method, final URI requestURI) { + super(method, requestURI); + } + + @Override + public HttpEntity getEntity() { + return this.entity; + } + + @Override + public void setEntity(final HttpEntity entity) { + this.entity = entity; + } + + @Override + public boolean expectContinue() { + final Header expect = getFirstHeader(HTTP.EXPECT_DIRECTIVE); + return expect != null && HTTP.EXPECT_CONTINUE.equalsIgnoreCase(expect.getValue()); + } + +} diff --git a/fluent-hc/src/main/java/org/apache/http/client/fluent/InternalHttpRequest.java b/fluent-hc/src/main/java/org/apache/http/client/fluent/InternalHttpRequest.java index a07c1b211..8d4595424 100644 --- a/fluent-hc/src/main/java/org/apache/http/client/fluent/InternalHttpRequest.java +++ b/fluent-hc/src/main/java/org/apache/http/client/fluent/InternalHttpRequest.java @@ -28,6 +28,8 @@ package org.apache.http.client.fluent; import java.net.URI; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; import org.apache.http.HttpVersion; import org.apache.http.ProtocolVersion; @@ -35,24 +37,32 @@ import org.apache.http.RequestLine; import org.apache.http.annotation.NotThreadSafe; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.Configurable; +import org.apache.http.client.methods.HttpExecutionAware; import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.concurrent.Cancellable; import org.apache.http.message.AbstractHttpMessage; import org.apache.http.message.BasicRequestLine; import org.apache.http.util.Args; @NotThreadSafe -class InternalHttpRequest extends AbstractHttpMessage implements HttpUriRequest, Configurable { +class InternalHttpRequest extends AbstractHttpMessage + implements HttpUriRequest, HttpExecutionAware, Configurable { private final String method; private ProtocolVersion version; private URI uri; private RequestConfig config; + private final AtomicBoolean aborted; + private final AtomicReference cancellableRef; + InternalHttpRequest(final String method, final URI requestURI) { Args.notBlank(method, "Method"); Args.notNull(requestURI, "Request URI"); this.method = method; this.uri = requestURI; + this.aborted = new AtomicBoolean(false); + this.cancellableRef = new AtomicReference(null); } public void setProtocolVersion(final ProtocolVersion version) { @@ -76,11 +86,24 @@ class InternalHttpRequest extends AbstractHttpMessage implements HttpUriRequest, @Override public void abort() throws UnsupportedOperationException { + if (this.aborted.compareAndSet(false, true)) { + final Cancellable cancellable = this.cancellableRef.getAndSet(null); + if (cancellable != null) { + cancellable.cancel(); + } + } } @Override public boolean isAborted() { - return false; + return this.aborted.get(); + } + + @Override + public void setCancellable(final Cancellable cancellable) { + if (!this.aborted.get()) { + this.cancellableRef.set(cancellable); + } } @Override @@ -97,7 +120,6 @@ class InternalHttpRequest extends AbstractHttpMessage implements HttpUriRequest, return new BasicRequestLine(getMethod(), uritext, ver); } - @Override public RequestConfig getConfig() { return config; diff --git a/fluent-hc/src/main/java/org/apache/http/client/fluent/Request.java b/fluent-hc/src/main/java/org/apache/http/client/fluent/Request.java index b95604cac..b3740d756 100644 --- a/fluent-hc/src/main/java/org/apache/http/client/fluent/Request.java +++ b/fluent-hc/src/main/java/org/apache/http/client/fluent/Request.java @@ -71,64 +71,64 @@ public class Request { private SimpleDateFormat dateFormatter; public static Request Get(final URI uri) { - return new Request(HttpGet.METHOD_NAME, uri); + return new Request(new InternalHttpRequest(HttpGet.METHOD_NAME, uri)); } public static Request Get(final String uri) { - return new Request(HttpGet.METHOD_NAME, URI.create(uri)); + return new Request(new InternalHttpRequest(HttpGet.METHOD_NAME, URI.create(uri))); } public static Request Head(final URI uri) { - return new Request(HttpHead.METHOD_NAME, uri); + return new Request(new InternalHttpRequest(HttpHead.METHOD_NAME, uri)); } public static Request Head(final String uri) { - return new Request(HttpHead.METHOD_NAME, URI.create(uri)); + return new Request(new InternalHttpRequest(HttpHead.METHOD_NAME, URI.create(uri))); } public static Request Post(final URI uri) { - return new Request(HttpPost.METHOD_NAME, uri); + return new Request(new InternalEntityEnclosingHttpRequest(HttpPost.METHOD_NAME, uri)); } public static Request Post(final String uri) { - return new Request(HttpPost.METHOD_NAME, URI.create(uri)); + return new Request(new InternalEntityEnclosingHttpRequest(HttpPost.METHOD_NAME, URI.create(uri))); } public static Request Put(final URI uri) { - return new Request(HttpPut.METHOD_NAME, uri); + return new Request(new InternalEntityEnclosingHttpRequest(HttpPut.METHOD_NAME, uri)); } public static Request Put(final String uri) { - return new Request(HttpPut.METHOD_NAME, URI.create(uri)); + return new Request(new InternalEntityEnclosingHttpRequest(HttpPut.METHOD_NAME, URI.create(uri))); } public static Request Trace(final URI uri) { - return new Request(HttpTrace.METHOD_NAME, uri); + return new Request(new InternalHttpRequest(HttpTrace.METHOD_NAME, uri)); } public static Request Trace(final String uri) { - return new Request(HttpTrace.METHOD_NAME, URI.create(uri)); + return new Request(new InternalHttpRequest(HttpTrace.METHOD_NAME, URI.create(uri))); } public static Request Delete(final URI uri) { - return new Request(HttpDelete.METHOD_NAME, uri); + return new Request(new InternalHttpRequest(HttpDelete.METHOD_NAME, uri)); } public static Request Delete(final String uri) { - return new Request(HttpDelete.METHOD_NAME, URI.create(uri)); + return new Request(new InternalHttpRequest(HttpDelete.METHOD_NAME, URI.create(uri))); } public static Request Options(final URI uri) { - return new Request(HttpOptions.METHOD_NAME, uri); + return new Request(new InternalHttpRequest(HttpOptions.METHOD_NAME, uri)); } public static Request Options(final String uri) { - return new Request(HttpOptions.METHOD_NAME, URI.create(uri)); + return new Request(new InternalHttpRequest(HttpOptions.METHOD_NAME, URI.create(uri))); } - Request(final String method, final URI requestURI) { + Request(final InternalHttpRequest request) { super(); - this.request = new InternalHttpRequest(method, requestURI); + this.request = request; this.configBuilder = RequestConfig.custom(); } @@ -333,10 +333,24 @@ public class Request { return body(new InternalByteArrayEntity(b)); } + /** + * @since 4.4 + */ + public Request bodyByteArray(final byte[] b, final ContentType contentType) { + return body(new InternalByteArrayEntity(b, contentType)); + } + public Request bodyByteArray(final byte[] b, final int off, final int len) { return body(new InternalByteArrayEntity(b, off, len)); } + /** + * @since 4.4 + */ + public Request bodyByteArray(final byte[] b, final int off, final int len, final ContentType contentType) { + return body(new InternalByteArrayEntity(b, off, len, contentType)); + } + public Request bodyStream(final InputStream instream) { return body(new InternalInputStreamEntity(instream, -1, null)); }