This is an automated email from the ASF dual-hosted git repository. bchapuis pushed a commit to branch armeria in repository https://gitbox.apache.org/repos/asf/incubator-baremaps.git
commit e94b62adfa0b7889f2f0d9e2cd2af971668a9b66 Author: Bertil Chapuis <[email protected]> AuthorDate: Sun Jan 14 23:44:09 2024 +0100 Use armeria for all commands and remove service talk --- baremaps-cli/pom.xml | 20 ---- .../org/apache/baremaps/cli/geocoder/Serve.java | 60 ++++++----- .../java/org/apache/baremaps/cli/iploc/Serve.java | 62 +++++++----- .../main/java/org/apache/baremaps/cli/map/Dev.java | 48 ++++----- .../java/org/apache/baremaps/cli/map/MBTiles.java | 72 ++++++------- .../main/java/org/apache/baremaps/cli/map/Map.java | 3 +- .../java/org/apache/baremaps/cli/map/Serve.java | 79 +++++++-------- .../org/apache/baremaps/cli/map/StyleCommand.java | 111 --------------------- baremaps-server/pom.xml | 44 -------- .../baremaps/server/BaseUriRequestFilter.java | 52 ---------- .../apache/baremaps/server/ClassPathResource.java | 74 -------------- .../org/apache/baremaps/server/CorsFilter.java | 84 ---------------- .../apache/baremaps/server/GeocoderResource.java | 54 +++++----- .../org/apache/baremaps/server/IpLocResource.java | 73 +++++++------- .../org/apache/baremaps/server/SearchResource.java | 32 +++--- .../BaseUriRequestFilterIntegrationTest.java | 54 ---------- .../server/ClassPathResourceIntegrationTest.java | 53 ---------- pom.xml | 89 ++--------------- 18 files changed, 255 insertions(+), 809 deletions(-) diff --git a/baremaps-cli/pom.xml b/baremaps-cli/pom.xml index bb1e853a..b9ebf99b 100644 --- a/baremaps-cli/pom.xml +++ b/baremaps-cli/pom.xml @@ -39,26 +39,6 @@ limitations under the License. <groupId>info.picocli</groupId> <artifactId>picocli</artifactId> </dependency> - <dependency> - <groupId>io.servicetalk</groupId> - <artifactId>servicetalk-data-jackson</artifactId> - </dependency> - <dependency> - <groupId>io.servicetalk</groupId> - <artifactId>servicetalk-data-jackson-jersey</artifactId> - </dependency> - <dependency> - <groupId>io.servicetalk</groupId> - <artifactId>servicetalk-http-netty</artifactId> - </dependency> - <dependency> - <groupId>io.servicetalk</groupId> - <artifactId>servicetalk-http-router-jersey</artifactId> - </dependency> - <dependency> - <groupId>io.servicetalk</groupId> - <artifactId>servicetalk-transport-netty</artifactId> - </dependency> <dependency> <groupId>org.apache.baremaps</groupId> <artifactId>baremaps-core</artifactId> diff --git a/baremaps-cli/src/main/java/org/apache/baremaps/cli/geocoder/Serve.java b/baremaps-cli/src/main/java/org/apache/baremaps/cli/geocoder/Serve.java index bdbf84cc..def8831e 100644 --- a/baremaps-cli/src/main/java/org/apache/baremaps/cli/geocoder/Serve.java +++ b/baremaps-cli/src/main/java/org/apache/baremaps/cli/geocoder/Serve.java @@ -18,19 +18,21 @@ package org.apache.baremaps.cli.geocoder; +import static org.apache.baremaps.utils.ObjectMapperUtils.objectMapper; -import io.servicetalk.http.netty.HttpServers; -import io.servicetalk.http.router.jersey.HttpJerseyRouterBuilder; +import com.linecorp.armeria.common.HttpHeaderNames; +import com.linecorp.armeria.common.HttpMethod; +import com.linecorp.armeria.server.Server; +import com.linecorp.armeria.server.annotation.JacksonResponseConverterFunction; +import com.linecorp.armeria.server.cors.CorsService; +import com.linecorp.armeria.server.file.FileService; +import com.linecorp.armeria.server.file.HttpFile; import java.nio.file.Path; import java.util.concurrent.Callable; -import org.apache.baremaps.server.ClassPathResource; -import org.apache.baremaps.server.CorsFilter; import org.apache.baremaps.server.GeocoderResource; import org.apache.lucene.search.SearcherFactory; import org.apache.lucene.search.SearcherManager; import org.apache.lucene.store.MMapDirectory; -import org.glassfish.hk2.utilities.binding.AbstractBinder; -import org.glassfish.jersey.server.ResourceConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import picocli.CommandLine.Command; @@ -54,28 +56,38 @@ public class Serve implements Callable<Integer> { @Override public Integer call() throws Exception { + try ( var directory = MMapDirectory.open(indexDirectory); var searcherManager = new SearcherManager(directory, new SearcherFactory())) { - var application = new ResourceConfig() - .register(CorsFilter.class) - .register(GeocoderResource.class) - .register(ClassPathResource.class) - .register(new AbstractBinder() { - @Override - protected void configure() { - bind("geocoder").to(String.class).named("directory"); - bind("index.html").to(String.class).named("index"); - bind(searcherManager).to(SearcherManager.class).named("searcherManager"); - } - }); - - var httpService = new HttpJerseyRouterBuilder().buildBlockingStreaming(application); - var serverContext = HttpServers.forPort(port).listenBlockingStreamingAndAwait(httpService); - - logger.info("Listening on {}", serverContext.listenAddress()); - serverContext.awaitShutdown(); + var serverBuilder = Server.builder(); + serverBuilder.http(port); + + var objectMapper = objectMapper(); + var jsonResponseConverter = new JacksonResponseConverterFunction(objectMapper); + serverBuilder.annotatedService(new GeocoderResource(searcherManager), jsonResponseConverter); + + var index = HttpFile.of(ClassLoader.getSystemClassLoader(), "/geocoder/index.html"); + serverBuilder.service("/", index.asService()); + serverBuilder.serviceUnder("/", + FileService.of(ClassLoader.getSystemClassLoader(), "/geocoder")); + + serverBuilder.decorator(CorsService.builderForAnyOrigin() + .allowRequestMethods(HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT, HttpMethod.DELETE, + HttpMethod.OPTIONS, HttpMethod.HEAD) + .allowRequestHeaders(HttpHeaderNames.ORIGIN, HttpHeaderNames.CONTENT_TYPE, + HttpHeaderNames.ACCEPT, HttpHeaderNames.AUTHORIZATION) + .allowCredentials() + .exposeHeaders(HttpHeaderNames.LOCATION) + .newDecorator()); + + serverBuilder.disableServerHeader(); + serverBuilder.disableDateHeader(); + + var server = serverBuilder.build(); + var future = server.start(); + future.join(); } return 0; diff --git a/baremaps-cli/src/main/java/org/apache/baremaps/cli/iploc/Serve.java b/baremaps-cli/src/main/java/org/apache/baremaps/cli/iploc/Serve.java index 4669cb04..eb2716f0 100644 --- a/baremaps-cli/src/main/java/org/apache/baremaps/cli/iploc/Serve.java +++ b/baremaps-cli/src/main/java/org/apache/baremaps/cli/iploc/Serve.java @@ -18,20 +18,22 @@ package org.apache.baremaps.cli.iploc; - +import static org.apache.baremaps.utils.ObjectMapperUtils.objectMapper; + +import com.linecorp.armeria.common.HttpHeaderNames; +import com.linecorp.armeria.common.HttpMethod; +import com.linecorp.armeria.server.Server; +import com.linecorp.armeria.server.annotation.JacksonResponseConverterFunction; +import com.linecorp.armeria.server.cors.CorsService; +import com.linecorp.armeria.server.file.FileService; +import com.linecorp.armeria.server.file.HttpFile; import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; -import io.servicetalk.http.netty.HttpServers; -import io.servicetalk.http.router.jersey.HttpJerseyRouterBuilder; import java.nio.file.Path; import java.util.concurrent.Callable; import javax.sql.DataSource; import org.apache.baremaps.iploc.IpLocRepository; -import org.apache.baremaps.server.ClassPathResource; -import org.apache.baremaps.server.CorsFilter; import org.apache.baremaps.server.IpLocResource; -import org.glassfish.hk2.utilities.binding.AbstractBinder; -import org.glassfish.jersey.server.ResourceConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import picocli.CommandLine.Command; @@ -66,25 +68,33 @@ public class Serve implements Callable<Integer> { IpLocRepository ipLocRepository = new IpLocRepository(dataSource); - var application = new ResourceConfig() - .register(CorsFilter.class) - .register(IpLocResource.class) - .register(ClassPathResource.class) - .register(new AbstractBinder() { - @Override - protected void configure() { - bind("iploc").to(String.class).named("directory"); - bind("index.html").to(String.class).named("index"); - bind(ipLocRepository).to(IpLocRepository.class).named("iplocRepository"); - } - }); - - var httpService = new HttpJerseyRouterBuilder().buildBlockingStreaming(application); - var serverContext = HttpServers.forPort(port).listenBlockingStreamingAndAwait(httpService); - - logger.info("Listening on {}", serverContext.listenAddress()); - - serverContext.awaitShutdown(); + var serverBuilder = Server.builder(); + serverBuilder.http(port); + + var objectMapper = objectMapper(); + var jsonResponseConverter = new JacksonResponseConverterFunction(objectMapper); + serverBuilder.annotatedService(new IpLocResource(ipLocRepository), jsonResponseConverter); + + var index = HttpFile.of(ClassLoader.getSystemClassLoader(), "/iploc/index.html"); + serverBuilder.service("/", index.asService()); + serverBuilder.serviceUnder("/", FileService.of(ClassLoader.getSystemClassLoader(), "/iploc")); + + serverBuilder.decorator(CorsService.builderForAnyOrigin() + .allowRequestMethods(HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT, HttpMethod.DELETE, + HttpMethod.OPTIONS, HttpMethod.HEAD) + .allowRequestHeaders(HttpHeaderNames.ORIGIN, HttpHeaderNames.CONTENT_TYPE, + HttpHeaderNames.ACCEPT, HttpHeaderNames.AUTHORIZATION) + .allowCredentials() + .exposeHeaders(HttpHeaderNames.LOCATION) + .newDecorator()); + + serverBuilder.disableServerHeader(); + serverBuilder.disableDateHeader(); + + var server = serverBuilder.build(); + var future = server.start(); + future.join(); + return 0; } } diff --git a/baremaps-cli/src/main/java/org/apache/baremaps/cli/map/Dev.java b/baremaps-cli/src/main/java/org/apache/baremaps/cli/map/Dev.java index f335ab6b..03342506 100644 --- a/baremaps-cli/src/main/java/org/apache/baremaps/cli/map/Dev.java +++ b/baremaps-cli/src/main/java/org/apache/baremaps/cli/map/Dev.java @@ -24,22 +24,23 @@ import com.linecorp.armeria.server.Server; import com.linecorp.armeria.server.annotation.JacksonResponseConverterFunction; import com.linecorp.armeria.server.cors.CorsService; import com.linecorp.armeria.server.file.FileService; +import com.linecorp.armeria.server.file.HttpFile; import java.io.IOException; import java.nio.file.Path; import java.util.concurrent.Callable; import java.util.concurrent.CompletableFuture; import java.util.function.Supplier; - -import com.linecorp.armeria.server.file.HttpFile; import org.apache.baremaps.cli.Options; import org.apache.baremaps.config.ConfigReader; -import org.apache.baremaps.server.*; +import org.apache.baremaps.server.ChangeResource; +import org.apache.baremaps.server.StyleResource; +import org.apache.baremaps.server.TileResource; +import org.apache.baremaps.server.TilesetResource; import org.apache.baremaps.tilestore.TileStore; import org.apache.baremaps.tilestore.postgres.PostgresTileStore; import org.apache.baremaps.utils.PostgresUtils; import org.apache.baremaps.vectortile.style.Style; import org.apache.baremaps.vectortile.tileset.Tileset; -import org.glassfish.hk2.api.TypeLiteral; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import picocli.CommandLine.Command; @@ -78,18 +79,20 @@ public class Dev implements Callable<Integer> { var tileset = objectMapper.readValue(configReader.read(this.tilesetPath), Tileset.class); var datasource = PostgresUtils.createDataSourceFromObject(tileset.getDatabase()); - var tileStoreType = new TypeLiteral<Supplier<TileStore>>() {}; - var tileStoreSupplier = (Supplier<TileStore>) () -> { + var tilesetSupplier = (Supplier<Tileset>) () -> { try { - var config = configReader.read(this.tilesetPath); - var tilesetObject = - objectMapper.readValue(config, Tileset.class); - return new PostgresTileStore(datasource, tilesetObject); + var config = configReader.read(tilesetPath); + return objectMapper.readValue(config, Tileset.class); } catch (IOException e) { throw new RuntimeException(e); } }; + var tileStoreSupplier = (Supplier<TileStore>) () -> { + var tileJSON = tilesetSupplier.get(); + return new PostgresTileStore(datasource, tileJSON); + }; + var styleSupplier = (Supplier<Style>) () -> { try { var config = configReader.read(stylePath); @@ -99,33 +102,26 @@ public class Dev implements Callable<Integer> { } }; - var tileJSONSupplier = (Supplier<Tileset>) () -> { - try { - var config = configReader.read(tilesetPath); - return objectMapper.readValue(config, Tileset.class); - } catch (IOException e) { - throw new RuntimeException(e); - } - }; - var serverBuilder = Server.builder(); serverBuilder.http(port); - JacksonResponseConverterFunction jsonResponseConverter = new JacksonResponseConverterFunction(objectMapper); - serverBuilder.annotatedService(new ChangeResource(tilesetPath, stylePath), jsonResponseConverter); + JacksonResponseConverterFunction jsonResponseConverter = + new JacksonResponseConverterFunction(objectMapper); + serverBuilder.annotatedService(new ChangeResource(tilesetPath, stylePath), + jsonResponseConverter); serverBuilder.annotatedService(new TileResource(tileStoreSupplier), jsonResponseConverter); serverBuilder.annotatedService(new StyleResource(styleSupplier), jsonResponseConverter); - serverBuilder.annotatedService(new TilesetResource(tileJSONSupplier), jsonResponseConverter); + serverBuilder.annotatedService(new TilesetResource(tilesetSupplier), jsonResponseConverter); HttpFile index = HttpFile.of(ClassLoader.getSystemClassLoader(), "/assets/viewer.html"); serverBuilder.service("/", index.asService()); serverBuilder.serviceUnder("/", FileService.of(ClassLoader.getSystemClassLoader(), "/assets")); serverBuilder.decorator(CorsService.builderForAnyOrigin() - .allowRequestMethods(HttpMethod.POST, HttpMethod.GET, HttpMethod.PUT) - .allowRequestHeaders("Origin", "Content-Type", "Accept") - .newDecorator()); - + .allowRequestMethods(HttpMethod.POST, HttpMethod.GET, HttpMethod.PUT) + .allowRequestHeaders("Origin", "Content-Type", "Accept") + .newDecorator()); + serverBuilder.disableServerHeader(); serverBuilder.disableDateHeader(); diff --git a/baremaps-cli/src/main/java/org/apache/baremaps/cli/map/MBTiles.java b/baremaps-cli/src/main/java/org/apache/baremaps/cli/map/MBTiles.java index 72e06639..487e8a0c 100644 --- a/baremaps-cli/src/main/java/org/apache/baremaps/cli/map/MBTiles.java +++ b/baremaps-cli/src/main/java/org/apache/baremaps/cli/map/MBTiles.java @@ -17,14 +17,19 @@ package org.apache.baremaps.cli.map; -import static io.servicetalk.data.jackson.jersey.ServiceTalkJacksonSerializerFeature.newContextResolver; import static org.apache.baremaps.utils.ObjectMapperUtils.objectMapper; import com.github.benmanes.caffeine.cache.CaffeineSpec; -import io.servicetalk.http.netty.HttpServers; -import io.servicetalk.http.router.jersey.HttpJerseyRouterBuilder; +import com.linecorp.armeria.common.HttpHeaderNames; +import com.linecorp.armeria.common.HttpMethod; +import com.linecorp.armeria.server.Server; +import com.linecorp.armeria.server.annotation.JacksonResponseConverterFunction; +import com.linecorp.armeria.server.cors.CorsService; +import com.linecorp.armeria.server.file.FileService; +import com.linecorp.armeria.server.file.HttpFile; import java.nio.file.Path; import java.util.concurrent.Callable; +import java.util.concurrent.CompletableFuture; import java.util.function.Supplier; import org.apache.baremaps.cli.Options; import org.apache.baremaps.config.ConfigReader; @@ -35,9 +40,6 @@ import org.apache.baremaps.tilestore.mbtiles.MBTilesStore; import org.apache.baremaps.utils.SqliteUtils; import org.apache.baremaps.vectortile.style.Style; import org.apache.baremaps.vectortile.tilejson.TileJSON; -import org.glassfish.hk2.api.TypeLiteral; -import org.glassfish.hk2.utilities.binding.AbstractBinder; -import org.glassfish.jersey.server.ResourceConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import picocli.CommandLine.Command; @@ -77,45 +79,45 @@ public class MBTiles implements Callable<Integer> { var caffeineSpec = CaffeineSpec.parse(cache); var datasource = SqliteUtils.createDataSource(mbtilesPath, true); - var tileStoreSupplierType = new TypeLiteral<Supplier<TileStore>>() {}; var tileStore = new MBTilesStore(datasource); var tileCache = new TileCache(tileStore, caffeineSpec); var tileStoreSupplier = (Supplier<TileStore>) () -> tileCache; - var styleSupplierType = new TypeLiteral<Supplier<Style>>() {}; var style = objectMapper.readValue(configReader.read(stylePath), Style.class); var styleSupplier = (Supplier<Style>) () -> style; - var tileJSONSupplierType = new TypeLiteral<Supplier<TileJSON>>() {}; var tileJSON = objectMapper.readValue(configReader.read(tileJSONPath), TileJSON.class); var tileJSONSupplier = (Supplier<TileJSON>) () -> tileJSON; - // Configure the application - var application = - new ResourceConfig() - .register(CorsFilter.class) - .register(TileResource.class) - .register(StyleResource.class) - .register(TilesetResource.class) - .register(ClassPathResource.class) - .register(newContextResolver(objectMapper)) - .register(new AbstractBinder() { - @Override - protected void configure() { - bind("assets").to(String.class).named("directory"); - bind("server.html").to(String.class).named("index"); - bind(tileStoreSupplier).to(tileStoreSupplierType); - bind(styleSupplier).to(styleSupplierType); - bind(tileJSONSupplier).to(tileJSONSupplierType); - } - }); - - var httpService = new HttpJerseyRouterBuilder().buildBlockingStreaming(application); - var serverContext = HttpServers.forPort(port).listenBlockingStreamingAndAwait(httpService); - - logger.info("Listening on {}", serverContext.listenAddress()); - - serverContext.awaitShutdown(); + var serverBuilder = Server.builder(); + serverBuilder.http(port); + + JacksonResponseConverterFunction jsonResponseConverter = + new JacksonResponseConverterFunction(objectMapper); + serverBuilder.annotatedService(new TileResource(tileStoreSupplier), jsonResponseConverter); + serverBuilder.annotatedService(new StyleResource(styleSupplier), jsonResponseConverter); + serverBuilder.annotatedService(new TileJSONResource(tileJSONSupplier), jsonResponseConverter); + + HttpFile index = HttpFile.of(ClassLoader.getSystemClassLoader(), "/assets/server.html"); + serverBuilder.service("/", index.asService()); + serverBuilder.serviceUnder("/", FileService.of(ClassLoader.getSystemClassLoader(), "/assets")); + + serverBuilder.decorator(CorsService.builderForAnyOrigin() + .allowRequestMethods(HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT, HttpMethod.DELETE, + HttpMethod.OPTIONS, HttpMethod.HEAD) + .allowRequestHeaders(HttpHeaderNames.ORIGIN, HttpHeaderNames.CONTENT_TYPE, + HttpHeaderNames.ACCEPT, HttpHeaderNames.AUTHORIZATION) + .allowCredentials() + .exposeHeaders(HttpHeaderNames.LOCATION) + .newDecorator()); + + serverBuilder.disableServerHeader(); + serverBuilder.disableDateHeader(); + + Server server = serverBuilder.build(); + CompletableFuture<Void> future = server.start(); + future.join(); + return 0; } } diff --git a/baremaps-cli/src/main/java/org/apache/baremaps/cli/map/Map.java b/baremaps-cli/src/main/java/org/apache/baremaps/cli/map/Map.java index 0f0f1a4c..fa825607 100644 --- a/baremaps-cli/src/main/java/org/apache/baremaps/cli/map/Map.java +++ b/baremaps-cli/src/main/java/org/apache/baremaps/cli/map/Map.java @@ -23,8 +23,7 @@ import picocli.CommandLine; import picocli.CommandLine.Command; @Command(name = "map", description = "Map commands.", - subcommands = {Init.class, Export.class, Serve.class, Dev.class, StyleCommand.class, - MBTiles.class}, + subcommands = {Init.class, Export.class, Serve.class, Dev.class, MBTiles.class}, sortOptions = false) public class Map implements Runnable { diff --git a/baremaps-cli/src/main/java/org/apache/baremaps/cli/map/Serve.java b/baremaps-cli/src/main/java/org/apache/baremaps/cli/map/Serve.java index d3163566..de2da754 100644 --- a/baremaps-cli/src/main/java/org/apache/baremaps/cli/map/Serve.java +++ b/baremaps-cli/src/main/java/org/apache/baremaps/cli/map/Serve.java @@ -17,20 +17,25 @@ package org.apache.baremaps.cli.map; -import static io.servicetalk.data.jackson.jersey.ServiceTalkJacksonSerializerFeature.newContextResolver; import static org.apache.baremaps.utils.ObjectMapperUtils.objectMapper; import com.github.benmanes.caffeine.cache.CaffeineSpec; -import io.servicetalk.http.netty.HttpServers; -import io.servicetalk.http.router.jersey.HttpJerseyRouterBuilder; +import com.linecorp.armeria.common.HttpHeaderNames; +import com.linecorp.armeria.common.HttpMethod; +import com.linecorp.armeria.server.Server; +import com.linecorp.armeria.server.annotation.JacksonResponseConverterFunction; +import com.linecorp.armeria.server.cors.CorsService; +import com.linecorp.armeria.server.file.FileService; +import com.linecorp.armeria.server.file.HttpFile; import java.nio.file.Path; import java.util.concurrent.Callable; +import java.util.concurrent.CompletableFuture; import java.util.function.Supplier; -import javax.sql.DataSource; import org.apache.baremaps.cli.Options; import org.apache.baremaps.config.ConfigReader; -import org.apache.baremaps.server.*; -import org.apache.baremaps.server.CorsFilter; +import org.apache.baremaps.server.StyleResource; +import org.apache.baremaps.server.TileJSONResource; +import org.apache.baremaps.server.TileResource; import org.apache.baremaps.tilestore.TileCache; import org.apache.baremaps.tilestore.TileStore; import org.apache.baremaps.tilestore.postgres.PostgresTileStore; @@ -38,9 +43,6 @@ import org.apache.baremaps.utils.PostgresUtils; import org.apache.baremaps.vectortile.style.Style; import org.apache.baremaps.vectortile.tilejson.TileJSON; import org.apache.baremaps.vectortile.tileset.Tileset; -import org.glassfish.hk2.api.TypeLiteral; -import org.glassfish.hk2.utilities.binding.AbstractBinder; -import org.glassfish.jersey.server.ResourceConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import picocli.CommandLine.Command; @@ -83,46 +85,45 @@ public class Serve implements Callable<Integer> { var tileset = objectMapper.readValue(configReader.read(tilesetPath), Tileset.class); var datasource = PostgresUtils.createDataSourceFromObject(tileset.getDatabase()); - var tileStoreSupplierType = new TypeLiteral<Supplier<TileStore>>() {}; var tileStore = new PostgresTileStore(datasource, tileset); var tileCache = new TileCache(tileStore, caffeineSpec); var tileStoreSupplier = (Supplier<TileStore>) () -> tileCache; - var styleSupplierType = new TypeLiteral<Supplier<Style>>() {}; var style = objectMapper.readValue(configReader.read(stylePath), Style.class); var styleSupplier = (Supplier<Style>) () -> style; - var tileJSONSupplierType = new TypeLiteral<Supplier<TileJSON>>() {}; var tileJSON = objectMapper.readValue(configReader.read(tilesetPath), TileJSON.class); var tileJSONSupplier = (Supplier<TileJSON>) () -> tileJSON; - var application = - new ResourceConfig() - .register(CorsFilter.class) - .register(TileResource.class) - .register(StyleResource.class) - .register(TileJSONResource.class) - .register(SearchResource.class) - .register(ClassPathResource.class) - .register(newContextResolver(objectMapper)) - .register(new AbstractBinder() { - @Override - protected void configure() { - bind("assets").to(String.class).named("directory"); - bind("server.html").to(String.class).named("index"); - bind(datasource).to(DataSource.class); - bind(tileStoreSupplier).to(tileStoreSupplierType); - bind(styleSupplier).to(styleSupplierType); - bind(tileJSONSupplier).to(tileJSONSupplierType); - } - }); - - var httpService = new HttpJerseyRouterBuilder().buildBlockingStreaming(application); - var serverContext = HttpServers.forPort(port).listenBlockingStreamingAndAwait(httpService); - - logger.info("Listening on {}", serverContext.listenAddress()); - - serverContext.awaitShutdown(); + var serverBuilder = Server.builder(); + serverBuilder.http(port); + + JacksonResponseConverterFunction jsonResponseConverter = + new JacksonResponseConverterFunction(objectMapper); + serverBuilder.annotatedService(new TileResource(tileStoreSupplier), jsonResponseConverter); + serverBuilder.annotatedService(new StyleResource(styleSupplier), jsonResponseConverter); + serverBuilder.annotatedService(new TileJSONResource(tileJSONSupplier), jsonResponseConverter); + + HttpFile index = HttpFile.of(ClassLoader.getSystemClassLoader(), "/assets/server.html"); + serverBuilder.service("/", index.asService()); + serverBuilder.serviceUnder("/", FileService.of(ClassLoader.getSystemClassLoader(), "/assets")); + + serverBuilder.decorator(CorsService.builderForAnyOrigin() + .allowRequestMethods(HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT, HttpMethod.DELETE, + HttpMethod.OPTIONS, HttpMethod.HEAD) + .allowRequestHeaders(HttpHeaderNames.ORIGIN, HttpHeaderNames.CONTENT_TYPE, + HttpHeaderNames.ACCEPT, HttpHeaderNames.AUTHORIZATION) + .allowCredentials() + .exposeHeaders(HttpHeaderNames.LOCATION) + .newDecorator()); + + serverBuilder.disableServerHeader(); + serverBuilder.disableDateHeader(); + + Server server = serverBuilder.build(); + CompletableFuture<Void> future = server.start(); + future.join(); + return 0; } } diff --git a/baremaps-cli/src/main/java/org/apache/baremaps/cli/map/StyleCommand.java b/baremaps-cli/src/main/java/org/apache/baremaps/cli/map/StyleCommand.java deleted file mode 100644 index e77f6425..00000000 --- a/baremaps-cli/src/main/java/org/apache/baremaps/cli/map/StyleCommand.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to you under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.baremaps.cli.map; - -import static io.servicetalk.data.jackson.jersey.ServiceTalkJacksonSerializerFeature.newContextResolver; -import static org.apache.baremaps.utils.ObjectMapperUtils.objectMapper; - -import io.servicetalk.http.netty.HttpServers; -import io.servicetalk.http.router.jersey.HttpJerseyRouterBuilder; -import java.io.IOException; -import java.net.URL; -import java.nio.file.Path; -import java.util.Map; -import java.util.concurrent.Callable; -import java.util.function.Supplier; -import org.apache.baremaps.cli.Options; -import org.apache.baremaps.config.ConfigReader; -import org.apache.baremaps.server.*; -import org.apache.baremaps.vectortile.style.Style; -import org.apache.baremaps.vectortile.style.StyleSource; -import org.glassfish.hk2.api.TypeLiteral; -import org.glassfish.hk2.utilities.binding.AbstractBinder; -import org.glassfish.jersey.server.ResourceConfig; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import picocli.CommandLine.Command; -import picocli.CommandLine.Mixin; -import picocli.CommandLine.Option; - -@Command(name = "style", - description = "Start a development server with live reload for editing styles. Overrides the style sources.") -public class StyleCommand implements Callable<Integer> { - - private static final Logger logger = LoggerFactory.getLogger(StyleCommand.class); - - @Mixin - private Options options; - - @Option(names = {"--tiles"}, paramLabel = "TILES", description = "The tiles url.", - required = true) - private URL tilesUrl; - - @Option(names = {"--style"}, paramLabel = "STYLE", description = "The style file.", - required = true) - private Path stylePath; - - @Option(names = {"--host"}, paramLabel = "HOST", description = "The host of the server.") - private String host = "localhost"; - - @Option(names = {"--port"}, paramLabel = "PORT", description = "The port of the server.") - private int port = 9000; - - @Override - public Integer call() throws Exception { - var configReader = new ConfigReader(); - var objectMapper = objectMapper(); - - var styleSupplierType = new TypeLiteral<Supplier<Style>>() {}; - var styleSupplier = (Supplier<Style>) () -> { - try { - var config = configReader.read(stylePath); - var object = objectMapper.readValue(config, Style.class); - var styleSource = new StyleSource("vector", tilesUrl.toString()); - object.setSources(Map.of("baremaps", styleSource)); - return object; - } catch (IOException e) { - throw new RuntimeException(e); - } - }; - - var application = new ResourceConfig() - .register(CorsFilter.class) - .register(ChangeResource.class) - .register(StyleResource.class) - .register(ChangeResource.class) - .register(ClassPathResource.class) - .register(newContextResolver(objectMapper)) - .register(new AbstractBinder() { - @Override - protected void configure() { - bind("assets").to(String.class).named("directory"); - bind("viewer.html").to(String.class).named("index"); - bind(stylePath).to(Path.class).named("style"); - bind(styleSupplier).to(styleSupplierType); - } - }); - - var httpService = new HttpJerseyRouterBuilder().buildBlockingStreaming(application); - var serverContext = HttpServers.forPort(port).listenBlockingStreamingAndAwait(httpService); - - logger.info("Listening on {}", serverContext.listenAddress()); - serverContext.awaitShutdown(); - - return 0; - } -} diff --git a/baremaps-server/pom.xml b/baremaps-server/pom.xml index 8ebd29dd..263d28d3 100644 --- a/baremaps-server/pom.xml +++ b/baremaps-server/pom.xml @@ -34,54 +34,10 @@ limitations under the License. <groupId>com.linecorp.armeria</groupId> <artifactId>armeria-reactor3</artifactId> </dependency> - <dependency> - <groupId>io.servicetalk</groupId> - <artifactId>servicetalk-http-api</artifactId> - </dependency> - <dependency> - <groupId>io.servicetalk</groupId> - <artifactId>servicetalk-transport-api</artifactId> - </dependency> - <dependency> - <groupId>jakarta.ws.rs</groupId> - <artifactId>jakarta.ws.rs-api</artifactId> - </dependency> <dependency> <groupId>org.apache.baremaps</groupId> <artifactId>baremaps-core</artifactId> </dependency> - <dependency> - <groupId>org.glassfish.jersey.inject</groupId> - <artifactId>jersey-hk2</artifactId> - </dependency> - <dependency> - <groupId>org.glassfish.jersey.media</groupId> - <artifactId>jersey-media-json-jackson</artifactId> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.glassfish.jersey.media</groupId> - <artifactId>jersey-media-multipart</artifactId> - </dependency> - <dependency> - <groupId>org.glassfish.jersey.media</groupId> - <artifactId>jersey-media-sse</artifactId> - </dependency> - <dependency> - <groupId>org.glassfish.jersey.test-framework</groupId> - <artifactId>jersey-test-framework-core</artifactId> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.glassfish.jersey.test-framework</groupId> - <artifactId>jersey-test-framework-util</artifactId> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.glassfish.jersey.test-framework.providers</groupId> - <artifactId>jersey-test-framework-provider-inmemory</artifactId> - <scope>test</scope> - </dependency> </dependencies> </project> diff --git a/baremaps-server/src/main/java/org/apache/baremaps/server/BaseUriRequestFilter.java b/baremaps-server/src/main/java/org/apache/baremaps/server/BaseUriRequestFilter.java deleted file mode 100644 index 4e88a968..00000000 --- a/baremaps-server/src/main/java/org/apache/baremaps/server/BaseUriRequestFilter.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to you under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.baremaps.server; - - - -import javax.inject.Singleton; -import javax.ws.rs.container.ContainerRequestContext; -import javax.ws.rs.container.ContainerRequestFilter; -import javax.ws.rs.container.PreMatching; -import javax.ws.rs.core.UriBuilder; -import javax.ws.rs.ext.Provider; - -/** - * A filter that sets the base URI of the request. - */ -@Provider -@PreMatching -@Singleton -public class BaseUriRequestFilter implements ContainerRequestFilter { - - @Override - public void filter(ContainerRequestContext requestContext) { - var baseUri = UriBuilder.fromUri(requestContext.getUriInfo().getBaseUri()); - var headers = requestContext.getHeaders(); - if (headers.get("X-Forwarded-Proto") != null) { - baseUri.scheme(headers.getFirst("X-Forwarded-Proto")); - } - if (headers.get("X-Forwarded-Host") != null) { - baseUri.host(headers.getFirst("X-Forwarded-Host")); - } - if (headers.get("X-Forwarded-Port") != null) { - baseUri.port(Integer.parseInt(headers.getFirst("X-Forwarded-Port"))); - } - requestContext.setRequestUri(baseUri.build(), requestContext.getUriInfo().getRequestUri()); - } -} diff --git a/baremaps-server/src/main/java/org/apache/baremaps/server/ClassPathResource.java b/baremaps-server/src/main/java/org/apache/baremaps/server/ClassPathResource.java deleted file mode 100644 index f1d0dbaf..00000000 --- a/baremaps-server/src/main/java/org/apache/baremaps/server/ClassPathResource.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to you under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.baremaps.server; - -import java.io.IOException; -import java.io.InputStream; -import javax.inject.Inject; -import javax.inject.Named; -import javax.inject.Singleton; -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.core.Response; - -/** - * Serves static resources from the class path. - */ -@Singleton -@Path("/") -public class ClassPathResource { - - private final String directory; - - private final String index; - - /** - * Constructs a {@code ClassPathResources}. - * - * @param directory the directory - * @param index the index - */ - @Inject - public ClassPathResource( - @Named("directory") String directory, - @Named("index") String index) { - this.directory = directory; - this.index = index; - } - - /** - * Serves a static resource from the class path. - * - * @param path the path - * @return the response - */ - @GET - @Path("{path:.*}") - public Response get(@PathParam("path") String path) { - if (path.isEmpty() || path.endsWith("/")) { - path += index; - } - path = String.format("%s/%s", directory, path); - try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream(path)) { - return Response.ok().entity(inputStream.readAllBytes()).build(); - } catch (NullPointerException | IOException e) { - return Response.status(404).build(); - } - } -} diff --git a/baremaps-server/src/main/java/org/apache/baremaps/server/CorsFilter.java b/baremaps-server/src/main/java/org/apache/baremaps/server/CorsFilter.java deleted file mode 100644 index 60e42147..00000000 --- a/baremaps-server/src/main/java/org/apache/baremaps/server/CorsFilter.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to you under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.baremaps.server; - - - -import javax.ws.rs.container.ContainerRequestContext; -import javax.ws.rs.container.ContainerRequestFilter; -import javax.ws.rs.container.ContainerResponseContext; -import javax.ws.rs.container.ContainerResponseFilter; -import javax.ws.rs.core.Response; -import javax.ws.rs.ext.Provider; - -/** - * A filter that adds CORS headers to requests. - */ -@Provider -public class CorsFilter implements ContainerRequestFilter, ContainerResponseFilter { - - private final String ACCESS_CONTROL_ALLOW_ORIGIN = "Access-Control-Allow-Origin"; - private final String ACCESS_CONTROL_ALLOW_CREDENTIALS = "Access-Control-Allow-Credentials"; - private final String ACCESS_CONTROL_ALLOW_METHODS = "Access-Control-Allow-Methods"; - private final String ACCESS_CONTROL_ALLOW_HEADERS = "Access-Control-Allow-Headers"; - private final String ACCESS_CONTROL_EXPOSE_HEADERS = "Access-Control-Expose-Headers"; - private final String ORIGIN = "Origin"; - private final String VARY = "Vary"; - - @Override - public void filter(ContainerRequestContext requestContext) { - var origin = requestContext.getHeaderString(ORIGIN); - if (origin == null) { - return; - } - if (requestContext.getMethod().equalsIgnoreCase("OPTIONS")) { - preflight(origin, requestContext); - } - } - - @Override - public void filter(ContainerRequestContext requestContext, - ContainerResponseContext responseContext) { - var origin = requestContext.getHeaderString(ORIGIN); - if (origin == null || requestContext.getMethod().equalsIgnoreCase("OPTIONS") - || requestContext.getProperty("cors.failure") != null) { - return; - } - responseContext.getHeaders().putSingle(ACCESS_CONTROL_ALLOW_ORIGIN, origin); - responseContext.getHeaders().putSingle(ACCESS_CONTROL_ALLOW_METHODS, - "GET, POST, PUT, DELETE, OPTIONS, HEAD"); - responseContext.getHeaders().putSingle(ACCESS_CONTROL_ALLOW_HEADERS, - "origin, content-type, accept, authorization"); - responseContext.getHeaders().putSingle(ACCESS_CONTROL_ALLOW_CREDENTIALS, "true"); - responseContext.getHeaders().putSingle(ACCESS_CONTROL_EXPOSE_HEADERS, "Location"); - responseContext.getHeaders().putSingle(VARY, ORIGIN); - } - - private void preflight(String origin, ContainerRequestContext requestContext) { - // Respond with a 204 no content since we are returning an empty response with just the header - // for preflight - var builder = Response.noContent(); - builder.header(ACCESS_CONTROL_ALLOW_ORIGIN, origin); - builder.header(VARY, ORIGIN); - builder.header(ACCESS_CONTROL_ALLOW_METHODS, "GET, POST, PUT, DELETE, OPTIONS, HEAD"); - builder.header(ACCESS_CONTROL_ALLOW_HEADERS, "origin, content-type, accept, authorization"); - builder.header(ACCESS_CONTROL_ALLOW_CREDENTIALS, "true"); - builder.header(ACCESS_CONTROL_EXPOSE_HEADERS, "Location"); - requestContext.abortWith(builder.build()); - } -} diff --git a/baremaps-server/src/main/java/org/apache/baremaps/server/GeocoderResource.java b/baremaps-server/src/main/java/org/apache/baremaps/server/GeocoderResource.java index 901a055e..14ca3840 100644 --- a/baremaps-server/src/main/java/org/apache/baremaps/server/GeocoderResource.java +++ b/baremaps-server/src/main/java/org/apache/baremaps/server/GeocoderResource.java @@ -17,23 +17,22 @@ package org.apache.baremaps.server; -import static com.google.common.net.HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN; -import static com.google.common.net.HttpHeaders.CONTENT_TYPE; -import static javax.ws.rs.core.MediaType.APPLICATION_JSON; +import static com.google.common.net.HttpHeaders.*; +import static io.netty.handler.codec.http.HttpHeaders.Values.APPLICATION_JSON; +import com.linecorp.armeria.common.HttpResponse; +import com.linecorp.armeria.common.HttpStatus; +import com.linecorp.armeria.common.ResponseHeaders; +import com.linecorp.armeria.server.annotation.Default; +import com.linecorp.armeria.server.annotation.Get; +import com.linecorp.armeria.server.annotation.Param; +import com.linecorp.armeria.server.annotation.ProducesJson; import java.io.IOException; import java.text.ParseException; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; -import javax.inject.Inject; -import javax.inject.Singleton; -import javax.ws.rs.DefaultValue; -import javax.ws.rs.GET; -import javax.ws.rs.QueryParam; -import javax.ws.rs.WebApplicationException; -import javax.ws.rs.core.Response; import org.apache.baremaps.geocoder.GeonamesQueryBuilder; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.ScoreDoc; @@ -44,8 +43,6 @@ import org.slf4j.LoggerFactory; /** * A resource that provides access to the geocoder. */ -@Singleton [email protected]("/") public class GeocoderResource { private static final Logger logger = LoggerFactory.getLogger(GeocoderResource.class); @@ -53,27 +50,23 @@ public class GeocoderResource { record GeocoderResponse(List<GeocoderResult> results) { } - record GeocoderResult(float score, Map<String, Object> data) { } - private final SearcherManager searcherManager; - @Inject public GeocoderResource(SearcherManager searcherManager) { this.searcherManager = searcherManager; } - @GET - @javax.ws.rs.Path("/api/geocoder") - public Response searchLocations( - @QueryParam("queryText") String queryText, - @QueryParam("countryCode") @DefaultValue("") String countryCode, - @QueryParam("limit") @DefaultValue("10") int limit) { + @Get("/api/geocoder") + @ProducesJson + public HttpResponse searchLocations( + @Param("queryText") String queryText, + @Param("countryCode") @Default("") String countryCode, + @Param("limit") @Default("10") int limit) { if (queryText == null) { - throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST) - .entity("The queryText parameter is mandatory").build()); + return HttpResponse.of(HttpStatus.BAD_REQUEST); } try { IndexSearcher searcher = searcherManager.acquire(); @@ -91,20 +84,25 @@ public class GeocoderResource { var result = searcher.search(query, limit); var results = Arrays.stream(result.scoreDocs).map(scoreDoc -> asResult(searcher, scoreDoc)).toList(); - return Response.status(Response.Status.OK).header(ACCESS_CONTROL_ALLOW_ORIGIN, "*") - .header(CONTENT_TYPE, APPLICATION_JSON).entity(new GeocoderResponse(results)).build(); + + var headers = ResponseHeaders.builder(200) + .add(CONTENT_TYPE, APPLICATION_JSON) + .add(ACCESS_CONTROL_ALLOW_ORIGIN, "*") + .build(); + + return HttpResponse.ofJson(headers, new GeocoderResponse(results)); } catch (IllegalArgumentException e) { logger.warn("Illegal input while processing request", e); - return Response.status(Response.Status.BAD_REQUEST).build(); + return HttpResponse.of(HttpStatus.BAD_REQUEST); } catch (IOException | ParseException e) { logger.error("Error while processing request", e); - return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); + return HttpResponse.of(HttpStatus.INTERNAL_SERVER_ERROR); } finally { searcherManager.release(searcher); } } catch (IOException e) { logger.error("Error while processing request", e); - return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); + return HttpResponse.of(HttpStatus.INTERNAL_SERVER_ERROR); } } diff --git a/baremaps-server/src/main/java/org/apache/baremaps/server/IpLocResource.java b/baremaps-server/src/main/java/org/apache/baremaps/server/IpLocResource.java index 621d98db..4d22dd6a 100644 --- a/baremaps-server/src/main/java/org/apache/baremaps/server/IpLocResource.java +++ b/baremaps-server/src/main/java/org/apache/baremaps/server/IpLocResource.java @@ -18,19 +18,17 @@ package org.apache.baremaps.server; import static com.google.common.net.HttpHeaders.*; -import static javax.ws.rs.core.MediaType.APPLICATION_JSON; +import static io.netty.handler.codec.http.HttpHeaders.Values.APPLICATION_JSON; import com.google.common.net.InetAddresses; -import io.servicetalk.http.api.StreamingHttpRequest; -import io.servicetalk.transport.api.ConnectionContext; +import com.linecorp.armeria.common.*; +import com.linecorp.armeria.server.ServiceRequestContext; +import com.linecorp.armeria.server.annotation.Get; +import com.linecorp.armeria.server.annotation.Param; +import com.linecorp.armeria.server.annotation.ProducesJson; import java.net.InetSocketAddress; import java.util.List; import java.util.Optional; -import javax.inject.Inject; -import javax.inject.Singleton; -import javax.ws.rs.GET; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.*; import org.apache.baremaps.iploc.IpLocObject; import org.apache.baremaps.iploc.IpLocRepository; import org.slf4j.Logger; @@ -39,15 +37,12 @@ import org.slf4j.LoggerFactory; /** * A resource that provides access to the IP location database. */ -@Singleton [email protected]("/") public class IpLocResource { private static final Logger logger = LoggerFactory.getLogger(IpLocResource.class); private final IpLocRepository ipLocRepository; - @Inject public IpLocResource(IpLocRepository ipLocRepository) { this.ipLocRepository = ipLocRepository; } @@ -55,52 +50,56 @@ public class IpLocResource { public record IP(String ip) { } - @GET - @javax.ws.rs.Path("/api/ip") - public Response ip( - @Context ConnectionContext context, - @Context StreamingHttpRequest request, - @QueryParam("ip") String ip) { + @Get("/api/ip") + @ProducesJson + public HttpResponse ip( + ServiceRequestContext context, + HttpHeaders requestHeaders, + @Param("ip") String ip) { try { var address = InetAddresses.forString( Optional.ofNullable((CharSequence) ip) - .or(() -> Optional.ofNullable(request.headers().get("X-Forwarded-For"))) - .or(() -> Optional.ofNullable(request.headers().get("X-Real-IP"))) - .orElse(((InetSocketAddress) context.remoteAddress()).getAddress().getHostAddress()) + .or(() -> Optional.ofNullable(requestHeaders.get("X-Forwarded-For"))) + .or(() -> Optional.ofNullable(requestHeaders.get("X-Real-IP"))) + .orElse(context.remoteAddress().getAddress().getHostAddress()) .toString().split(",")[0].trim()); - return Response.status(200) // lgtm [java/xss] - .header(ACCESS_CONTROL_ALLOW_ORIGIN, "*") - .header(CONTENT_TYPE, APPLICATION_JSON) - .entity(new IP(address.toString())).build(); + + var responseHeaders = ResponseHeaders.builder(200) + .add(CONTENT_TYPE, APPLICATION_JSON) + .add(ACCESS_CONTROL_ALLOW_ORIGIN, "*") + .build(); + + return HttpResponse.ofJson(responseHeaders, new IP(address.toString())); } catch (IllegalArgumentException e) { logger.error("Error while processing request", e); - return Response.serverError().build(); + return HttpResponse.of(HttpStatus.INTERNAL_SERVER_ERROR); } } - @GET - @javax.ws.rs.Path("/api/iploc") + @Get("/api/iploc") + @ProducesJson public Response iploc( - @Context ConnectionContext context, - @Context StreamingHttpRequest request, - @QueryParam("ip") String ip) { + ServiceRequestContext context, + HttpHeaders requestHeaders, + @Param("ip") String ip) { try { var address = InetAddresses.forString( Optional.ofNullable((CharSequence) ip) - .or(() -> Optional.ofNullable(request.headers().get("X-Forwarded-For"))) - .or(() -> Optional.ofNullable(request.headers().get("X-Real-IP"))) + .or(() -> Optional.ofNullable(requestHeaders.get("X-Forwarded-For"))) + .or(() -> Optional.ofNullable(requestHeaders.get("X-Real-IP"))) .orElse(((InetSocketAddress) context.remoteAddress()).getAddress().getHostAddress()) .toString().split(",")[0].trim()); List<IpLocObject> inetnumLocations = ipLocRepository.findByInetAddress(address); List<InetnumLocationDto> inetnumLocationDtos = inetnumLocations.stream().map(InetnumLocationDto::new).toList(); - return Response.status(200) // lgtm [java/xss] - .header(ACCESS_CONTROL_ALLOW_ORIGIN, "*") - .header(CONTENT_TYPE, APPLICATION_JSON) - .entity(inetnumLocationDtos).build(); + var responseHeaders = ResponseHeaders.builder(200) + .add(CONTENT_TYPE, APPLICATION_JSON) + .add(ACCESS_CONTROL_ALLOW_ORIGIN, "*") + .build(); + return HttpResponse.ofJson(responseHeaders, inetnumLocationDtos); } catch (IllegalArgumentException e) { logger.error("Error while processing request", e); - return Response.serverError().build(); + return HttpResponse.of(HttpStatus.INTERNAL_SERVER_ERROR); } } diff --git a/baremaps-server/src/main/java/org/apache/baremaps/server/SearchResource.java b/baremaps-server/src/main/java/org/apache/baremaps/server/SearchResource.java index 5b6eaaac..d7dc7002 100644 --- a/baremaps-server/src/main/java/org/apache/baremaps/server/SearchResource.java +++ b/baremaps-server/src/main/java/org/apache/baremaps/server/SearchResource.java @@ -20,26 +20,22 @@ package org.apache.baremaps.server; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.linecorp.armeria.common.HttpResponse; +import com.linecorp.armeria.common.HttpStatus; +import com.linecorp.armeria.server.annotation.Default; +import com.linecorp.armeria.server.annotation.Get; +import com.linecorp.armeria.server.annotation.Param; +import com.linecorp.armeria.server.annotation.ProducesJson; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; -import javax.inject.Inject; -import javax.inject.Singleton; import javax.sql.DataSource; -import javax.ws.rs.DefaultValue; -import javax.ws.rs.GET; -import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * A resource that searches for entities in the database. */ -@Singleton [email protected]("/") public class SearchResource { private static final Logger logger = LoggerFactory.getLogger(SearchResource.class); @@ -55,7 +51,6 @@ public class SearchResource { private final DataSource dataSource; - @Inject public SearchResource(DataSource dataSource) { this.dataSource = dataSource; } @@ -66,12 +61,11 @@ public class SearchResource { record SearchResult(long id, JsonNode tags, String wkt, double score) { } - @GET - @javax.ws.rs.Path("/api/search") - @Produces(MediaType.APPLICATION_JSON) - public Response search( - @QueryParam("query") String queryText, - @QueryParam("limit") @DefaultValue("10") int limit) { + @Get("/api/search") + @ProducesJson + public HttpResponse search( + @Param("query") String queryText, + @Param("limit") @Default("10") int limit) { try (var connection = dataSource.getConnection(); var statement = connection.prepareStatement(SEARCH_QUERY)) { statement.setString(1, queryText); @@ -88,10 +82,10 @@ public class SearchResource { } } var response = new SearchResponse(list); - return Response.status(Response.Status.OK).entity(response).build(); + return HttpResponse.ofJson(response); } catch (SQLException | JsonProcessingException e) { logger.error("Error while searching", e); - return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); + return HttpResponse.of(HttpStatus.INTERNAL_SERVER_ERROR); } } } diff --git a/baremaps-server/src/test/java/org/apache/baremaps/server/BaseUriRequestFilterIntegrationTest.java b/baremaps-server/src/test/java/org/apache/baremaps/server/BaseUriRequestFilterIntegrationTest.java deleted file mode 100644 index 9071d3c6..00000000 --- a/baremaps-server/src/test/java/org/apache/baremaps/server/BaseUriRequestFilterIntegrationTest.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to you under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.baremaps.server; - -import static org.junit.Assert.assertEquals; - -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.UriInfo; -import org.glassfish.jersey.server.ResourceConfig; -import org.glassfish.jersey.test.JerseyTest; -import org.glassfish.jersey.test.TestProperties; -import org.junit.Test; - -public class BaseUriRequestFilterIntegrationTest extends JerseyTest { - - @Path("") - public static class BaseUriService { - @GET - public String getBaseUri(@Context UriInfo uriInfo) { - return uriInfo.getBaseUri().toString(); - } - } - - @Override - protected ResourceConfig configure() { - enable(TestProperties.LOG_TRAFFIC); - enable(TestProperties.DUMP_ENTITY); - return new ResourceConfig().registerClasses(BaseUriRequestFilter.class, BaseUriService.class); - } - - @Test - public void testBaseUri() { - String baseUriStr = target().path("").request().header("X-Forwarded-Host", "test.com") - .header("X-Forwarded-Proto", "https").header("X-Forwarded-Port", "443").get(String.class); - assertEquals("https://test.com:443/", baseUriStr); - } -} diff --git a/baremaps-server/src/test/java/org/apache/baremaps/server/ClassPathResourceIntegrationTest.java b/baremaps-server/src/test/java/org/apache/baremaps/server/ClassPathResourceIntegrationTest.java deleted file mode 100644 index 300bc0dc..00000000 --- a/baremaps-server/src/test/java/org/apache/baremaps/server/ClassPathResourceIntegrationTest.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to you under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.baremaps.server; - -import static org.junit.Assert.assertTrue; - -import org.glassfish.jersey.internal.inject.AbstractBinder; -import org.glassfish.jersey.server.ResourceConfig; -import org.glassfish.jersey.test.JerseyTest; -import org.glassfish.jersey.test.TestProperties; -import org.junit.Test; - -public class ClassPathResourceIntegrationTest extends JerseyTest { - - @Override - protected ResourceConfig configure() { - enable(TestProperties.LOG_TRAFFIC); - enable(TestProperties.DUMP_ENTITY); - return new ResourceConfig() - .register(ClassPathResource.class) - .register(new AbstractBinder() { - @Override - protected void configure() { - bind("assets").to(String.class).named("directory"); - bind("viewer.html").to(String.class).named("index"); - } - }); - } - - @Test - public void testAssetsDirectory() { - assertTrue(target().path("").request().get(String.class).contains("<title>Baremaps</title>")); - assertTrue(target().path("viewer.html").request().get(String.class) - .contains("<title>Baremaps</title>")); - assertTrue(target().path("server.html").request().get(String.class) - .contains("<title>Baremaps</title>")); - } -} diff --git a/pom.xml b/pom.xml index 2aa0e735..19fca361 100644 --- a/pom.xml +++ b/pom.xml @@ -79,7 +79,6 @@ limitations under the License. <sonar.moduleKey>${project.groupId}:${project.artifactId}</sonar.moduleKey> <sonar.organization>apache</sonar.organization> <sonar.projectKey>apache_baremaps</sonar.projectKey> - <version.lib.annotation-api>1.3.2</version.lib.annotation-api> <version.lib.armeria>1.26.4</version.lib.armeria> <version.lib.awaitability>4.2.0</version.lib.awaitability> <version.lib.awssdk>2.21.5</version.lib.awssdk> @@ -92,28 +91,24 @@ limitations under the License. <version.lib.graalvm>23.0.2</version.lib.graalvm> <version.lib.guava>32.1.3-jre</version.lib.guava> <version.lib.hikari>5.0.1</version.lib.hikari> - <version.lib.hk2>2.6.1</version.lib.hk2> <version.lib.ipresource>1.52</version.lib.ipresource> <version.lib.jackson>2.13.0</version.lib.jackson> - <version.lib.jakarta>2.1.6</version.lib.jakarta> - <version.lib.jersey>2.37</version.lib.jersey> <version.lib.jmh>1.35</version.lib.jmh> <version.lib.jts>1.19.0</version.lib.jts> <version.lib.junit>5.10.0</version.lib.junit> <version.lib.junit-vintage>5.10.0</version.lib.junit-vintage> <version.lib.log4j>3.0.0-alpha1</version.lib.log4j> + <version.lib.lucene>9.4.2</version.lib.lucene> + <version.lib.lucene-spatial>9.4.2</version.lib.lucene-spatial> <version.lib.pgbulkinsert>8.1.2</version.lib.pgbulkinsert> <version.lib.picocli>4.7.5</version.lib.picocli> <version.lib.postgresql>42.6.0</version.lib.postgresql> <version.lib.proj4j>1.3.0</version.lib.proj4j> <version.lib.protobuf>3.21.6</version.lib.protobuf> <version.lib.roaringbitmap>1.0.0</version.lib.roaringbitmap> - <version.lib.servicetalk>0.42.38</version.lib.servicetalk> <version.lib.slf4j>2.0.9</version.lib.slf4j> <version.lib.sqlite>3.43.2.1</version.lib.sqlite> <version.lib.testcontainers>1.19.1</version.lib.testcontainers> - <version.lucene>9.4.2</version.lucene> - <version.lucene-spatial>9.4.2</version.lucene-spatial> <version.plugin.jacoco-maven-plugin>0.8.11</version.plugin.jacoco-maven-plugin> <version.plugin.jib-maven-plugin>3.0.0</version.plugin.jib-maven-plugin> <version.plugin.maven-compiler-plugin>3.10.1</version.plugin.maven-compiler-plugin> @@ -206,56 +201,11 @@ limitations under the License. <artifactId>picocli</artifactId> <version>${version.lib.picocli}</version> </dependency> - <dependency> - <groupId>io.servicetalk</groupId> - <artifactId>servicetalk-data-jackson</artifactId> - <version>${version.lib.servicetalk}</version> - </dependency> - <dependency> - <groupId>io.servicetalk</groupId> - <artifactId>servicetalk-data-jackson-jersey</artifactId> - <version>${version.lib.servicetalk}</version> - </dependency> - <dependency> - <groupId>io.servicetalk</groupId> - <artifactId>servicetalk-http-api</artifactId> - <version>${version.lib.servicetalk}</version> - </dependency> - <dependency> - <groupId>io.servicetalk</groupId> - <artifactId>servicetalk-http-netty</artifactId> - <version>${version.lib.servicetalk}</version> - </dependency> - <dependency> - <groupId>io.servicetalk</groupId> - <artifactId>servicetalk-http-router-jersey</artifactId> - <version>${version.lib.servicetalk}</version> - </dependency> - <dependency> - <groupId>io.servicetalk</groupId> - <artifactId>servicetalk-http-router-predicate</artifactId> - <version>${version.lib.servicetalk}</version> - </dependency> - <dependency> - <groupId>io.servicetalk</groupId> - <artifactId>servicetalk-transport-api</artifactId> - <version>${version.lib.servicetalk}</version> - </dependency> - <dependency> - <groupId>io.servicetalk</groupId> - <artifactId>servicetalk-transport-netty</artifactId> - <version>${version.lib.servicetalk}</version> - </dependency> <dependency> <groupId>it.unimi.dsi</groupId> <artifactId>fastutil</artifactId> <version>${version.lib.fastutil}</version> </dependency> - <dependency> - <groupId>jakarta.ws.rs</groupId> - <artifactId>jakarta.ws.rs-api</artifactId> - <version>${version.lib.jakarta}</version> - </dependency> <dependency> <groupId>mil.nga.geopackage</groupId> <artifactId>geopackage</artifactId> @@ -321,32 +271,32 @@ limitations under the License. <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-analyzers-common</artifactId> - <version>${version.lucene}</version> + <version>${version.lib.lucene}</version> </dependency> <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-core</artifactId> - <version>${version.lucene}</version> + <version>${version.lib.lucene}</version> </dependency> <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-expressions</artifactId> - <version>${version.lucene}</version> + <version>${version.lib.lucene}</version> </dependency> <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-queryparser</artifactId> - <version>${version.lucene}</version> + <version>${version.lib.lucene}</version> </dependency> <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-replicator</artifactId> - <version>${version.lucene}</version> + <version>${version.lib.lucene}</version> </dependency> <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-spatial-extras</artifactId> - <version>${version.lucene}</version> + <version>${version.lib.lucene}</version> </dependency> <dependency> <groupId>org.awaitility</groupId> @@ -354,29 +304,6 @@ limitations under the License. <version>${version.lib.awaitability}</version> <scope>test</scope> </dependency> - <dependency> - <groupId>org.glassfish.hk2</groupId> - <artifactId>hk2-api</artifactId> - <version>${version.lib.hk2}</version> - </dependency> - <dependency> - <groupId>org.glassfish.hk2</groupId> - <artifactId>hk2-locator</artifactId> - <version>${version.lib.hk2}</version> - </dependency> - <dependency> - <groupId>org.glassfish.jersey</groupId> - <artifactId>jersey-bom</artifactId> - <version>${version.lib.jersey}</version> - <type>pom</type> - <scope>import</scope> - </dependency> - <dependency> - <groupId>org.glassfish.jersey.test-framework.providers</groupId> - <artifactId>jersey-test-framework-provider-inmemory</artifactId> - <version>${version.lib.jersey}</version> - <scope>test</scope> - </dependency> <dependency> <groupId>org.graalvm.js</groupId> <artifactId>js</artifactId>
