Skip to content

Commit

Permalink
android: java envoy pass through implementation (#390)
Browse files Browse the repository at this point in the history
Description: android: java envoy pass through implementation
Risk Level: low
Testing: local

Signed-off-by: Alan Chiu <achiu@lyft.com>
Signed-off-by: JP Simard <jp@jpsim.com>
  • Loading branch information
Alan Chiu authored and jpsim committed Nov 28, 2022
1 parent b185383 commit 7180db1
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 88 deletions.
2 changes: 1 addition & 1 deletion mobile/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,5 @@ touch $@

define_kt_toolchain(
name = "kotlin_toolchain",
jvm_target = "1.6",
jvm_target = "1.8",
)
14 changes: 14 additions & 0 deletions mobile/examples/java/hello_world/BUILD
Original file line number Diff line number Diff line change
@@ -1,8 +1,22 @@
licenses(["notice"]) # Apache 2

load("@io_bazel_rules_kotlin//kotlin:kotlin.bzl", "kt_android_library")

android_binary(
name = "hello_envoy",
custom_package = "io.envoyproxy.envoymobile.helloenvoy",
manifest = "AndroidManifest.xml",
deps = [
"hello_envoy_java_lib",
],
)

# We'll use the kotlin rule here to avoid having an explicit dependency on
# kotlin runtime.
kt_android_library(
name = "hello_envoy_java_lib",
srcs = [
"EmptyFile.kt", # Needed for the kotlin rule
"MainActivity.java",
],
custom_package = "io.envoyproxy.envoymobile.helloenvoy",
Expand Down
1 change: 1 addition & 0 deletions mobile/examples/java/hello_world/EmptyFile.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package io.envoyproxy.envoymobile.helloenvoy
97 changes: 40 additions & 57 deletions mobile/examples/java/hello_world/MainActivity.java
Original file line number Diff line number Diff line change
@@ -1,57 +1,51 @@
package io.envoyproxy.envoymobile.helloenvoy;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import io.envoyproxy.envoymobile.AndroidEnvoyBuilder;
import io.envoyproxy.envoymobile.Envoy;
import io.envoyproxy.envoymobile.engine.AndroidEngineImpl;
import io.envoyproxy.envoymobile.engine.EnvoyEngine;
import io.envoyproxy.envoymobile.Request;
import io.envoyproxy.envoymobile.RequestBuilder;
import io.envoyproxy.envoymobile.RequestMethod;
import io.envoyproxy.envoymobile.ResponseHandler;
import io.envoyproxy.envoymobile.shared.Failure;
import io.envoyproxy.envoymobile.shared.Response;
import io.envoyproxy.envoymobile.shared.ResponseRecyclerViewAdapter;
import io.envoyproxy.envoymobile.shared.Success;
import kotlin.Unit;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
import java.util.Collections;
import java.util.concurrent.TimeUnit;

public class MainActivity extends Activity {
private static final String ENDPOINT =
"http://0.0.0.0:9001/api.lyft.com/static/demo/hello_world.txt";

private static final String ENVOY_SERVER_HEADER = "server";

private static final String REQUEST_HANDLER_THREAD_NAME = "hello_envoy_java";
private static final String ENVOY_SERVER_HEADER = "server";
private static final String REQUEST_AUTHORITY = "s3.amazonaws.com";
private static final String REQUEST_PATH = "/api.lyft.com/static/demo/hello_world.txt";
private static final String REQUEST_SCHEME = "http";

private Envoy envoy;
private RecyclerView recyclerView;

private HandlerThread thread = new HandlerThread(REQUEST_HANDLER_THREAD_NAME);
private ResponseRecyclerViewAdapter viewAdapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

this.envoy = new AndroidEnvoyBuilder(getBaseContext()).build();
envoy = new AndroidEnvoyBuilder(getBaseContext()).build();

recyclerView = (RecyclerView)findViewById(R.id.recycler_view);
recyclerView = findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));

final ResponseRecyclerViewAdapter adapter = new ResponseRecyclerViewAdapter();
recyclerView.setAdapter(adapter);
viewAdapter = new ResponseRecyclerViewAdapter();
recyclerView.setAdapter(viewAdapter);
DividerItemDecoration dividerItemDecoration =
new DividerItemDecoration(recyclerView.getContext(), DividerItemDecoration.VERTICAL);
recyclerView.addItemDecoration(dividerItemDecoration);
Expand All @@ -62,9 +56,7 @@ protected void onCreate(Bundle savedInstanceState) {
handler.postDelayed(new Runnable() {
@Override
public void run() {
final Response response = makeRequest();
recyclerView.post((Runnable)() -> adapter.add(response));

makeRequest();
// Make a call again
handler.postDelayed(this, TimeUnit.SECONDS.toMillis(1));
}
Expand All @@ -76,38 +68,29 @@ protected void onDestroy() {
thread.quit();
}

private Response makeRequest() {
try {
URL url = new URL(ENDPOINT);
// Open connection to the envoy thread listening locally on port 9001.
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setRequestProperty("host", "s3.amazonaws.com");
int status = connection.getResponseCode();
if (status == 200) {
List<String> serverHeaderField = connection.getHeaderFields().get(ENVOY_SERVER_HEADER);
InputStream inputStream = connection.getInputStream();
String body = deserialize(inputStream);
inputStream.close();
Log.d("Response", "successful response!");
return new Success(body,
serverHeaderField != null ? String.join(", ", serverHeaderField) : "");
} else {
return new Failure("failed with status " + status);
}
} catch (Exception e) {
return new Failure(e.getMessage());
}
}

private String deserialize(InputStream inputStream) throws IOException {
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String line = bufferedReader.readLine();
while (line != null) {
stringBuilder.append(line);
line = bufferedReader.readLine();
}
bufferedReader.close();
return stringBuilder.toString();
private void makeRequest() {
Request request =
new RequestBuilder(RequestMethod.GET, REQUEST_SCHEME, REQUEST_AUTHORITY, REQUEST_PATH)
.build();

ResponseHandler handler =
new ResponseHandler(Runnable::run)
.onHeaders((headers, status, endStream) -> {
if (status == 200) {
String serverHeaderField = headers.get(ENVOY_SERVER_HEADER).get(0);
String body = "";
recyclerView.post(() -> viewAdapter.add(new Success(body, serverHeaderField)));
} else {
recyclerView.post(
() -> viewAdapter.add(new Failure("failed with status " + status)));
}
return Unit.INSTANCE;
})
.onError(() -> {
recyclerView.post(() -> viewAdapter.add(new Failure("failed with error ")));
return Unit.INSTANCE;
});

envoy.send(request, null, Collections.emptyMap(), handler);
}
}
45 changes: 18 additions & 27 deletions mobile/examples/kotlin/hello_world/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,16 @@ import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView
import android.util.Log
import io.envoyproxy.envoymobile.AndroidEnvoyBuilder
import io.envoyproxy.envoymobile.CancelableStream
import io.envoyproxy.envoymobile.Envoy
import io.envoyproxy.envoymobile.RequestBuilder
import io.envoyproxy.envoymobile.ResponseHandler
import io.envoyproxy.envoymobile.RequestMethod
import io.envoyproxy.envoymobile.ResponseHandler
import io.envoyproxy.envoymobile.shared.Failure
import io.envoyproxy.envoymobile.shared.Response
import io.envoyproxy.envoymobile.shared.ResponseRecyclerViewAdapter
import io.envoyproxy.envoymobile.shared.Success
import java.io.IOException
import java.io.InputStream
import java.net.HttpURLConnection
import java.net.URL
import java.util.concurrent.Executor
import java.util.concurrent.TimeUnit
import java.util.concurrent.Executor;


private const val REQUEST_HANDLER_THREAD_NAME = "hello_envoy_kt"
Expand Down Expand Up @@ -74,28 +69,24 @@ class MainActivity : Activity() {
thread.quit()
}

private fun makeRequest(): Unit {
private fun makeRequest() {
val request = RequestBuilder(RequestMethod.GET, REQUEST_SCHEME,
REQUEST_AUTHORITY, REQUEST_PATH).build()
val handler = ResponseHandler(object : Executor {
override fun execute(r : Runnable) {
r.run()
}
})
.onHeaders({ headers, status, _ ->
if (status == 200) {
val serverHeaderField = headers[ENVOY_SERVER_HEADER]?.first() ?: ""
val body = "" // fake data
recyclerView.post { viewAdapter.add(Success(body, serverHeaderField)) }
} else {
recyclerView.post { viewAdapter.add(Failure("failed with status: $status")) }
}
})
REQUEST_AUTHORITY, REQUEST_PATH).build()

envoy.send(request, null, emptyMap(), handler)
}
val handler = ResponseHandler(Executor { r -> r.run() })
.onHeaders { headers, status, _ ->
if (status == 200) {
val serverHeaderField = headers[ENVOY_SERVER_HEADER]?.first() ?: ""
val body = "" // fake data
recyclerView.post { viewAdapter.add(Success(body, serverHeaderField)) }
} else {
recyclerView.post { viewAdapter.add(Failure("failed with status: $status")) }
}
}
.onError {
recyclerView.post { viewAdapter.add(Failure("failed with error ")) }
}

private fun deserialize(inputStream: InputStream): String {
return inputStream.bufferedReader().use { reader -> reader.readText() }
envoy.send(request, null, emptyMap(), handler)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class Envoy constructor(
// Dedicated thread for running this instance of Envoy.
private val runner: Thread = Thread(ThreadGroup("Envoy"), Runnable {
engine.runWithConfig(config.trim(), logLevel.level)
});
})

/**
* Create a new Envoy instance. The Envoy runner Thread is started as part of instance
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ import java.util.concurrent.Executor;
class ResponseHandler(val executor: Executor) {

class EnvoyObserverAdapter(
internal val responseHandler: ResponseHandler
private val responseHandler: ResponseHandler
) : EnvoyObserver {

override fun getExecutor() : Executor = responseHandler.executor
override fun getExecutor(): Executor = responseHandler.executor

override fun onHeaders(headers: Map<String, List<String>>?, endStream: Boolean) {
val statusCode = headers!![":status"]?.first()?.toIntOrNull() ?: 0
Expand Down

0 comments on commit 7180db1

Please sign in to comment.