Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CM: WIP for android http client #127

Open
wants to merge 14 commits into
base: master
Choose a base branch
from

Conversation

carlo-backblaze
Copy link

@carlo-backblaze carlo-backblaze commented Sep 21, 2020

  • WIP, do not merge

  • Will most likely be split into it's own repository

  • Creating separate gradle project including an Android application for instrumented tests and examples httpclient_android/app

  • Creating a httpclient library targeting Android frameworks in httpclient_android/http_client

  • Creating base library unit tests

  • Removing the Apache HTTP Client framework dependencies

  • Using URLConnection, HttpUrlConnection, and HttpsUrlConnection

  • Will be outputting .aar library for publishing

Comment on lines 147 to 153
URL clientUrl = new URL(url);
URLConnection head;
if (clientUrl.getProtocol().equals("https")) {
head = (HttpsURLConnection) clientUrl.openConnection();
} else {
head = (HttpURLConnection) clientUrl.openConnection();
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this looks similar to code above, perhaps factor it out into something that take a url string and returns the URLConnection instance for it?

Now that I look more closely at it, is the if statement necessary? It looks like we make an openConnection on the clientUrl and then case it to a specific Http/Https flavor of UrlConnection, but then assign it to a variable of type URLConnection.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The difference is that each HttpsURLConnection has all of the SSL methods. I can create a convenience builder/class if you think that is necessary.

Copy link
Contributor

@malaysf malaysf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there are some empty files like
httpclient_android/TODO

can these be removed?

Also, there are some image files in the diff, are those needed?

public class B2StorageHttpClientBuilderTest {

@Test
public void B2StorageHttpClientBuilder_builder() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are there any real tests we can put in here?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. of course

* Copyright 2020, Backblaze Inc. All Rights Reserved.
* License https://www.backblaze.com/using_b2_code.html
*/
package com.backblaze.b2.client.webApiHttpClient.android.UrlConnection;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the webApiHttpClient name refers to a webApi implementation using the Apache HttpClient library.

I think the correct package name here would be:
com.backblaze.b2.client.webApiUrlConnection

I would also advocate for making this a regular java module as there is nothing Android specific about this. If needed, create a second Gradle file to allow it to be built for Android.


import android.os.Bundle;

public class MainActivity extends AppCompatActivity {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this file needed?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's an example Android App where integration tests/example can be added.

* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like an example file that can be removed.

@@ -0,0 +1,101 @@
/*
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for renaming the package, but please also move all these files into the core project.

connection.disconnect();
} catch (Error e) {
// restore the interrupt because we're not acting on it here.
if (e.getMessage() != null) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this swallow the error here or rethrow?

public void B2StorageHttpClientBuilder_setHttpClientFactory() {
final HttpClientFactory clientFactory = HttpClientFactoryImpl.build();
final B2StorageClient factory = new B2StorageHttpClientBuilder.build();
final B2StorageHttpClientBuilder factoryTwo = factory.setHttpClientFactory(clientFactory);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm confused, B2StorageClient doesn't have a method setHttpClientFactory. Am I missing something?

*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
public class B2StorageHttpClientBuilderTest {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests need to be more detailed, more than just asserting non null. Check default values and that specified values are set in the built B2StorageClient instance.

import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

public class B2StorageHttpClientFactoryTest {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

like above, tests need to do more than assert non null.

connection.setConnectTimeout(this.connectTimeoutSeconds);
return connection;
} catch (Error e) {
// Log
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing log statement? Should this also turn around and throw a B2Exception?

Comment on lines +116 to +122
final Scanner input = new Scanner(new InputStreamReader(client.getInputStream()));
final StringBuilder response = new StringBuilder();
String line;
while ((line = input.hasNext())) {
response.append(line);
}
input.close();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be factored out into a helper method since it is used below as well

Comment on lines +95 to +99
if (clientUrl.getProtocol().equals("https")) {
client = (HttpsURLConnection) clientUrl.openConnection();
} else {
client = (HttpURLConnection) clientUrl.openConnection();
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this necessary? clientUrl.openConnection returns a URLConnection instance already so downcasting to HttpsURLConnection or HttpURLConnection and then storing in a URLConnection instance is unnecessary.

I think this could be reduced down to:

final URLConnection client = clientUrl.openConnection();

This applies to the several occurrences of this code.

* @param request the object to be json'ified.
* @return a new ByteArrayEntity with the json representation of request in it.
*/
private static String parseToStringUsingBzJson(Object request) throws B2Exception {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you meant to name this parseToStringUsingB2Json instead of parseToStringUsingBzJson?

* @return the body of the response.
* @throws B2Exception if there's any trouble
*/
private String postAndReturnString(String url, B2Headers headersOrNull, String requestString)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can requestString be wrapped as an InputStream and call the other overload of postAndReturnString so that there's only one core implementation?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants