~ubuntu-branches/ubuntu/trusty/httpcomponents-core/trusty

« back to all changes in this revision

Viewing changes to src/docbkx/advanced.xml

  • Committer: Bazaar Package Importer
  • Author(s): David Paleino
  • Date: 2010-06-12 08:37:34 UTC
  • Revision ID: james.westby@ubuntu.com-20100612083734-1y8kp6qm4sjk60az
Tags: upstream-4.0.1
ImportĀ upstreamĀ versionĀ 4.0.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?xml version="1.0" encoding="UTF-8"?>
 
2
<!DOCTYPE preface PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
 
3
                 "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
 
4
<!-- 
 
5
   $HeadURL:$
 
6
   $Revision:$
 
7
   $Date:$
 
8
 
 
9
   ====================================================================
 
10
   Licensed to the Apache Software Foundation (ASF) under one
 
11
   or more contributor license agreements.  See the NOTICE file
 
12
   distributed with this work for additional information
 
13
   regarding copyright ownership.  The ASF licenses this file
 
14
   to you under the Apache License, Version 2.0 (the
 
15
   "License"); you may not use this file except in compliance
 
16
   with the License.  You may obtain a copy of the License at
 
17
 
 
18
     http://www.apache.org/licenses/LICENSE-2.0
 
19
 
 
20
   Unless required by applicable law or agreed to in writing,
 
21
   software distributed under the License is distributed on an
 
22
   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 
23
   KIND, either express or implied.  See the License for the
 
24
   specific language governing permissions and limitations
 
25
   under the License.
 
26
   ====================================================================
 
27
 
 
28
-->
 
29
<chapter id="advanced">
 
30
    <title>Advanced topics</title>
 
31
    <section>
 
32
        <title>HTTP message parsing and formatting framework</title>
 
33
        <para>
 
34
        HTTP message processing framework is designed to be expressive and flexible while remaining 
 
35
        memory efficient and fast. HttpCore HTTP message processing code achieves near zero 
 
36
        intermediate garbage and near zero-copy buffering for its parsing and formatting 
 
37
        operations. The same HTTP message parsing and formatting API and implementations are used 
 
38
        by both the blocking and non-blocking transport implementations, which helps ensure a 
 
39
        consistent behavior of HTTP services regardless of the I/O model.
 
40
        </para>
 
41
        <section>
 
42
            <title>HTTP line parsing and formatting</title>
 
43
            <para>
 
44
            HttpCore utilizes a number of low level components for all its line parsing and 
 
45
            formatting methods. 
 
46
            </para>
 
47
            <para>
 
48
            <classname>CharArrayBuffer</classname> represents a sequence of characters, usually a 
 
49
            single line in an HTTP message stream such as a request line, a status line or a 
 
50
            header. Internally <classname>CharArrayBuffer</classname> is backed by an array of 
 
51
            chars, which can be expanded to accommodate more input if needed. <classname>
 
52
            CharArrayBuffer</classname> also provides a number of utility methods for manipulating 
 
53
            content of the buffer, storing more data and retrieving subsets of data.
 
54
            </para>
 
55
            <programlisting><![CDATA[
 
56
CharArrayBuffer buf = new CharArrayBuffer(64); 
 
57
buf.append("header:  data ");
 
58
int i = buf.indexOf(':');
 
59
String s = buf.substringTrimmed(i + 1, buf.length());
 
60
System.out.println(s);
 
61
System.out.println(s.length());
 
62
]]></programlisting>
 
63
            <para>stdout &gt;</para>
 
64
            <programlisting><![CDATA[
 
65
data
 
66
4
 
67
]]></programlisting>
 
68
            <para>
 
69
            <classname>ParserCursor</classname> represents a context of a parsing operation: the 
 
70
            bounds limiting the scope of the parsing operation and the current position the parsing 
 
71
            operation is expected to start at. 
 
72
            </para>
 
73
            <programlisting><![CDATA[
 
74
CharArrayBuffer buf = new CharArrayBuffer(64); 
 
75
buf.append("header:  data ");
 
76
int i = buf.indexOf(':');
 
77
ParserCursor cursor = new ParserCursor(0, buf.length()); 
 
78
cursor.updatePos(i + 1);
 
79
System.out.println(cursor);
 
80
]]></programlisting>
 
81
            <para>stdout &gt;</para>
 
82
            <programlisting><![CDATA[
 
83
[0>7>14]
 
84
]]></programlisting>
 
85
            <para>
 
86
            <interfacename>LineParser</interfacename> is the interface for parsing lines in the 
 
87
            head section of an HTTP message. There are individual methods for parsing a request 
 
88
            line, a status line, or a header line. The lines to parse are passed in memory, the 
 
89
            parser does not depend on any specific I/O mechanism.
 
90
            </para>
 
91
            <programlisting><![CDATA[
 
92
CharArrayBuffer buf = new CharArrayBuffer(64); 
 
93
buf.append("HTTP/1.1 200");
 
94
ParserCursor cursor = new ParserCursor(0, buf.length()); 
 
95
 
 
96
LineParser parser = new BasicLineParser();
 
97
ProtocolVersion ver = parser.parseProtocolVersion(buf, cursor);
 
98
System.out.println(ver);
 
99
System.out.println(buf.substringTrimmed(
 
100
    cursor.getPos(), 
 
101
    cursor.getUpperBound()));
 
102
]]></programlisting>
 
103
            <para>stdout &gt;</para>
 
104
            <programlisting><![CDATA[
 
105
HTTP/1.1
 
106
200
 
107
]]></programlisting>
 
108
            <programlisting><![CDATA[
 
109
CharArrayBuffer buf = new CharArrayBuffer(64); 
 
110
buf.append("HTTP/1.1 200 OK");
 
111
ParserCursor cursor = new ParserCursor(0, buf.length()); 
 
112
LineParser parser = new BasicLineParser();
 
113
StatusLine sl = parser.parseStatusLine(buf, cursor);
 
114
System.out.println(sl.getReasonPhrase());
 
115
]]></programlisting>
 
116
            <para>stdout &gt;</para>
 
117
            <programlisting><![CDATA[
 
118
OK
 
119
]]></programlisting>
 
120
            <para>
 
121
            <interfacename>LineFormatter</interfacename> for formatting elements of the head 
 
122
            section of an HTTP message. This is the complement to <interfacename>LineParser
 
123
            </interfacename>. There are individual methods for formatting a request line, a status 
 
124
            line, or a header line. 
 
125
            </para>
 
126
            <para>
 
127
            Please note the formatting does not include the trailing line break sequence 
 
128
            <literal>CR-LF</literal>.
 
129
            </para>
 
130
            <programlisting><![CDATA[
 
131
CharArrayBuffer buf = new CharArrayBuffer(64); 
 
132
LineFormatter formatter = new BasicLineFormatter();
 
133
formatter.formatRequestLine(buf, 
 
134
    new BasicRequestLine("GET", "/", HttpVersion.HTTP_1_1));
 
135
System.out.println(buf.toString());
 
136
formatter.formatHeader(buf, 
 
137
    new BasicHeader("Content-Type", "text/plain"));
 
138
System.out.println(buf.toString());
 
139
]]></programlisting>
 
140
            <para>stdout &gt;</para>
 
141
            <programlisting><![CDATA[
 
142
GET / HTTP/1.1
 
143
Content-Type: text/plain
 
144
]]></programlisting>
 
145
            <para>
 
146
            <interfacename>HeaderValueParser</interfacename> is the interface for parsing header 
 
147
            values into elements. 
 
148
            </para>
 
149
            <programlisting><![CDATA[
 
150
CharArrayBuffer buf = new CharArrayBuffer(64); 
 
151
HeaderValueParser parser = new BasicHeaderValueParser();
 
152
buf.append("name1=value1; param1=p1, " + 
 
153
    "name2 = \"value2\", name3  = value3");
 
154
ParserCursor cursor = new ParserCursor(0, buf.length()); 
 
155
System.out.println(parser.parseHeaderElement(buf, cursor));
 
156
System.out.println(parser.parseHeaderElement(buf, cursor));
 
157
System.out.println(parser.parseHeaderElement(buf, cursor));
 
158
]]></programlisting>
 
159
            <para>stdout &gt;</para>
 
160
            <programlisting><![CDATA[
 
161
name1=value1; param1=p1
 
162
name2=value2
 
163
name3=value3
 
164
]]></programlisting>
 
165
            <para>
 
166
            <interfacename>HeaderValueFormatter</interfacename> is the interface for formatting 
 
167
            elements of a header value. This is the complement to <interfacename>HeaderValueParser
 
168
            </interfacename>.
 
169
            </para>
 
170
            <programlisting><![CDATA[
 
171
CharArrayBuffer buf = new CharArrayBuffer(64); 
 
172
HeaderValueFormatter formatter = new BasicHeaderValueFormatter();
 
173
HeaderElement[] hes = new HeaderElement[] {
 
174
        new BasicHeaderElement("name1", "value1", 
 
175
                new NameValuePair[] {
 
176
                    new BasicNameValuePair("param1", "p1")} ),
 
177
        new BasicHeaderElement("name2", "value2"), 
 
178
        new BasicHeaderElement("name3", "value3"), 
 
179
};
 
180
formatter.formatElements(buf, hes, true);
 
181
System.out.println(buf.toString());
 
182
]]></programlisting>
 
183
            <para>stdout &gt;</para>
 
184
            <programlisting><![CDATA[
 
185
name1="value1"; param1="p1", name2="value2", name3="value3"
 
186
]]></programlisting>
 
187
        </section>
 
188
        <section>
 
189
            <title>HTTP message streams and session I/O buffers</title>
 
190
            <para>
 
191
            HttpCore provides a number of utility classes for the blocking and non-blocking I/O 
 
192
            models that facilitate the processing of HTTP message streams, simplify handling of 
 
193
            <literal>CR-LF</literal> delimited lines in HTTP messages and manage intermediate data 
 
194
            buffering. 
 
195
            </para>
 
196
            <para>
 
197
            HTTP connection implementations usually rely on session input/output buffers for 
 
198
            reading and writing data from and to an HTTP message stream. Session input/output 
 
199
            buffer implementations are I/O model specific and are optimized either for blocking or 
 
200
            non-blocking operations.
 
201
            </para>
 
202
            <para>
 
203
            Blocking HTTP connections use socket bound session buffers to transfer data. Session 
 
204
            buffer interfaces are similar to <classname>java.io.InputStream</classname> / 
 
205
            <classname>java.io.OutputStream</classname> classes, but they also provide methods for 
 
206
            reading and writing <literal>CR-LF</literal> delimited lines. 
 
207
            </para>
 
208
            <programlisting><![CDATA[
 
209
Socket socket1;
 
210
Socket socket2;
 
211
HttpParams params = new BasicHttpParams(); 
 
212
SessionInputBuffer inbuffer = new SocketInputBuffer(
 
213
    socket1, 4096, params);
 
214
SessionOutputBuffer outbuffer = new SocketOutputBuffer(
 
215
    socket2, 4096, params);
 
216
 
 
217
CharArrayBuffer linebuf = new CharArrayBuffer(1024); 
 
218
inbuffer.readLine(linebuf);
 
219
outbuffer.writeLine(linebuf);
 
220
]]></programlisting>
 
221
            <para>
 
222
            Non-blocking HTTP connections use session buffers optimized for reading and writing 
 
223
            data from and to non-blocking NIO channels. NIO session input/output sessions help deal 
 
224
            with <literal>CR-LF</literal> delimited lines in a non-blocking I/O mode.  
 
225
            </para>
 
226
            <programlisting><![CDATA[
 
227
ReadableByteChannel channel1;
 
228
WritableByteChannel channel2;
 
229
 
 
230
HttpParams params = new BasicHttpParams(); 
 
231
SessionInputBuffer inbuffer = new SessionInputBufferImpl(
 
232
    4096, 1024, params);
 
233
SessionOutputBuffer outbuffer = new SessionOutputBufferImpl(
 
234
    4096, 1024, params);
 
235
 
 
236
CharArrayBuffer linebuf = new CharArrayBuffer(1024); 
 
237
boolean endOfStream = false;
 
238
int bytesRead = inbuffer.fill(channel1);
 
239
if (bytesRead == -1) {
 
240
    endOfStream = true;
 
241
}
 
242
if (inbuffer.readLine(linebuf, endOfStream)) {
 
243
    outbuffer.writeLine(linebuf);
 
244
}
 
245
if (outbuffer.hasData()) {
 
246
    outbuffer.flush(channel2);
 
247
}
 
248
]]></programlisting>
 
249
        </section>
 
250
        <section>
 
251
            <title>HTTP message parsers and formatter</title>
 
252
            <para>
 
253
            HttpCore also provides a coarse-grained facade type of interfaces for parsing and 
 
254
            formatting of HTTP messages. Default implementations of those interfaces build upon the 
 
255
            functionality provided by <interfacename>SessionInputBuffer</interfacename> / 
 
256
            <interfacename>SessionOutputBuffer</interfacename> and <interfacename>HttpLineParser
 
257
            </interfacename>/ <interfacename>HttpLineFormatter</interfacename> implementations.
 
258
            </para>
 
259
            <para>
 
260
            Example of HTTP request parsing / writing for blocking HTTP connections:
 
261
            </para>
 
262
            <programlisting><![CDATA[
 
263
SessionInputBuffer inbuffer;
 
264
SessionOutputBuffer outbuffer;
 
265
 
 
266
HttpParams params = new BasicHttpParams();
 
267
 
 
268
HttpMessageParser requestParser = new HttpRequestParser(
 
269
        inbuffer, 
 
270
        new BasicLineParser(), 
 
271
        new DefaultHttpRequestFactory(),
 
272
        params); 
 
273
 
 
274
HttpRequest request = (HttpRequest) requestParser.parse();
 
275
 
 
276
HttpMessageWriter requestWriter = new HttpRequestWriter(
 
277
        outbuffer, 
 
278
        new BasicLineFormatter(), 
 
279
        params);
 
280
 
 
281
requestWriter.write(request);
 
282
]]></programlisting>
 
283
            <para>
 
284
            Example of HTTP response parsing / writing for blocking HTTP connections:
 
285
            </para>
 
286
            <programlisting><![CDATA[
 
287
SessionInputBuffer inbuffer;
 
288
SessionOutputBuffer outbuffer;
 
289
 
 
290
HttpParams params = new BasicHttpParams();
 
291
 
 
292
HttpMessageParser responseParser = new HttpResponseParser(
 
293
        inbuffer, 
 
294
        new BasicLineParser(), 
 
295
        new DefaultHttpResponseFactory(),
 
296
        params); 
 
297
 
 
298
HttpResponse response = (HttpResponse) responseParser.parse();
 
299
 
 
300
HttpMessageWriter responseWriter = new HttpResponseWriter(
 
301
        outbuffer, 
 
302
        new BasicLineFormatter(), 
 
303
        params);
 
304
 
 
305
responseWriter.write(response);
 
306
]]></programlisting>
 
307
            <para>
 
308
            Example of HTTP request parsing / writing for non-blocking HTTP connections:
 
309
            </para>
 
310
            <programlisting><![CDATA[
 
311
SessionInputBuffer inbuffer;
 
312
SessionOutputBuffer outbuffer;
 
313
 
 
314
HttpParams params = new BasicHttpParams();
 
315
 
 
316
NHttpMessageParser requestParser = new HttpRequestParser(
 
317
        inbuffer, 
 
318
        new BasicLineParser(), 
 
319
        new DefaultHttpRequestFactory(),
 
320
        params); 
 
321
 
 
322
HttpRequest request = (HttpRequest) requestParser.parse();
 
323
 
 
324
NHttpMessageWriter requestWriter = new HttpRequestWriter(
 
325
        outbuffer, 
 
326
        new BasicLineFormatter(), 
 
327
        params);
 
328
 
 
329
requestWriter.write(request);
 
330
]]></programlisting>
 
331
            <para>
 
332
            Example of HTTP response parsing / writing for non-blocking HTTP connections:
 
333
            </para>
 
334
            <programlisting><![CDATA[
 
335
SessionInputBuffer inbuffer;
 
336
SessionOutputBuffer outbuffer;
 
337
 
 
338
HttpParams params = new BasicHttpParams();
 
339
 
 
340
NHttpMessageParser responseParser = new HttpResponseParser(
 
341
        inbuffer, 
 
342
        new BasicLineParser(), 
 
343
        new DefaultHttpResponseFactory(),
 
344
        params); 
 
345
 
 
346
HttpResponse response = (HttpResponse) responseParser.parse();
 
347
 
 
348
NHttpMessageWriter responseWriter = new HttpResponseWriter(
 
349
        outbuffer, 
 
350
        new BasicLineFormatter(), 
 
351
        params);
 
352
 
 
353
responseWriter.write(response);
 
354
]]></programlisting>
 
355
        </section>
 
356
        <section>
 
357
            <title>HTTP header parsing on demand</title>
 
358
            <para>
 
359
            The default implementations of <interfacename>HttpMessageParser</interfacename> and 
 
360
            <interfacename>NHttpMessageParser</interfacename> interfaces do not parse HTTP headers 
 
361
            immediately. Parsing of header value is deferred until its properties are accessed. 
 
362
            Those headers that are never used by the application will not be parsed at all. The
 
363
            <classname>CharArrayBuffer</classname> backing the header can be obtained through an 
 
364
            optional <interfacename>FormattedHeader</interfacename> interface.
 
365
            </para>
 
366
            <programlisting><![CDATA[
 
367
Header h1 = response.getFirstHeader("Content-Type");
 
368
if (h1 instanceof FormattedHeader) {
 
369
    CharArrayBuffer buf = ((FormattedHeader) h1).getBuffer();
 
370
    System.out.println(buf);
 
371
}
 
372
]]></programlisting>
 
373
        </section>
 
374
    </section>
 
375
    <section>
 
376
        <title>Customizing HTTP connections</title>
 
377
        <para>
 
378
        One can customize the way HTTP connections parse and format HTTP messages by extending the 
 
379
        default implementations and overriding factory methods and replacing the default parser or 
 
380
        formatter implementations with a custom one. 
 
381
        </para>
 
382
        <para>
 
383
        For blocking HTTP connections one also can provide custom implementation of session 
 
384
        input/output buffers.
 
385
        </para>
 
386
        <programlisting><![CDATA[
 
387
class MyDefaultNHttpClientConnection 
 
388
                        extends DefaultNHttpClientConnection {
 
389
 
 
390
    public MyDefaultNHttpClientConnection(
 
391
            IOSession session,
 
392
            HttpResponseFactory responseFactory,
 
393
            ByteBufferAllocator allocator,
 
394
            HttpParams params) {
 
395
        super(session, responseFactory, allocator, params);
 
396
    }
 
397
    
 
398
    @Override
 
399
    protected NHttpMessageWriter createRequestWriter(
 
400
            SessionOutputBuffer buffer, 
 
401
            HttpParams params) {
 
402
        return new HttpRequestWriter(
 
403
            buffer, new BasicLineFormatter(), params);
 
404
    }
 
405
 
 
406
    @Override
 
407
    protected NHttpMessageParser createResponseParser(
 
408
            SessionInputBuffer buffer, 
 
409
            HttpResponseFactory responseFactory, 
 
410
            HttpParams params) {
 
411
        return new HttpResponseParser(
 
412
            buffer, new BasicLineParser(), responseFactory, params);
 
413
    }
 
414
    
 
415
};
 
416
]]></programlisting>
 
417
        <para>
 
418
        For non-blocking HTTP connection implementation one can replace the default HTTP message 
 
419
        parser and formatter implementations. The session input/output buffer implementations can 
 
420
        be overridden at the I/O reactor level.
 
421
        </para>
 
422
        <programlisting><![CDATA[
 
423
class MyDefaultHttpClientConnection 
 
424
                        extends DefaultHttpClientConnection {
 
425
 
 
426
    @Override
 
427
    protected SessionInputBuffer createSessionInputBuffer(
 
428
            Socket socket, 
 
429
            int buffersize, 
 
430
            HttpParams params) throws IOException {
 
431
        return new MySocketInputBuffer(socket, buffersize, params);
 
432
    }
 
433
 
 
434
    @Override
 
435
    protected SessionOutputBuffer createSessionOutputBuffer(
 
436
            Socket socket, 
 
437
            int buffersize, 
 
438
            HttpParams params) throws IOException {
 
439
        return new MySocketOutputBuffer(socket, buffersize, params);
 
440
    }
 
441
 
 
442
    @Override
 
443
    protected HttpMessageWriter createRequestWriter(
 
444
            SessionOutputBuffer buffer, 
 
445
            HttpParams params) {
 
446
        return new MyHttpRequestWriter(
 
447
            buffer, new BasicLineFormatter(), params);
 
448
    }
 
449
 
 
450
    @Override
 
451
    protected HttpMessageParser createResponseParser(
 
452
            SessionInputBuffer buffer, 
 
453
            HttpResponseFactory responseFactory, 
 
454
            HttpParams params) {
 
455
        return new MyHttpResponseParser(
 
456
        buffer, new BasicLineParser(), responseFactory, params);
 
457
    }    
 
458
    
 
459
};
 
460
]]></programlisting>
 
461
    </section>
 
462
</chapter>