| <?xml version="1.0" encoding="UTF-8"?> |
| <!DOCTYPE preface PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" |
| "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd"> |
| <!-- |
| ==================================================================== |
| 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. |
| ==================================================================== |
| |
| --> |
| <chapter id="fluent"> |
| <title>Fluent API</title> |
| <section> |
| <title>Easy to use facade API</title> |
| <para> |
| As of version of 4.2 HttpClient comes with an easy to use facade API based on the concept |
| of a fluent interface. Fluent facade API exposes only the most fundamental functions of |
| HttpClient and is intended for simple use cases that do not require the full flexibility of |
| HttpClient. For instance, fluent facade API relieves the users from having to deal with |
| connection management and resource deallocation. |
| </para> |
| <para>Here are several examples of HTTP requests executed through the HC fluent API</para> |
| <programlisting><![CDATA[ |
| // Execute a GET with timeout settings and return response content as String. |
| Request.Get("http://somehost/") |
| .connectTimeout(1000) |
| .socketTimeout(1000) |
| .execute().returnContent().asString(); |
| ]]> |
| </programlisting> |
| <programlisting><![CDATA[ |
| // 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(); |
| ]]> |
| </programlisting> |
| <programlisting><![CDATA[ |
| // 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") |
| .viaProxy(new HttpHost("myproxy", 8080)) |
| .bodyForm(Form.form().add("username", "vip").add("password", "secret").build()) |
| .execute().saveContent(new File("result.dump")); |
| ]]> |
| </programlisting> |
| <para>One can also use <classname>Executor</classname> directly in order to execute requests in |
| a specific security context whereby authentication details are cached and re-used for |
| subsequent requests. |
| </para> |
| <programlisting><![CDATA[ |
| Executor executor = Executor.newInstance() |
| .auth(new HttpHost("somehost"), "username", "password") |
| .auth(new HttpHost("myproxy", 8080), "username", "password") |
| .authPreemptive(new HttpHost("myproxy", 8080)); |
| |
| executor.execute(Request.Get("http://somehost/")) |
| .returnContent().asString(); |
| |
| executor.execute(Request.Post("http://somehost/do-stuff") |
| .useExpectContinue() |
| .bodyString("Important stuff", ContentType.DEFAULT_TEXT)) |
| .returnContent().asString(); |
| ]]> |
| </programlisting> |
| <section> |
| <title>Response handling</title> |
| <para>The fluent facade API generally relieves the users from having to deal with |
| connection management and resource deallocation. In most cases, though, this comes at |
| a price of having to buffer content of response messages in memory. It is highly |
| recommended to use <interfacename>ResponseHandler</interfacename> for HTTP response |
| processing in order to avoid having to buffer content in memory.</para> |
| <programlisting><![CDATA[ |
| 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); |
| } |
| } |
| |
| }); |
| ]]> |
| </programlisting> |
| </section> |
| </section> |
| </chapter> |