Tweaked fluent API

git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@1189929 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Oleg Kalnichevski 2011-10-27 18:50:52 +00:00
parent d8b5071301
commit 41cfb9bbea
9 changed files with 323 additions and 28 deletions

1
.gitignore vendored
View File

@ -2,4 +2,5 @@
.project
.settings
.clover
.externalToolBuilders
target

View File

@ -0,0 +1,72 @@
/*
* ====================================================================
*
* 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.fluent;
import java.io.File;
import org.apache.http.HttpHost;
import org.apache.http.HttpVersion;
import org.apache.http.entity.ContentType;
/**
* This example demonstrates how the he HttpClient fluent API can be used to execute multiple
* requests within the same security context. The Executor class maintains a common context shared
* by all requests executed with it. The Executor is thread-safe and can be used to execute
* requests concurrently from multiple threads of execution.
*/
public class FluentExecutor {
public static void main(String[] args)throws Exception {
Executor executor = Executor.newInstance()
.auth(new HttpHost("somehost"), "username", "password")
.auth(new HttpHost("myproxy", 8080), "username", "password")
.authPreemptive(new HttpHost("myproxy", 8080));
// Execute a GET with timeout settings and return response content as String.
executor.execute(Request.Get("http://somehost/")
.connectTimeout(1000)
.socketTimeout(1000)
).returnContent().asString();
// Execute a POST with the 'expect-continue' handshake, using HTTP/1.1,
// containing a request body as String and return response content as byte array.
executor.execute(Request.Post("http://somehost/do-stuff")
.useExpectContinue()
.version(HttpVersion.HTTP_1_1)
.bodyString("Important stuff", ContentType.DEFAULT_TEXT)
).returnContent().asBytes();
// Execute a POST with a custom header through the proxy containing a request body
// as an HTML form and save the result to the file
executor.execute(Request.Post("http://somehost/some-form")
.addHeader("X-Custom-header", "stuff")
.proxy(new HttpHost("myproxy", 8080))
.bodyForm(Form.form().add("username", "vip").add("password", "secret").build())
).saveContent(new File("result.dump"));
}
}

View File

@ -0,0 +1,64 @@
/*
* ====================================================================
*
* 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.fluent;
import java.io.File;
import org.apache.http.HttpHost;
import org.apache.http.HttpVersion;
import org.apache.http.entity.ContentType;
/**
* This example demonstrates basics of request execution with the HttpClient fluent API.
*/
public class FluentRequests {
public static void main(String[] args)throws Exception {
// Execute a GET with timeout settings and return response content as String.
Request.Get("http://somehost/")
.connectTimeout(1000)
.socketTimeout(1000)
.execute().returnContent().asString();
// Execute a POST with the 'expect-continue' handshake, using HTTP/1.1,
// containing a request body as String and return response content as byte array.
Request.Post("http://somehost/do-stuff")
.useExpectContinue()
.version(HttpVersion.HTTP_1_1)
.bodyString("Important stuff", ContentType.DEFAULT_TEXT)
.execute().returnContent().asBytes();
// Execute a POST with a custom header through the proxy containing a request body
// as an HTML form and save the result to the file
Request.Post("http://somehost/some-form")
.addHeader("X-Custom-header", "stuff")
.proxy(new HttpHost("myproxy", 8080))
.bodyForm(Form.form().add("username", "vip").add("password", "secret").build())
.execute().saveContent(new File("result.dump"));
}
}

View File

@ -0,0 +1,91 @@
/*
* ====================================================================
*
* 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.fluent;
import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpResponseException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.entity.ContentType;
import org.apache.http.protocol.HTTP;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
/**
* This example demonstrates how the HttpClient fluent API can be used to handle HTTP responses
* without buffering content body in memory.
*/
public class FluentResponseHandling {
public static void main(String[] args)throws Exception {
Document result = Request.Get("http://somehost/content")
.execute().handleResponse(new ResponseHandler<Document>() {
public Document handleResponse(final HttpResponse response) throws IOException {
StatusLine statusLine = response.getStatusLine();
HttpEntity entity = response.getEntity();
if (statusLine.getStatusCode() >= 300) {
throw new HttpResponseException(
statusLine.getStatusCode(),
statusLine.getReasonPhrase());
}
if (entity == null) {
throw new ClientProtocolException("Response contains no content");
}
DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
try {
DocumentBuilder docBuilder = dbfac.newDocumentBuilder();
ContentType contentType = ContentType.getOrDefault(entity);
if (!contentType.equals(ContentType.APPLICATION_XML)) {
throw new ClientProtocolException("Unexpected content type:" + contentType);
}
String charset = contentType.getCharset();
if (charset == null) {
charset = HTTP.DEFAULT_CONTENT_CHARSET;
}
return docBuilder.parse(entity.getContent(), charset);
} catch (ParserConfigurationException ex) {
throw new IllegalStateException(ex);
} catch (SAXException ex) {
throw new ClientProtocolException("Malformed XML document", ex);
}
}
});
// Do something useful with the result
System.out.println(result);
}
}

View File

@ -35,6 +35,8 @@ import org.apache.http.protocol.HTTP;
public class Content {
public static final Content NO_CONTENT = new Content(new byte[] {}, ContentType.DEFAULT_BINARY);
private final byte[] raw;
private final ContentType type;

View File

@ -87,8 +87,7 @@ public class Executor {
return auth(authScope, creds);
}
public Executor authPreemptive(final HttpHost host, final Credentials creds) {
auth(host, creds);
public Executor authPreemptive(final HttpHost host) {
this.authCache.put(host, new BasicScheme());
return this;
}
@ -117,13 +116,6 @@ public class Executor {
return auth(host, new NTCredentials(username, password, workstation, domain));
}
public Executor authPreemptive(final HttpHost host,
final String username, final String password) {
auth(host, username, password);
this.authCache.put(host, new BasicScheme());
return this;
}
public Executor clearAuth() {
if (this.credentialsProvider != null) {
this.credentialsProvider.clear();
@ -143,7 +135,7 @@ public class Executor {
return this;
}
public Response exec(
public Response execute(
final Request req) throws ClientProtocolException, IOException {
this.localContext.setAttribute(ClientContext.CREDS_PROVIDER, this.credentialsProvider);
this.localContext.setAttribute(ClientContext.AUTH_CACHE, this.authCache);

View File

@ -0,0 +1,57 @@
/*
* ====================================================================
*
* 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.fluent;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
public class Form {
private final List<NameValuePair> params;
public static Form form() {
return new Form();
}
Form() {
super();
this.params = new ArrayList<NameValuePair>();
}
public Form add(final String name, final String value) {
this.params.add(new BasicNameValuePair(name, value));
return this;
}
public List<NameValuePair> build() {
return new ArrayList<NameValuePair>(this.params);
}
}

View File

@ -26,6 +26,7 @@
package org.apache.http.client.fluent;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
@ -55,6 +56,7 @@ import org.apache.http.client.methods.HttpTrace;
import org.apache.http.conn.params.ConnRoutePNames;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.FileEntity;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.params.CoreConnectionPNames;
@ -139,7 +141,7 @@ public class Request {
return this.request;
}
public Response exec() throws ClientProtocolException, IOException {
public Response execute() throws ClientProtocolException, IOException {
return new Response(Executor.CLIENT.execute(this.request));
}
@ -268,35 +270,43 @@ public class Request {
return this;
}
public Request htmlFormBody(final NameValuePair[] formParams, final String charset) {
public Request bodyForm(final Iterable <? extends NameValuePair> formParams, final String charset) {
try {
return body(new UrlEncodedFormEntity(Arrays.asList(formParams)));
return body(new UrlEncodedFormEntity(formParams));
} catch (UnsupportedEncodingException ex) {
throw new IllegalArgumentException(ex);
}
}
public Request htmlFormBody(final NameValuePair... formParams) {
return htmlFormBody(formParams, HTTP.DEFAULT_CONTENT_CHARSET);
public Request bodyForm(final Iterable <? extends NameValuePair> formParams) {
return bodyForm(formParams, HTTP.DEFAULT_CONTENT_CHARSET);
}
public Request stringBody(final String s, final ContentType contentType) {
public Request bodyForm(final NameValuePair... formParams) {
return bodyForm(Arrays.asList(formParams), HTTP.DEFAULT_CONTENT_CHARSET);
}
public Request bodyString(final String s, final ContentType contentType) {
return body(StringEntity.create(s, contentType));
}
public Request byteArrayBody(final byte[] b) {
public Request bodyFile(final File file, final ContentType contentType) {
return body(new FileEntity(file, contentType));
}
public Request bodyByteArray(final byte[] b) {
return body(new ByteArrayEntity(b));
}
public Request byteArrayBody(final byte[] b, int off, int len) {
public Request bodyByteArray(final byte[] b, int off, int len) {
return body(new ByteArrayEntity(b, off, len));
}
public Request streamBody(final InputStream instream) {
public Request bodyStream(final InputStream instream) {
return body(new InputStreamEntity(instream, -1));
}
public Request streamBody(final InputStream instream, final ContentType contentType) {
public Request bodyStream(final InputStream instream, final ContentType contentType) {
return body(new InputStreamEntity(instream, -1, contentType));
}

View File

@ -56,7 +56,7 @@ public class Response {
}
}
public void dispose() {
private void dispose() {
if (this.consumed) {
return;
}
@ -68,7 +68,12 @@ public class Response {
}
}
public <T> T handle(final ResponseHandler<T> handler) throws ClientProtocolException, IOException {
public void discardContent() {
dispose();
}
public <T> T handleResponse(
final ResponseHandler<T> handler) throws ClientProtocolException, IOException {
assertNotConsumed();
try {
return handler.handleResponse(this.response);
@ -77,8 +82,8 @@ public class Response {
}
}
public Content content() throws ClientProtocolException, IOException {
return handle(new ResponseHandler<Content>() {
public Content returnContent() throws ClientProtocolException, IOException {
return handleResponse(new ResponseHandler<Content>() {
public Content handleResponse(
final HttpResponse response) throws ClientProtocolException, IOException {
@ -89,17 +94,18 @@ public class Response {
statusLine.getReasonPhrase());
}
if (entity != null) {
return new Content(EntityUtils.toByteArray(entity),
return new Content(
EntityUtils.toByteArray(entity),
ContentType.getOrDefault(entity));
} else {
return null;
return Content.NO_CONTENT;
}
}
});
}
public HttpResponse response() throws IOException {
public HttpResponse returnResponse() throws IOException {
assertNotConsumed();
try {
HttpEntity entity = this.response.getEntity();
@ -113,7 +119,7 @@ public class Response {
}
}
public void save(final File file) throws IOException {
public void saveContent(final File file) throws IOException {
assertNotConsumed();
FileOutputStream out = new FileOutputStream(file);
try {