refactoring
This commit is contained in:
parent
d1451e9889
commit
9823461435
3 changed files with 123 additions and 150 deletions
|
@ -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");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,15 +1,23 @@
|
||||||
package net.osmand.plus.server;
|
package net.osmand.plus.server;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
import android.webkit.MimeTypeMap;
|
||||||
import fi.iki.elonen.NanoHTTPD;
|
import fi.iki.elonen.NanoHTTPD;
|
||||||
|
import net.osmand.PlatformUtil;
|
||||||
import net.osmand.plus.OsmandApplication;
|
import net.osmand.plus.OsmandApplication;
|
||||||
import net.osmand.plus.server.endpoints.TileEndpoint;
|
import net.osmand.plus.server.endpoints.TileEndpoint;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public class OsmAndHttpServer extends NanoHTTPD {
|
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";
|
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;
|
private OsmandApplication application;
|
||||||
|
|
||||||
public OsmAndHttpServer() throws IOException {
|
public OsmAndHttpServer() throws IOException {
|
||||||
|
@ -24,15 +32,95 @@ public class OsmAndHttpServer extends NanoHTTPD {
|
||||||
|
|
||||||
public void setApplication(OsmandApplication application) {
|
public void setApplication(OsmandApplication application) {
|
||||||
this.application = application;
|
this.application = application;
|
||||||
router.setApplication(application);
|
for (String s : endpoints.keySet()) {
|
||||||
}
|
endpoints.get(s).setApplication(application);
|
||||||
|
}
|
||||||
private void registerEndpoints() {
|
|
||||||
router.register("/tile", new TileEndpoint(application));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Response serve(IHTTPSession session) {
|
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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import net.osmand.plus.OsmandApplication;
|
||||||
import net.osmand.plus.render.MapRenderRepositories;
|
import net.osmand.plus.render.MapRenderRepositories;
|
||||||
import net.osmand.plus.resources.AsyncLoadingThread;
|
import net.osmand.plus.resources.AsyncLoadingThread;
|
||||||
import net.osmand.plus.server.ApiEndpoint;
|
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 org.apache.commons.logging.Log;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
|
@ -35,20 +35,6 @@ public class TileEndpoint implements ApiEndpoint {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NanoHTTPD.Response process(NanoHTTPD.IHTTPSession session) {
|
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;
|
int zoom;
|
||||||
double lat;
|
double lat;
|
||||||
double lon;
|
double lon;
|
||||||
|
@ -57,6 +43,27 @@ public class TileEndpoint implements ApiEndpoint {
|
||||||
zoom = s.nextInt();
|
zoom = s.nextInt();
|
||||||
lat = s.nextDouble();
|
lat = s.nextDouble();
|
||||||
lon = 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;
|
Future<Pair<RotatedTileBox, Bitmap>> future;
|
||||||
final RotatedTileBox rotatedTileBox = new RotatedTileBox.RotatedTileBoxBuilder()
|
final RotatedTileBox rotatedTileBox = new RotatedTileBox.RotatedTileBoxBuilder()
|
||||||
.setLocation(lat, lon)
|
.setLocation(lat, lon)
|
||||||
|
@ -67,8 +74,10 @@ public class TileEndpoint implements ApiEndpoint {
|
||||||
@Override
|
@Override
|
||||||
public Pair<RotatedTileBox, Bitmap> call() throws Exception {
|
public Pair<RotatedTileBox, Bitmap> call() throws Exception {
|
||||||
Bitmap bmp;
|
Bitmap bmp;
|
||||||
|
int sleepTime = 500;
|
||||||
while ((bmp = map.get(rotatedTileBox)) == null) {
|
while ((bmp = map.get(rotatedTileBox)) == null) {
|
||||||
Thread.sleep(500);
|
Thread.sleep(sleepTime);
|
||||||
|
sleepTime += 500;
|
||||||
}
|
}
|
||||||
return Pair.create(rotatedTileBox, bmp);
|
return Pair.create(rotatedTileBox, bmp);
|
||||||
}
|
}
|
||||||
|
@ -82,21 +91,12 @@ public class TileEndpoint implements ApiEndpoint {
|
||||||
try {
|
try {
|
||||||
Pair<RotatedTileBox, Bitmap> pair = future.get();
|
Pair<RotatedTileBox, Bitmap> pair = future.get();
|
||||||
Bitmap bitmap = pair.second;
|
Bitmap bitmap = pair.second;
|
||||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
return bitmap;
|
||||||
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());
|
|
||||||
} catch (ExecutionException e) {
|
} catch (ExecutionException e) {
|
||||||
LOG.error("Execution exception", e);
|
LOG.error("Execution exception", e);
|
||||||
return ApiRouter.ErrorResponses.response500;
|
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
LOG.error("Interrupted exception", e);
|
LOG.error("Interrupted exception", e);
|
||||||
return ApiRouter.ErrorResponses.response500;
|
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue