9
9
import java .io .OutputStream ;
10
10
import java .net .HttpURLConnection ;
11
11
import java .net .URL ;
12
+ import java .nio .file .Files ;
13
+ import java .nio .file .Path ;
12
14
import java .util .List ;
13
15
import java .util .Map ;
14
16
import java .util .Map .Entry ;
15
17
import java .util .stream .Collectors ;
16
18
17
19
import static java .nio .charset .StandardCharsets .UTF_8 ;
20
+ import static java .nio .file .Files .newOutputStream ;
18
21
19
22
class UrlOutputStream extends OutputStream {
20
- // Allow streaming, using a chunk size that is similar to a typical NDJSON
21
- // message length
22
- public static final int CHUNK_LENGTH = 256 ;
23
- private final HttpURLConnection urlConnection ;
24
- private final OutputStream outputStream ;
25
-
26
- private String method ;
27
- private URL url ;
28
- private final Map <String , List <String >> requestHeaders ;
23
+ private final CurlOption option ;
24
+ private final Path temp ;
25
+ private final OutputStream tempOutputStream ;
29
26
30
27
UrlOutputStream (CurlOption option ) throws IOException {
31
- this .method = option .getMethod ().name ();
32
- this .url = option .getUri ().toURL ();
33
-
34
- urlConnection = (HttpURLConnection ) this .url .openConnection ();
35
- for (Entry <String , String > header : option .getHeaders ()) {
36
- urlConnection .setRequestProperty (header .getKey (), header .getValue ());
37
- }
38
- urlConnection .setRequestMethod (this .method );
39
- urlConnection .setDoOutput (true );
40
- urlConnection .setChunkedStreamingMode (CHUNK_LENGTH );
41
- urlConnection .setInstanceFollowRedirects (false );
42
- requestHeaders = urlConnection .getRequestProperties ();
43
- outputStream = urlConnection .getOutputStream ();
28
+ this .option = option ;
29
+ this .temp = Files .createTempFile ("cucumber" , null );
30
+ this .tempOutputStream = newOutputStream (temp );
44
31
}
45
32
46
33
@ Override
47
34
public void write (byte [] buffer , int offset , int count ) throws IOException {
48
- outputStream .write (buffer , offset , count );
35
+ tempOutputStream .write (buffer , offset , count );
49
36
}
50
37
51
38
@ Override
52
39
public void write (byte [] buffer ) throws IOException {
53
- outputStream .write (buffer );
40
+ tempOutputStream .write (buffer );
54
41
}
55
42
56
43
@ Override
57
44
public void write (int b ) throws IOException {
58
- outputStream .write (b );
45
+ tempOutputStream .write (b );
59
46
}
60
47
61
48
@ Override
62
49
public void flush () throws IOException {
63
- outputStream .flush ();
50
+ tempOutputStream .flush ();
64
51
}
65
52
66
53
@ Override
67
54
public void close () throws IOException {
68
- outputStream .close ();
69
- int httpStatus = urlConnection .getResponseCode ();
70
- boolean redirect = httpStatus >= 300 && httpStatus < 400 ;
71
- boolean error = httpStatus >= 400 ;
72
- try (InputStream inputStream = error ? urlConnection .getErrorStream () : urlConnection .getInputStream ()) {
73
- Map <String , List <String >> responseHeaders = urlConnection .getHeaderFields ();
74
- try (BufferedReader br = new BufferedReader (new InputStreamReader (inputStream , UTF_8 ))) {
75
- String responseBody = br .lines ().collect (Collectors .joining (System .lineSeparator ()));
76
- if (error || redirect ) {
77
- String message = generateCurlLikeMessage (this .method , this .url , this .requestHeaders , responseHeaders , responseBody , redirect );
78
- throw new IOException (message );
79
- }
55
+ tempOutputStream .close ();
56
+
57
+ URL url = option .getUri ().toURL ();
58
+ HttpURLConnection urlConnection = (HttpURLConnection ) url .openConnection ();
59
+ for (Entry <String , String > header : option .getHeaders ()) {
60
+ urlConnection .setRequestProperty (header .getKey (), header .getValue ());
61
+ }
62
+ urlConnection .setInstanceFollowRedirects (true );
63
+ urlConnection .setRequestMethod (option .getMethod ().name ());
64
+ urlConnection .setDoOutput (true );
65
+ Map <String , List <String >> requestHeaders = urlConnection .getRequestProperties ();
66
+ try (OutputStream outputStream = urlConnection .getOutputStream ()) {
67
+ Files .copy (temp , outputStream );
68
+ handleResponse (urlConnection , requestHeaders );
69
+ }
70
+ }
71
+
72
+ private static void handleResponse (HttpURLConnection urlConnection , Map <String , List <String >> requestHeaders ) throws IOException {
73
+ Map <String , List <String >> responseHeaders = urlConnection .getHeaderFields ();
74
+ int responseCode = urlConnection .getResponseCode ();
75
+ boolean success = 200 <= responseCode && responseCode < 300 ;
76
+
77
+ InputStream inputStream = urlConnection .getErrorStream () != null ? urlConnection .getErrorStream () : urlConnection .getInputStream ();
78
+ try (BufferedReader br = new BufferedReader (new InputStreamReader (inputStream , UTF_8 ))) {
79
+ String responseBody = br .lines ().collect (Collectors .joining (System .lineSeparator ()));
80
+ if (!success ) {
81
+ String method = urlConnection .getRequestMethod ();
82
+ URL url = urlConnection .getURL ();
83
+ throw createCurlLikeException (method , url , requestHeaders , responseHeaders , responseBody );
80
84
}
81
85
}
82
86
}
83
87
84
- static String generateCurlLikeMessage (
88
+ static IOException createCurlLikeException (
85
89
String method ,
86
90
URL url ,
87
91
Map <String , List <String >> requestHeaders ,
88
92
Map <String , List <String >> responseHeaders ,
89
- String responseBody ,
90
- boolean redirect ) {
91
- return String .format (
92
- "%s:\n > %s %s\n %s%s\n %s" ,
93
- redirect ? "HTTP redirect not supported" : "HTTP request failed" ,
93
+ String responseBody ) {
94
+ return new IOException (String .format (
95
+ "%s:\n > %s %s%s%s%s" ,
96
+ "HTTP request failed" ,
94
97
method ,
95
98
url ,
96
99
headersToString ("> " , requestHeaders ),
97
100
headersToString ("< " , responseHeaders ),
98
101
responseBody
99
- );
102
+ )) ;
100
103
}
101
104
102
105
private static String headersToString (String prefix , Map <String , List <String >> headers ) {
@@ -109,10 +112,12 @@ private static String headersToString(String prefix, Map<String, List<String>> h
109
112
.map (value -> {
110
113
if (header .getKey () == null ) {
111
114
return prefix + value ;
115
+ } else if (header .getValue () == null ) {
116
+ return prefix + header .getKey ();
112
117
} else {
113
- return prefix + ( header .getKey () + ": " ) + value ;
118
+ return prefix + header .getKey () + ": " + value ;
114
119
}
115
120
})
116
- ).collect (Collectors .joining ("\n " ));
121
+ ).collect (Collectors .joining ("\n " , "" , " \n " ));
117
122
}
118
123
}
0 commit comments