13
13
14
14
package org .asynchttpclient .providers .grizzly .bodyhandler ;
15
15
16
+ import org .asynchttpclient .Body ;
17
+ import org .asynchttpclient .Part ;
16
18
import org .asynchttpclient .Request ;
19
+ import org .asynchttpclient .multipart .MultipartBody ;
17
20
import org .asynchttpclient .multipart .MultipartRequestEntity ;
21
+ import org .asynchttpclient .providers .grizzly .FeedableBodyGenerator ;
22
+ import org .asynchttpclient .providers .grizzly .GrizzlyAsyncHttpProvider ;
18
23
import org .asynchttpclient .util .AsyncHttpProviderUtils ;
19
24
import org .glassfish .grizzly .Buffer ;
20
25
import org .glassfish .grizzly .filterchain .FilterChainContext ;
21
- import org .glassfish .grizzly .http .HttpContent ;
22
26
import org .glassfish .grizzly .http .HttpRequestPacket ;
27
+ import org .glassfish .grizzly .memory .Buffers ;
23
28
import org .glassfish .grizzly .memory .MemoryManager ;
24
- import org .glassfish .grizzly .utils .BufferOutputStream ;
25
29
26
30
import java .io .IOException ;
31
+ import java .util .List ;
27
32
28
33
import static org .asynchttpclient .util .MiscUtil .isNonEmpty ;
29
34
@@ -42,25 +47,70 @@ public boolean doHandle(final FilterChainContext ctx,
42
47
final HttpRequestPacket requestPacket )
43
48
throws IOException {
44
49
45
- MultipartRequestEntity mre =
50
+ final List <Part > parts = request .getParts ();
51
+ final MultipartRequestEntity mre =
46
52
AsyncHttpProviderUtils .createMultipartRequestEntity (
47
- request .getParts (),
48
- request .getHeaders ());
49
- requestPacket .setContentLengthLong (mre .getContentLength ());
50
- requestPacket .setContentType (mre .getContentType ());
51
- final MemoryManager mm = ctx .getMemoryManager ();
52
- Buffer b = mm .allocate (512 );
53
- BufferOutputStream o = new BufferOutputStream (mm , b , true );
54
- mre .writeRequest (o );
55
- b = o .getBuffer ();
56
- b .trim ();
57
- if (b .hasRemaining ()) {
58
- final HttpContent content = requestPacket .httpContentBuilder ().content (b ).build ();
59
- content .setLast (true );
60
- ctx .write (content , ((!requestPacket .isCommitted ()) ? ctx .getTransportContext ().getCompletionHandler () : null ));
53
+ parts , request .getHeaders ());
54
+ final long contentLength = mre .getContentLength ();
55
+ final String contentType = mre .getContentType ();
56
+ requestPacket .setContentLengthLong (contentLength );
57
+ requestPacket .setContentType (contentType );
58
+ if (GrizzlyAsyncHttpProvider .LOGGER .isDebugEnabled ()) {
59
+ GrizzlyAsyncHttpProvider .LOGGER .debug (
60
+ "REQUEST(modified): contentLength={}, contentType={}" ,
61
+ new Object []{
62
+ requestPacket .getContentLength (),
63
+ requestPacket .getContentType ()
64
+ });
61
65
}
62
66
63
- return true ;
67
+ final FeedableBodyGenerator generator = new FeedableBodyGenerator () {
68
+ @ Override
69
+ public Body createBody () throws IOException {
70
+ return new MultipartBody (parts , contentType ,
71
+ String .valueOf (contentLength ));
72
+ }
73
+ };
74
+ generator .setFeeder (new FeedableBodyGenerator .BaseFeeder (generator ) {
75
+ @ Override
76
+ public void flush () throws IOException {
77
+ final Body bodyLocal = feedableBodyGenerator .createBody ();
78
+ try {
79
+ final MemoryManager mm = ctx .getMemoryManager ();
80
+ boolean last = false ;
81
+ while (!last ) {
82
+ Buffer buffer = mm .allocate (BodyHandler .MAX_CHUNK_SIZE );
83
+ buffer .allowBufferDispose (true );
84
+ final long readBytes =
85
+ bodyLocal .read (buffer .toByteBuffer ());
86
+ if (readBytes > 0 ) {
87
+ buffer .position ((int ) readBytes );
88
+ buffer .trim ();
89
+ } else {
90
+ buffer .dispose ();
91
+ if (readBytes < 0 ) {
92
+ last = true ;
93
+ buffer = Buffers .EMPTY_BUFFER ;
94
+ } else {
95
+ throw new IllegalStateException (
96
+ "MultipartBody unexpectedly returned 0 bytes available" );
97
+ }
98
+ }
99
+ feed (buffer , last );
100
+ }
101
+ } finally {
102
+ if (bodyLocal != null ) {
103
+ try {
104
+ bodyLocal .close ();
105
+ } catch (IOException ignore ) {
106
+ }
107
+ }
108
+ }
109
+ }
110
+ });
111
+ generator .initializeAsynchronousTransfer (ctx , requestPacket );
112
+ return false ;
113
+
64
114
}
65
115
66
116
} // END PartsBodyHandler
0 commit comments