diff --git a/http-requests-core/src/main/java/com/budjb/httprequests/HttpRequest.java b/http-requests-core/src/main/java/com/budjb/httprequests/HttpRequest.java index 16f61c6..6444b96 100644 --- a/http-requests-core/src/main/java/com/budjb/httprequests/HttpRequest.java +++ b/http-requests-core/src/main/java/com/budjb/httprequests/HttpRequest.java @@ -86,7 +86,7 @@ public HttpRequest() { * * @param uri URI of the request. */ - public HttpRequest(URI uri) { + public HttpRequest(URI uri) throws URISyntaxException { parseUri(uri); } @@ -131,7 +131,7 @@ public HttpRequest setUri(String uri) throws URISyntaxException { * @param uri URI of the request. * @return The instance of this class the method was called with. */ - public HttpRequest setUri(URI uri) { + public HttpRequest setUri(URI uri) throws URISyntaxException { parseUri(uri); return this; } @@ -416,17 +416,25 @@ private void parseUri(String uri) throws URISyntaxException { * * @param uri URI object to parse. */ - private void parseUri(URI uri) { + private void parseUri(URI uri) throws URISyntaxException { String scheme = uri.getScheme(); String host = uri.getHost(); int port = uri.getPort(); String path = uri.getRawPath(); String query = uri.getQuery(); + if (uri.getScheme() == null) { + throw new URISyntaxException(uri.toString(), "URI must contain a scheme"); + } + + if (uri.getHost() == null) { + throw new URISyntaxException(uri.toString(), "URI must contain a host"); + } + StringBuilder builder = new StringBuilder(scheme).append("://").append(host); if (port != -1 && !(scheme.equalsIgnoreCase("https") && port == 443) && !(scheme.equalsIgnoreCase("http") && port == 80)) { - builder = builder.append(':').append(port); + builder.append(':').append(port); } builder.append(path); diff --git a/http-requests-core/src/main/java/com/budjb/httprequests/converter/EntityConverterManager.java b/http-requests-core/src/main/java/com/budjb/httprequests/converter/EntityConverterManager.java index d34d7d5..3d08bb3 100644 --- a/http-requests-core/src/main/java/com/budjb/httprequests/converter/EntityConverterManager.java +++ b/http-requests-core/src/main/java/com/budjb/httprequests/converter/EntityConverterManager.java @@ -130,6 +130,10 @@ public HttpEntity write(ConvertingHttpEntity entity) throws UnsupportedConversio * @throws UnsupportedConversionException when there are no entity writers that support the object type. */ public HttpEntity write(Object entity, String contentType, String characterSet) throws UnsupportedConversionException { + if (entity == null) { + return null; + } + Class type = entity.getClass(); for (EntityWriter writer : getEntityWriters()) { diff --git a/http-requests-documentation/src/docs/changelog.adoc b/http-requests-documentation/src/docs/changelog.adoc index d7fcc53..5ffe114 100644 --- a/http-requests-documentation/src/docs/changelog.adoc +++ b/http-requests-documentation/src/docs/changelog.adoc @@ -9,6 +9,13 @@ The changelog will be updated with release notes for each release of the library precedence over a user-specified one. * Add http-requests-mock library to enable easier testing of code using the http-requests libraries. +* Fix `NullPointerException` when sending a request with a null entity + (https://github.com/budjb/http-requests/issues/14[#14]). +* Write a test to ensure that retrieving an entity when the response does not contain + an entity does not result in a `NullPointerException` + (https://github.com/budjb/http-requests/issues/13[#13]). +* Throw a `URISyntaxException` instead of `NullPointerException` when a URI is not absolute + (https://github.com/budjb/http-requests/issues/12[#12]). 2.0.6:: diff --git a/http-requests-functional-test/src/main/groovy/com/budjb/httprequests/HttpIntegrationTestSuiteSpec.groovy b/http-requests-functional-test/src/main/groovy/com/budjb/httprequests/HttpIntegrationTestSuiteSpec.groovy index 5144696..c373539 100644 --- a/http-requests-functional-test/src/main/groovy/com/budjb/httprequests/HttpIntegrationTestSuiteSpec.groovy +++ b/http-requests-functional-test/src/main/groovy/com/budjb/httprequests/HttpIntegrationTestSuiteSpec.groovy @@ -222,7 +222,6 @@ abstract class HttpIntegrationTestSuiteSpec extends AbstractIntegrationSpec { formData.addField('foo', 'baz') formData.addField('key', 'value') - when: def response = httpClientFactory.createHttpClient().post("${baseUrl}/testForm", formData) @@ -617,6 +616,45 @@ abstract class HttpIntegrationTestSuiteSpec extends AbstractIntegrationSpec { response.getHeader('content-type') == 'foo/bar' } + def 'Sending a null request entity does not send any request entity'() { + setup: + HttpRequest request = new HttpRequest("${baseUrl}/testBasicPost") + + when: + def response = httpClientFactory.createHttpClient().post(request, null) + + then: + !response.hasEntity() + } + + def 'Retrieving a response entity when the response does not contain and entity does not result in a NullPointerException'() { + setup: + HttpRequest request = new HttpRequest("${baseUrl}/testBasicPost") + + when: + def response = httpClientFactory.createHttpClient().post(request, null) + + then: + !response.hasEntity() + response.getEntity(String) == null + } + + def 'Making a request with a URI that does not contain a scheme throws a URISyntaxException'() { + when: + httpClientFactory.createHttpClient().get('foobar') + + then: + thrown URISyntaxException + } + + def 'Making a request with a URI that does not contain a host throws a URISyntaxException'() { + when: + httpClientFactory.createHttpClient().get('https:///foo/bar') + + then: + thrown URISyntaxException + } + static class CloseableFilter implements HttpClientFilter, Closeable { boolean closed = false diff --git a/http-requests-groovy/src/main/java/com/budjb/httprequests/groovy/HttpRequestDelegate.java b/http-requests-groovy/src/main/java/com/budjb/httprequests/groovy/HttpRequestDelegate.java index 31e5eb2..0c540fe 100644 --- a/http-requests-groovy/src/main/java/com/budjb/httprequests/groovy/HttpRequestDelegate.java +++ b/http-requests-groovy/src/main/java/com/budjb/httprequests/groovy/HttpRequestDelegate.java @@ -58,7 +58,7 @@ public void uri(String uri) throws URISyntaxException { * * @param uri The URI of the request. */ - public void uri(URI uri) { + public void uri(URI uri) throws URISyntaxException { httpRequest.setUri(uri); }