Skip to content

Commit

Permalink
Finish implementation and test of HttpURLConnectionAdapter
Browse files Browse the repository at this point in the history
  • Loading branch information
bitwiseman committed Nov 9, 2021
1 parent 7015783 commit 05087f6
Show file tree
Hide file tree
Showing 4 changed files with 158 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,17 @@ public String getHeaderFieldKey(int n) {

@Override
public void setFixedLengthStreamingMode(int contentLength) {
throw new UnsupportedOperationException("Setting streaming mode is not supported by " + this.getClass());
throw new UnsupportedOperationException();
}

@Override
public void setFixedLengthStreamingMode(long contentLength) {
throw new UnsupportedOperationException("Setting streaming mode is not supported by " + this.getClass());
throw new UnsupportedOperationException();
}

@Override
public void setChunkedStreamingMode(int chunklen) {
throw new UnsupportedOperationException("Setting streaming mode is not supported by " + this.getClass());
throw new UnsupportedOperationException();
}

@Override
Expand All @@ -52,17 +52,17 @@ public String getHeaderField(int n) {

@Override
public void setInstanceFollowRedirects(boolean followRedirects) {
super.setInstanceFollowRedirects(followRedirects);
throw new UnsupportedOperationException();
}

@Override
public boolean getInstanceFollowRedirects() {
return super.getInstanceFollowRedirects();
throw new UnsupportedOperationException();
}

@Override
public void setRequestMethod(String method) throws ProtocolException {
super.setRequestMethod(method);
throw new UnsupportedOperationException();
}

@Override
Expand All @@ -84,7 +84,7 @@ public String getResponseMessage() throws IOException {
public long getHeaderFieldDate(String name, long defaultValue) {
String dateString = getHeaderField(name);
try {
return GitHubClient.parseDate(dateString).getTime();
return Date.parse(dateString);
} catch (Exception e) {
}
return defaultValue;
Expand All @@ -107,7 +107,7 @@ public void setConnectTimeout(int timeout) {

@Override
public int getConnectTimeout() {
return super.getConnectTimeout();
throw new UnsupportedOperationException();
}

@Override
Expand All @@ -117,7 +117,7 @@ public void setReadTimeout(int timeout) {

@Override
public int getReadTimeout() {
return super.getReadTimeout();
throw new UnsupportedOperationException();
}

@Override
Expand Down Expand Up @@ -190,18 +190,18 @@ public long getHeaderFieldLong(String name, long defaultValue) {

@Override
public Object getContent() throws IOException {
return super.getContent();
throw new UnsupportedOperationException();
}

// @Override
// public Object getContent(Class<?>[] classes) throws IOException {
// return super.getContent(classes);
// }
//
// @Override
// public InputStream getInputStream() throws IOException {
// return connectorResponse.bodyStream();
// }
@Override
public Object getContent(Class[] classes) throws IOException {
throw new UnsupportedOperationException();
}

@Override
public InputStream getInputStream() throws IOException {
return connectorResponse.bodyStream();
}

@Override
public OutputStream getOutputStream() throws IOException {
Expand All @@ -215,67 +215,62 @@ public String toString() {

@Override
public void setDoInput(boolean doinput) {
throw new IllegalStateException();
throw new UnsupportedOperationException();
}

@Override
public boolean getDoInput() {
return super.getDoInput();
throw new UnsupportedOperationException();
}

@Override
public void setDoOutput(boolean dooutput) {
throw new IllegalStateException();
throw new UnsupportedOperationException();
}

@Override
public boolean getDoOutput() {
return super.getDoOutput();
throw new UnsupportedOperationException();
}

@Override
public void setAllowUserInteraction(boolean allowuserinteraction) {
super.setAllowUserInteraction(allowuserinteraction);
throw new UnsupportedOperationException();
}

@Override
public void setUseCaches(boolean usecaches) {
throw new IllegalStateException();
throw new UnsupportedOperationException();
}

@Override
public boolean getUseCaches() {
return super.getUseCaches();
throw new UnsupportedOperationException();
}

@Override
public void setIfModifiedSince(long ifmodifiedsince) {
throw new IllegalStateException();
throw new UnsupportedOperationException();
}

@Override
public long getIfModifiedSince() {
String modifiedSince = connectorResponse.request().header("If-Modified-Since");
if (modifiedSince != null) {
return GitHubClient.parseDate(modifiedSince).getTime();
} else {
return 0;
}
return getHeaderFieldDate("If-Modified-Since", 0);
}

@Override
public void setDefaultUseCaches(boolean defaultusecaches) {
throw new IllegalStateException();
throw new UnsupportedOperationException();
}

@Override
public void setRequestProperty(String key, String value) {
throw new IllegalStateException();
throw new UnsupportedOperationException();
}

@Override
public void addRequestProperty(String key, String value) {
throw new IllegalStateException();
throw new UnsupportedOperationException();
}

@Override
Expand Down Expand Up @@ -305,7 +300,7 @@ public void disconnect() {

@Override
public boolean usingProxy() {
return false;
throw new UnsupportedOperationException();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.kohsuke.github.connector.GitHubConnectorRequest;
import org.kohsuke.github.connector.GitHubConnectorResponse;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
Expand Down Expand Up @@ -152,6 +153,11 @@ private static void setRequestMethod(String method, HttpURLConnection connection
*/
static class HttpURLConnectionGitHubConnectorResponse extends GitHubConnectorResponse {

private boolean inputStreamRead = false;
private byte[] inputBytes = null;
private boolean errorStreamRead = false;
private String errorString = null;

@Nonnull
private final HttpURLConnection connection;

Expand All @@ -167,24 +173,41 @@ static class HttpURLConnectionGitHubConnectorResponse extends GitHubConnectorRes
* {@inheritDoc}
*/
public InputStream bodyStream() throws IOException {
return wrapStream(connection.getInputStream());
synchronized (this) {
if (!inputStreamRead) {
try (InputStream stream = wrapStream(connection.getInputStream())) {
if (stream != null) {
inputBytes = IOUtils.toByteArray(stream);
inputStreamRead = true;
}
}
}
}

return inputBytes == null ? null : new ByteArrayInputStream(inputBytes);
}

/**
* {@inheritDoc}
*/
public String errorMessage() {
String result = null;
InputStream stream = null;
try {
stream = connection.getErrorStream();
if (stream != null) {
result = IOUtils.toString(wrapStream(stream), StandardCharsets.UTF_8);
synchronized (this) {
if (!errorStreamRead) {
try (InputStream stream = wrapStream(connection.getErrorStream())) {
if (stream != null) {
errorString = new String(IOUtils.toByteArray(stream), StandardCharsets.UTF_8);
errorStreamRead = true;
}
}
}
}
if (errorString != null) {
result = errorString;
}
} catch (Exception e) {
LOGGER.log(FINER, "Ignored exception get error message", e);
} finally {
IOUtils.closeQuietly(stream);
}
return result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ public void testHandler_WaitStuck() throws Exception {
snapshotNotAllowed();

gitHub = getGitHubBuilder().withEndpoint(mockGitHub.apiServer().baseUrl())
.withRateLimitHandler(new RateLimitHandler() {
.withAbuseLimitHandler(new AbuseLimitHandler() {
@Override
public void onError(IOException e, HttpURLConnection uc) throws IOException {
}
Expand Down
96 changes: 95 additions & 1 deletion src/test/java/org/kohsuke/github/RateLimitHandlerTest.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
package org.kohsuke.github;

import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
import org.apache.commons.io.IOUtils;
import org.hamcrest.Matchers;
import org.junit.Assert;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Map;

import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.core.IsInstanceOf.instanceOf;
Expand Down Expand Up @@ -46,7 +53,94 @@ public void testHandler_Fail() throws Exception {
snapshotNotAllowed();

gitHub = getGitHubBuilder().withEndpoint(mockGitHub.apiServer().baseUrl())
.withRateLimitHandler(RateLimitHandler.FAIL)
.withRateLimitHandler(new RateLimitHandler() {
@Override
public void onError(IOException e, HttpURLConnection uc) throws IOException {
// Verify
assertThat(uc.getDate(), Matchers.greaterThanOrEqualTo(new Date().getTime() - 10000));
assertThat(uc.getExpiration(), equalTo(0L));
assertThat(uc.getIfModifiedSince(), equalTo(0L));
assertThat(uc.getLastModified(), equalTo(1581014017000L));
assertThat(uc.getRequestMethod(), equalTo("GET"));
assertThat(uc.getResponseCode(), equalTo(403));
assertThat(uc.getResponseMessage(), equalTo("403 Forbidden"));
assertThat(uc.getURL().toString(), endsWith("/repos/hub4j-test-org/temp-testHandler_Fail"));
assertThat(uc.getHeaderFieldInt("X-RateLimit-Limit", 10), equalTo(5000));
assertThat(uc.getHeaderFieldInt("X-RateLimit-Remaining", 10), equalTo(0));
assertThat(uc.getHeaderFieldInt("X-Foo", 20), equalTo(20));
assertThat(uc.getHeaderFieldLong("X-RateLimit-Limit", 15L), equalTo(5000L));
assertThat(uc.getHeaderFieldLong("X-RateLimit-Remaining", 15L), equalTo(0L));
assertThat(uc.getHeaderFieldLong("X-Foo", 20L), equalTo(20L));

assertThat(uc.getContentEncoding(), nullValue());
assertThat(uc.getContentType(), equalTo("application/json; charset=utf-8"));
assertThat(uc.getContentLength(), equalTo(-1));

// getting an input stream in an error case should throw
IOException ioEx = Assert.assertThrows(IOException.class, () -> uc.getInputStream());

InputStream errorStream = uc.getErrorStream();
assertThat(errorStream, notNullValue());
String error = IOUtils.toString(errorStream, StandardCharsets.UTF_8);
assertThat(error, containsString("Must have push access to repository"));

// calling again should still error
ioEx = Assert.assertThrows(IOException.class, () -> uc.getInputStream());

assertThat(uc.getHeaderFields(), instanceOf(Map.class));
assertThat(uc.getHeaderFields().size(), equalTo(27));
assertThat(uc.getHeaderField("Status"), equalTo("403 Forbidden"));
assertThat(uc.getHeaderField(0), equalTo("HTTP/1.1 403 Forbidden"));
assertThat(uc.getHeaderFieldKey(0), nullValue());
assertThat(uc.getHeaderFieldKey(1), equalTo("Access-Control-Allow-Origin"));

assertThat(uc.getRequestProperties(), instanceOf(Map.class));
assertThat(uc.getRequestProperties().size(), equalTo(3));
assertThat(uc.getRequestProperty("Accept"), equalTo("application/vnd.github.v3+json"));

// disconnect does nothing, never throws
uc.disconnect();
uc.disconnect();

Assert.assertThrows(UnsupportedOperationException.class, () -> uc.connect());

Assert.assertThrows(UnsupportedOperationException.class, () -> uc.getAllowUserInteraction());
Assert.assertThrows(UnsupportedOperationException.class, () -> uc.getConnectTimeout());
Assert.assertThrows(UnsupportedOperationException.class, () -> uc.getDefaultUseCaches());
Assert.assertThrows(UnsupportedOperationException.class, () -> uc.getDoInput());
Assert.assertThrows(UnsupportedOperationException.class, () -> uc.getDoOutput());
Assert.assertThrows(UnsupportedOperationException.class, () -> uc.getInstanceFollowRedirects());
Assert.assertThrows(UnsupportedOperationException.class, () -> uc.getOutputStream());
Assert.assertThrows(UnsupportedOperationException.class, () -> uc.getPermission());
Assert.assertThrows(UnsupportedOperationException.class, () -> uc.getReadTimeout());
Assert.assertThrows(UnsupportedOperationException.class, () -> uc.getUseCaches());
Assert.assertThrows(UnsupportedOperationException.class, () -> uc.usingProxy());

Assert.assertThrows(UnsupportedOperationException.class,
() -> uc.addRequestProperty("bogus", "item"));
Assert.assertThrows(UnsupportedOperationException.class,
() -> uc.setAllowUserInteraction(true));
Assert.assertThrows(UnsupportedOperationException.class, () -> uc.setChunkedStreamingMode(1));
Assert.assertThrows(UnsupportedOperationException.class, () -> uc.setConnectTimeout(10));
Assert.assertThrows(UnsupportedOperationException.class, () -> uc.setDefaultUseCaches(true));
Assert.assertThrows(UnsupportedOperationException.class, () -> uc.setDoInput(true));
Assert.assertThrows(UnsupportedOperationException.class, () -> uc.setDoOutput(true));
Assert.assertThrows(UnsupportedOperationException.class,
() -> uc.setFixedLengthStreamingMode(1));
Assert.assertThrows(UnsupportedOperationException.class,
() -> uc.setFixedLengthStreamingMode(1L));
Assert.assertThrows(UnsupportedOperationException.class, () -> uc.setIfModifiedSince(1L));
Assert.assertThrows(UnsupportedOperationException.class,
() -> uc.setInstanceFollowRedirects(true));
Assert.assertThrows(UnsupportedOperationException.class, () -> uc.setReadTimeout(10));
Assert.assertThrows(UnsupportedOperationException.class, () -> uc.setRequestMethod("GET"));
Assert.assertThrows(UnsupportedOperationException.class,
() -> uc.setRequestProperty("bogus", "thing"));
Assert.assertThrows(UnsupportedOperationException.class, () -> uc.setUseCaches(true));

RateLimitHandler.FAIL.onError(e, uc);
}
})
.build();

gitHub.getMyself();
Expand Down

0 comments on commit 05087f6

Please sign in to comment.