Skip to content

Commit 16a0ec5

Browse files
chingor13sduskis
authored andcommitted
Fix handling interrupted uploads (#572)
* Add failing test for an interrupted POST with response * Try to parse the response if we get an IOException when writing content * Adding missing unit test for handling IOException on socket close
1 parent 09ccdf5 commit 16a0ec5

File tree

2 files changed

+130
-0
lines changed

2 files changed

+130
-0
lines changed

google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpRequest.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,12 @@ LowLevelHttpResponse execute(final OutputWriter outputWriter) throws IOException
117117
writeContentToOutputStream(outputWriter, out);
118118

119119
threw = false;
120+
} catch (IOException e) {
121+
// If we've gotten a response back, continue on and try to parse the response. Otherwise,
122+
// re-throw the IOException
123+
if (!hasReponse(connection)) {
124+
throw e;
125+
}
120126
} finally {
121127
try {
122128
out.close();
@@ -150,6 +156,15 @@ LowLevelHttpResponse execute(final OutputWriter outputWriter) throws IOException
150156
}
151157
}
152158

159+
private boolean hasReponse(HttpURLConnection connection) {
160+
try {
161+
return connection.getResponseCode() > 0;
162+
} catch (IOException e) {
163+
// There's some exception trying to parse the response
164+
return false;
165+
}
166+
}
167+
153168
private void writeContentToOutputStream(final OutputWriter outputWriter, final OutputStream out)
154169
throws IOException {
155170
if (writeTimeout == 0) {

google-http-client/src/test/java/com/google/api/client/http/javanet/NetHttpRequestTest.java

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.google.api.client.http.HttpContent;
44
import com.google.api.client.http.InputStreamContent;
5+
import com.google.api.client.http.LowLevelHttpResponse;
56
import com.google.api.client.http.javanet.NetHttpRequest.OutputWriter;
67
import com.google.api.client.testing.http.HttpTesting;
78
import com.google.api.client.testing.http.javanet.MockHttpURLConnection;
@@ -82,4 +83,118 @@ private static void postWithTimeout(int timeout) throws Exception {
8283
request.execute(new SleepingOutputWriter(5000L));
8384
}
8485

86+
@Test
87+
public void testInterruptedWriteWithResponse() throws Exception {
88+
MockHttpURLConnection connection = new MockHttpURLConnection(new URL(HttpTesting.SIMPLE_URL)) {
89+
@Override
90+
public OutputStream getOutputStream() throws IOException {
91+
return new OutputStream() {
92+
@Override
93+
public void write(int b) throws IOException {
94+
throw new IOException("Error writing request body to server");
95+
}
96+
};
97+
}
98+
};
99+
connection.setResponseCode(401);
100+
connection.setRequestMethod("POST");
101+
NetHttpRequest request = new NetHttpRequest(connection);
102+
InputStream is = NetHttpRequestTest.class.getClassLoader().getResourceAsStream("file.txt");
103+
HttpContent content = new InputStreamContent("text/plain", is);
104+
request.setStreamingContent(content);
105+
106+
LowLevelHttpResponse response = request.execute();
107+
assertEquals(401, response.getStatusCode());
108+
}
109+
110+
@Test
111+
public void testInterruptedWriteWithoutResponse() throws Exception {
112+
MockHttpURLConnection connection = new MockHttpURLConnection(new URL(HttpTesting.SIMPLE_URL)) {
113+
@Override
114+
public OutputStream getOutputStream() throws IOException {
115+
return new OutputStream() {
116+
@Override
117+
public void write(int b) throws IOException {
118+
throw new IOException("Error writing request body to server");
119+
}
120+
};
121+
}
122+
};
123+
connection.setRequestMethod("POST");
124+
NetHttpRequest request = new NetHttpRequest(connection);
125+
InputStream is = NetHttpRequestTest.class.getClassLoader().getResourceAsStream("file.txt");
126+
HttpContent content = new InputStreamContent("text/plain", is);
127+
request.setStreamingContent(content);
128+
129+
try {
130+
request.execute();
131+
fail("Expected to throw an IOException");
132+
} catch (IOException e) {
133+
assertEquals("Error writing request body to server", e.getMessage());
134+
}
135+
}
136+
137+
@Test
138+
public void testInterruptedWriteErrorOnResponse() throws Exception {
139+
MockHttpURLConnection connection = new MockHttpURLConnection(new URL(HttpTesting.SIMPLE_URL)) {
140+
@Override
141+
public OutputStream getOutputStream() throws IOException {
142+
return new OutputStream() {
143+
@Override
144+
public void write(int b) throws IOException {
145+
throw new IOException("Error writing request body to server");
146+
}
147+
};
148+
}
149+
150+
@Override
151+
public int getResponseCode() throws IOException {
152+
throw new IOException("Error parsing response code");
153+
}
154+
};
155+
connection.setRequestMethod("POST");
156+
NetHttpRequest request = new NetHttpRequest(connection);
157+
InputStream is = NetHttpRequestTest.class.getClassLoader().getResourceAsStream("file.txt");
158+
HttpContent content = new InputStreamContent("text/plain", is);
159+
request.setStreamingContent(content);
160+
161+
try {
162+
request.execute();
163+
fail("Expected to throw an IOException");
164+
} catch (IOException e) {
165+
assertEquals("Error writing request body to server", e.getMessage());
166+
}
167+
}
168+
169+
@Test
170+
public void testErrorOnClose() throws Exception {
171+
MockHttpURLConnection connection = new MockHttpURLConnection(new URL(HttpTesting.SIMPLE_URL)) {
172+
@Override
173+
public OutputStream getOutputStream() throws IOException {
174+
return new OutputStream() {
175+
@Override
176+
public void write(int b) throws IOException {
177+
return;
178+
}
179+
180+
@Override
181+
public void close() throws IOException {
182+
throw new IOException("Error during close");
183+
}
184+
};
185+
}
186+
};
187+
connection.setRequestMethod("POST");
188+
NetHttpRequest request = new NetHttpRequest(connection);
189+
InputStream is = NetHttpRequestTest.class.getClassLoader().getResourceAsStream("file.txt");
190+
HttpContent content = new InputStreamContent("text/plain", is);
191+
request.setStreamingContent(content);
192+
193+
try {
194+
request.execute();
195+
fail("Expected to throw an IOException");
196+
} catch (IOException e) {
197+
assertEquals("Error during close", e.getMessage());
198+
}
199+
}
85200
}

0 commit comments

Comments
 (0)