refactoring

This commit is contained in:
simon 2020-09-04 17:38:36 +03:00
parent d1451e9889
commit 9823461435
3 changed files with 123 additions and 150 deletions

View file

@ -1,115 +0,0 @@
package net.osmand.plus.server;
import android.util.Log;
import android.webkit.MimeTypeMap;
import fi.iki.elonen.NanoHTTPD;
import net.osmand.PlatformUtil;
import net.osmand.plus.OsmandApplication;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import static fi.iki.elonen.NanoHTTPD.newFixedLengthResponse;
public class ApiRouter {
private static final String FOLDER_NAME = "server";
private static final org.apache.commons.logging.Log LOG = PlatformUtil.getLog(ApiRouter.class);
private final Map<String, ApiEndpoint> endpoints = new HashMap<>();
private OsmandApplication application;
public OsmandApplication getApplication() {
return application;
}
public void setApplication(OsmandApplication application) {
this.application = application;
for (String s : endpoints.keySet()) {
endpoints.get(s).setApplication(application);
}
}
public NanoHTTPD.Response getStatic(String uri) {
InputStream is;
String mimeType = parseMimeType(uri);
if (application != null) {
try {
is = application.getAssets().open(FOLDER_NAME + uri);
if (is.available() == 0) {
return ErrorResponses.response404;
}
return newFixedLengthResponse(
NanoHTTPD.Response.Status.OK,
mimeType,
is,
is.available());
} catch (IOException e) {
return ErrorResponses.response404;
}
}
return ErrorResponses.response500;
}
public NanoHTTPD.Response route(NanoHTTPD.IHTTPSession session) {
Log.d("SERVER", "URI: " + session.getUri());
String uri = session.getUri();
if (uri.equals("/")) {
return getStatic("/go.html");
}
if (isApiUrl(uri)) {
return routeApi(session);
}
return getStatic(uri);
}
public void register(String path, ApiEndpoint endpoint) {
endpoint.setApplication(application);
endpoints.put(path, endpoint);
}
private NanoHTTPD.Response routeApi(NanoHTTPD.IHTTPSession session) {
String uri = session.getUri();
int pathEnd = uri.indexOf("/", 1);
if (pathEnd != -1) {
uri = uri.substring(0, pathEnd);
}
ApiEndpoint endpoint = endpoints.get(uri);
if (endpoint != null) {
return endpoint.process(session);
}
return ErrorResponses.response404;
}
private boolean isApiUrl(String uri) {
for (String endpoint : endpoints.keySet()) {
int stringLength = endpoint.length();
if (uri.startsWith(endpoint) &&
(uri.length() == endpoint.length() || uri.charAt(stringLength) == '/')) {
return true;
}
}
return false;
}
private String parseMimeType(String url) {
String type = "text/plain";
if (url.endsWith(".js")) return "text/javascript";
String extension = MimeTypeMap.getFileExtensionFromUrl(url);
if (extension != null) {
type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
}
return type;
}
public static class ErrorResponses {
public static NanoHTTPD.Response response404 =
newFixedLengthResponse(NanoHTTPD.Response.Status.NOT_FOUND,
NanoHTTPD.MIME_PLAINTEXT, "404 Not Found");
public static NanoHTTPD.Response response500 =
newFixedLengthResponse(NanoHTTPD.Response.Status.INTERNAL_ERROR,
NanoHTTPD.MIME_PLAINTEXT, "500 Internal Server Error");
}
}

View file

@ -1,15 +1,23 @@
package net.osmand.plus.server;
import android.util.Log;
import android.webkit.MimeTypeMap;
import fi.iki.elonen.NanoHTTPD;
import net.osmand.PlatformUtil;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.server.endpoints.TileEndpoint;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
public class OsmAndHttpServer extends NanoHTTPD {
public static int PORT = 24990;
private static final String FOLDER_NAME = "server";
private static final org.apache.commons.logging.Log LOG = PlatformUtil.getLog(OsmAndHttpServer.class);
public static final int PORT = 24990;
public static String HOSTNAME = "0.0.0.0";
private final ApiRouter router = new ApiRouter();
private final Map<String, ApiEndpoint> endpoints = new HashMap<>();
private OsmandApplication application;
public OsmAndHttpServer() throws IOException {
@ -24,15 +32,95 @@ public class OsmAndHttpServer extends NanoHTTPD {
public void setApplication(OsmandApplication application) {
this.application = application;
router.setApplication(application);
}
private void registerEndpoints() {
router.register("/tile", new TileEndpoint(application));
for (String s : endpoints.keySet()) {
endpoints.get(s).setApplication(application);
}
}
@Override
public Response serve(IHTTPSession session) {
return router.route(session);
Log.d("SERVER", "URI: " + session.getUri());
String uri = session.getUri();
if (uri.equals("/")) {
return getStatic("/go.html");
}
if (isApiUrl(uri)) {
return routeApi(session);
}
return getStatic(uri);
}
private NanoHTTPD.Response routeApi(NanoHTTPD.IHTTPSession session) {
String uri = session.getUri();
int pathEnd = uri.indexOf("/", 1);
if (pathEnd != -1) {
uri = uri.substring(0, pathEnd);
}
ApiEndpoint endpoint = endpoints.get(uri);
if (endpoint != null) {
return endpoint.process(session);
}
return ErrorResponses.response404;
}
private boolean isApiUrl(String uri) {
for (String endpoint : endpoints.keySet()) {
int stringLength = endpoint.length();
if (uri.startsWith(endpoint) &&
(uri.length() == endpoint.length() || uri.charAt(stringLength) == '/')) {
return true;
}
}
return false;
}
private void registerEndpoints() {
register("/tile", new TileEndpoint(application));
}
private void register(String path, ApiEndpoint endpoint) {
endpoint.setApplication(application);
endpoints.put(path, endpoint);
}
private NanoHTTPD.Response getStatic(String uri) {
InputStream is;
String mimeType = parseMimeType(uri);
if (application != null) {
try {
is = application.getAssets().open(FOLDER_NAME + uri);
if (is.available() == 0) {
return ErrorResponses.response404;
}
return newFixedLengthResponse(
NanoHTTPD.Response.Status.OK,
mimeType,
is,
is.available());
} catch (IOException e) {
return ErrorResponses.response404;
}
}
return ErrorResponses.response500;
}
private String parseMimeType(String url) {
String type = "text/plain";
if (url.endsWith(".js")) return "text/javascript";
String extension = MimeTypeMap.getFileExtensionFromUrl(url);
if (extension != null) {
type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
}
return type;
}
public static class ErrorResponses {
public static NanoHTTPD.Response response404 =
newFixedLengthResponse(NanoHTTPD.Response.Status.NOT_FOUND,
NanoHTTPD.MIME_PLAINTEXT, "404 Not Found");
public static NanoHTTPD.Response response500 =
newFixedLengthResponse(NanoHTTPD.Response.Status.INTERNAL_ERROR,
NanoHTTPD.MIME_PLAINTEXT, "500 Internal Server Error");
}
}

View file

@ -9,7 +9,7 @@ import net.osmand.plus.OsmandApplication;
import net.osmand.plus.render.MapRenderRepositories;
import net.osmand.plus.resources.AsyncLoadingThread;
import net.osmand.plus.server.ApiEndpoint;
import net.osmand.plus.server.ApiRouter;
import net.osmand.plus.server.OsmAndHttpServer;
import org.apache.commons.logging.Log;
import java.io.ByteArrayInputStream;
@ -35,20 +35,6 @@ public class TileEndpoint implements ApiEndpoint {
@Override
public NanoHTTPD.Response process(NanoHTTPD.IHTTPSession session) {
try {
return tileApiCall(session);
} catch (Exception e) {
LOG.error("Exception", e);
}
return ApiRouter.ErrorResponses.response500;
}
@Override
public void setApplication(OsmandApplication application) {
this.application = application;
}
private synchronized NanoHTTPD.Response tileApiCall(NanoHTTPD.IHTTPSession session) {
int zoom;
double lat;
double lon;
@ -57,6 +43,27 @@ public class TileEndpoint implements ApiEndpoint {
zoom = s.nextInt();
lat = s.nextDouble();
lon = s.nextDouble();
Bitmap bitmap = requestTile(lat, lon, zoom);
if (bitmap == null) {
return OsmAndHttpServer.ErrorResponses.response500;
}
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
ByteArrayInputStream str = new ByteArrayInputStream(byteArray);
return newFixedLengthResponse(
NanoHTTPD.Response.Status.OK,
"image/png",
str,
str.available());
}
@Override
public void setApplication(OsmandApplication application) {
this.application = application;
}
private synchronized Bitmap requestTile(double lat, double lon, int zoom) {
Future<Pair<RotatedTileBox, Bitmap>> future;
final RotatedTileBox rotatedTileBox = new RotatedTileBox.RotatedTileBoxBuilder()
.setLocation(lat, lon)
@ -67,8 +74,10 @@ public class TileEndpoint implements ApiEndpoint {
@Override
public Pair<RotatedTileBox, Bitmap> call() throws Exception {
Bitmap bmp;
int sleepTime = 500;
while ((bmp = map.get(rotatedTileBox)) == null) {
Thread.sleep(500);
Thread.sleep(sleepTime);
sleepTime += 500;
}
return Pair.create(rotatedTileBox, bmp);
}
@ -82,21 +91,12 @@ public class TileEndpoint implements ApiEndpoint {
try {
Pair<RotatedTileBox, Bitmap> pair = future.get();
Bitmap bitmap = pair.second;
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
ByteArrayInputStream str = new ByteArrayInputStream(byteArray);
return newFixedLengthResponse(
NanoHTTPD.Response.Status.OK,
"image/png",
str,
str.available());
return bitmap;
} catch (ExecutionException e) {
LOG.error("Execution exception", e);
return ApiRouter.ErrorResponses.response500;
} catch (InterruptedException e) {
LOG.error("Interrupted exception", e);
return ApiRouter.ErrorResponses.response500;
}
return null;
}
}