From c0b96d2e8aea0188f538b522cd40c55184c5927f Mon Sep 17 00:00:00 2001
From: Brandon Clayton <bclayton@usgs.gov>
Date: Thu, 25 Mar 2021 09:55:35 -0600
Subject: [PATCH] update to nshmp-ws-utils

---
 build.gradle                                  |  2 +-
 gradle.properties                             | 11 +--
 gradle/dependencies.gradle                    | 17 ++--
 .../nshmp/aws/HazardResultSliceLambda.java    |  2 +-
 .../aws/HazardResultsMetadataLambda.java      |  2 +-
 .../nshmp/aws/HazardResultsSlicerLambda.java  |  2 +-
 .../nshmp/www/DeaggEpsilonController.java     |  9 +-
 .../nshmp/www/HazardController.java           |  8 +-
 .../earthquake/nshmp/www/RateController.java  | 21 ++---
 .../nshmp/www/SourceController.java           |  4 +-
 .../earthquake/nshmp/www/meta/MetaUtil.java   | 92 -------------------
 .../earthquake/nshmp/www/meta/Metadata.java   |  1 -
 .../www/services/DeaggEpsilonService.java     | 29 +++---
 .../nshmp/www/services/HazardService.java     | 37 ++++----
 .../nshmp/www/services/RateService.java       | 41 +++++----
 .../nshmp/www/services/ServicesUtil.java      | 11 +--
 .../nshmp/www/services/ServletUtil.java       |  9 +-
 .../nshmp/www/services/SourceServices.java    | 19 ++--
 18 files changed, 107 insertions(+), 210 deletions(-)

diff --git a/build.gradle b/build.gradle
index 50cc3dac6..99520d152 100644
--- a/build.gradle
+++ b/build.gradle
@@ -35,9 +35,9 @@ plugins {
   id "com.github.spotbugs" version "${spotbugsVersion}"
   id "com.star-zero.gradle.githook" version "${githooksVersion}"
   id "eclipse-wtp"
+  id "io.micronaut.application" version "${mnPluginVersion}"
   id "jacoco"
   id "maven-publish"
-  id "net.ltgt.apt-eclipse" version "${aptEclipseVersion}"
 }
 
 configurations {
diff --git a/gradle.properties b/gradle.properties
index c7ec9ca89..9f478ac91 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,4 +1,3 @@
-aptEclipseVersion = 0.21
 awsEc2Version = 1.11.619
 awsLambdaCoreVersion = 1.1.0
 awsLambdaVersion = 1.11.461
@@ -6,12 +5,12 @@ awsS3Version = 1.11.579
 githooksVersion = 1.2.0
 jacksonVersion = 2.9.0
 junitVersion = 5.5.2
-logbackVersion = 1.2.3
-mnOpenAPIVersion = 1.4.0
-mnVersion = 1.3.2
+micronautVersion = 2.4.1
+mnPluginVersion = 1.4.2
 nodeVersion = 3.0.1
-nshmpLibVersion = 0.3.0
+nshmpLibVersion = 0.3.1
+nshmpWsUtilsVersion = 0.1.1
 shadowVersion = 5.2.0
 spotbugsVersion = 4.2.4
 spotlessVersion = 4.1.0
-swaggerVersion = 2.1.1
+swaggerVersion = 2.1.7
diff --git a/gradle/dependencies.gradle b/gradle/dependencies.gradle
index d2cce5242..5eeb91e80 100644
--- a/gradle/dependencies.gradle
+++ b/gradle/dependencies.gradle
@@ -1,6 +1,7 @@
 
 dependencies {
   implementation "ghsc:nshmp-lib:${nshmpLibVersion}"
+  implementation "ghsc:nshmp-ws-utils:${nshmpWsUtilsVersion}"
   nshmp "ghsc:nshmp-lib:${nshmpLibVersion}@zip"
 
   // AWS
@@ -10,26 +11,26 @@ dependencies {
   implementation "com.amazonaws:aws-java-sdk-ec2:${awsEc2Version}"
 
   // Micronaut
-  annotationProcessor platform("io.micronaut:micronaut-bom:${mnVersion}")
+  annotationProcessor platform("io.micronaut:micronaut-bom")
   annotationProcessor "io.micronaut:micronaut-inject-java"
   annotationProcessor "io.micronaut:micronaut-validation"
-  implementation platform("io.micronaut:micronaut-bom:${mnVersion}")
+  implementation platform("io.micronaut:micronaut-bom")
   implementation "io.micronaut:micronaut-http-client"
   implementation "io.micronaut:micronaut-inject"
   implementation "io.micronaut:micronaut-validation"
   implementation "io.micronaut:micronaut-runtime"
   implementation "io.micronaut:micronaut-http-server-netty"
   implementation "com.fasterxml.jackson.module:jackson-module-parameter-names:${jacksonVersion}"
-  runtimeOnly "ch.qos.logback:logback-classic:${logbackVersion}"
+  runtimeOnly "ch.qos.logback:logback-classic"
 
   // Swagger
-  annotationProcessor("io.micronaut.configuration:micronaut-openapi:${mnOpenAPIVersion}")
-  implementation("io.swagger.core.v3:swagger-annotations:${swaggerVersion}")
-  implementation("io.swagger.core.v3:swagger-models:${swaggerVersion}")
+  annotationProcessor("io.micronaut.configuration:micronaut-openapi")
+  implementation("io.swagger.core.v3:swagger-annotations")
+  implementation("io.swagger.core.v3:swagger-models")
 
   // junit
-  testAnnotationProcessor "io.micronaut:micronaut-inject-java:${mnVersion}"
-  testImplementation platform("io.micronaut:micronaut-bom:${mnVersion}")
+  testAnnotationProcessor "io.micronaut:micronaut-inject-java"
+  testImplementation platform("io.micronaut:micronaut-bom")
   testImplementation "org.junit.jupiter:junit-jupiter:${junitVersion}"
   testImplementation "org.junit.jupiter:junit-jupiter-api"
   testImplementation "io.micronaut.test:micronaut-test-junit5"
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultSliceLambda.java b/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultSliceLambda.java
index 74f7fc811..1311536a1 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultSliceLambda.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultSliceLambda.java
@@ -36,8 +36,8 @@ import gov.usgs.earthquake.nshmp.calc.Site;
 import gov.usgs.earthquake.nshmp.data.Interpolator;
 import gov.usgs.earthquake.nshmp.internal.Parsing;
 import gov.usgs.earthquake.nshmp.internal.Parsing.Delimiter;
-import gov.usgs.earthquake.nshmp.internal.www.meta.Status;
 import gov.usgs.earthquake.nshmp.www.meta.Metadata;
+import gov.usgs.earthquake.nshmp.www.meta.Status;
 import gov.usgs.earthquake.nshmp.www.services.ServletUtil;
 
 /**
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultsMetadataLambda.java b/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultsMetadataLambda.java
index 1d7db3b60..88c16e1e6 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultsMetadataLambda.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultsMetadataLambda.java
@@ -34,9 +34,9 @@ import gov.usgs.earthquake.nshmp.gmm.Gmm;
 import gov.usgs.earthquake.nshmp.gmm.Imt;
 import gov.usgs.earthquake.nshmp.internal.Parsing;
 import gov.usgs.earthquake.nshmp.internal.Parsing.Delimiter;
-import gov.usgs.earthquake.nshmp.internal.www.meta.Status;
 import gov.usgs.earthquake.nshmp.model.SourceType;
 import gov.usgs.earthquake.nshmp.www.meta.Metadata;
+import gov.usgs.earthquake.nshmp.www.meta.Status;
 import gov.usgs.earthquake.nshmp.www.services.ServletUtil;
 
 /**
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultsSlicerLambda.java b/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultsSlicerLambda.java
index ac5925f3e..a535f4cd8 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultsSlicerLambda.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultsSlicerLambda.java
@@ -29,8 +29,8 @@ import com.google.common.base.Throwables;
 import gov.usgs.earthquake.nshmp.aws.Util.LambdaHelper;
 import gov.usgs.earthquake.nshmp.internal.Parsing;
 import gov.usgs.earthquake.nshmp.internal.Parsing.Delimiter;
-import gov.usgs.earthquake.nshmp.internal.www.meta.Status;
 import gov.usgs.earthquake.nshmp.www.meta.Metadata;
+import gov.usgs.earthquake.nshmp.www.meta.Status;
 import gov.usgs.earthquake.nshmp.www.services.ServletUtil;
 
 /**
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/DeaggEpsilonController.java b/src/main/java/gov/usgs/earthquake/nshmp/www/DeaggEpsilonController.java
index 592309fb3..f498983b2 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/DeaggEpsilonController.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/DeaggEpsilonController.java
@@ -2,15 +2,14 @@ package gov.usgs.earthquake.nshmp.www;
 
 import java.util.EnumMap;
 
-import javax.annotation.Nullable;
 import javax.inject.Inject;
 
 import gov.usgs.earthquake.nshmp.gmm.Imt;
-import gov.usgs.earthquake.nshmp.internal.www.NshmpMicronautServlet;
 import gov.usgs.earthquake.nshmp.www.services.DeaggEpsilonService;
 import gov.usgs.earthquake.nshmp.www.services.DeaggEpsilonService.Query;
 import gov.usgs.earthquake.nshmp.www.services.HazardService;
 
+import io.micronaut.core.annotation.Nullable;
 import io.micronaut.http.HttpRequest;
 import io.micronaut.http.HttpResponse;
 import io.micronaut.http.MediaType;
@@ -32,8 +31,7 @@ public class DeaggEpsilonController {
 
   @Get(uri = "/usage", produces = MediaType.APPLICATION_JSON)
   public HttpResponse<String> doGetUsage(HttpRequest<?> request) {
-    var urlHelper = servlet.urlHelper(request);
-    return HazardService.handleDoGetMetadata(urlHelper);
+    return HazardService.handleDoGetMetadata(request);
   }
 
   /**
@@ -68,9 +66,8 @@ public class DeaggEpsilonController {
       @Schema(
           defaultValue = "{\"SA0P01\": 0.01}",
           required = true) @QueryValue @Nullable EnumMap<Imt, Double> imtImls) {
-    var urlHelper = servlet.urlHelper(request);
     var query = new Query(request, longitude, latitude, vs30, basin);
-    return DeaggEpsilonService.handleDoGetDeaggEpsilon(query, urlHelper);
+    return DeaggEpsilonService.handleDoGetDeaggEpsilon(request, query);
   }
 
   /**
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/HazardController.java b/src/main/java/gov/usgs/earthquake/nshmp/www/HazardController.java
index d6d381b18..e85229e1c 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/HazardController.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/HazardController.java
@@ -1,12 +1,11 @@
 package gov.usgs.earthquake.nshmp.www;
 
-import javax.annotation.Nullable;
 import javax.inject.Inject;
 
-import gov.usgs.earthquake.nshmp.internal.www.NshmpMicronautServlet;
 import gov.usgs.earthquake.nshmp.www.services.HazardService;
 import gov.usgs.earthquake.nshmp.www.services.HazardService.QueryParameters;
 
+import io.micronaut.core.annotation.Nullable;
 import io.micronaut.http.HttpRequest;
 import io.micronaut.http.HttpResponse;
 import io.micronaut.http.annotation.Controller;
@@ -42,8 +41,7 @@ public class HazardController {
       responseCode = "200")
   @Get
   public HttpResponse<String> doGetMetadata(HttpRequest<?> request) {
-    var urlHelper = servlet.urlHelper(request);
-    return HazardService.handleDoGetMetadata(urlHelper);
+    return HazardService.handleDoGetMetadata(request);
   }
 
   /**
@@ -75,6 +73,6 @@ public class HazardController {
      */
 
     var query = new QueryParameters(longitude, latitude, vs30, truncate, maxdir);
-    return HazardService.handleDoGetHazard(query, servlet.urlHelper(request));
+    return HazardService.handleDoGetHazard(request, query);
   }
 }
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/RateController.java b/src/main/java/gov/usgs/earthquake/nshmp/www/RateController.java
index caaa0379f..7dda0228d 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/RateController.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/RateController.java
@@ -2,14 +2,13 @@ package gov.usgs.earthquake.nshmp.www;
 
 import java.util.Optional;
 
-import javax.annotation.Nullable;
 import javax.inject.Inject;
 
-import gov.usgs.earthquake.nshmp.internal.www.NshmpMicronautServlet;
 import gov.usgs.earthquake.nshmp.www.services.RateService;
 import gov.usgs.earthquake.nshmp.www.services.RateService.Query;
 import gov.usgs.earthquake.nshmp.www.services.RateService.Service;
 
+import io.micronaut.core.annotation.Nullable;
 import io.micronaut.http.HttpRequest;
 import io.micronaut.http.HttpResponse;
 import io.micronaut.http.MediaType;
@@ -49,8 +48,7 @@ public class RateController {
       responseCode = "200")
   @Get(uri = "/rate/usage", produces = MediaType.APPLICATION_JSON)
   public HttpResponse<String> doGetUsageRate(HttpRequest<?> request) {
-    var urlHelper = servlet.urlHelper(request);
-    return RateService.handleDoGetUsage(Service.RATE, urlHelper);
+    return RateService.handleDoGetUsage(request, Service.RATE);
   }
 
   /**
@@ -87,9 +85,8 @@ public class RateController {
           minimum = "0.01",
           maximum = "1000") @QueryValue @Nullable Double distance) {
     var service = Service.RATE;
-    var urlHelper = servlet.urlHelper(request);
     var query = new Query(service, longitude, latitude, distance, Optional.empty());
-    return RateService.handleDoGetCalc(query, urlHelper);
+    return RateService.handleDoGetCalc(request, query);
   }
 
   /**
@@ -126,9 +123,8 @@ public class RateController {
           minimum = "0.01",
           maximum = "1000") @PathVariable @Nullable Double distance) {
     var service = Service.RATE;
-    var urlHelper = servlet.urlHelper(request);
     var query = new Query(service, longitude, latitude, distance, Optional.empty());
-    return RateService.handleDoGetCalc(query, urlHelper);
+    return RateService.handleDoGetCalc(request, query);
   }
 
   /**
@@ -147,8 +143,7 @@ public class RateController {
       responseCode = "200")
   @Get(uri = "/probability/usage", produces = MediaType.APPLICATION_JSON)
   public HttpResponse<String> doGetUsageProbability(HttpRequest<?> request) {
-    var urlHelper = servlet.urlHelper(request);
-    return RateService.handleDoGetUsage(Service.PROBABILITY, urlHelper);
+    return RateService.handleDoGetUsage(request, Service.PROBABILITY);
   }
 
   /**
@@ -190,9 +185,8 @@ public class RateController {
           minimum = "1",
           maximum = "10000") @QueryValue @Nullable Double timespan) {
     var service = Service.PROBABILITY;
-    var urlHelper = servlet.urlHelper(request);
     var query = new Query(service, longitude, latitude, distance, Optional.ofNullable(timespan));
-    return RateService.handleDoGetCalc(query, urlHelper);
+    return RateService.handleDoGetCalc(request, query);
   }
 
   /**
@@ -234,9 +228,8 @@ public class RateController {
           minimum = "1",
           maximum = "10000") @PathVariable @Nullable Double timespan) {
     var service = Service.PROBABILITY;
-    var urlHelper = servlet.urlHelper(request);
     var query = new Query(service, longitude, latitude, distance, Optional.ofNullable(timespan));
-    return RateService.handleDoGetCalc(query, urlHelper);
+    return RateService.handleDoGetCalc(request, query);
   }
 
 }
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/SourceController.java b/src/main/java/gov/usgs/earthquake/nshmp/www/SourceController.java
index 994639b76..d60708d38 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/SourceController.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/SourceController.java
@@ -2,7 +2,6 @@ package gov.usgs.earthquake.nshmp.www;
 
 import javax.inject.Inject;
 
-import gov.usgs.earthquake.nshmp.internal.www.NshmpMicronautServlet;
 import gov.usgs.earthquake.nshmp.www.services.SourceServices;
 
 import io.micronaut.http.HttpRequest;
@@ -48,8 +47,7 @@ public class SourceController {
       responseCode = "200")
   @Get(produces = MediaType.APPLICATION_JSON)
   public HttpResponse<String> doGetUsage(HttpRequest<?> request) {
-    var urlHelper = servlet.urlHelper(request);
-    return SourceServices.handleDoGetUsage(urlHelper);
+    return SourceServices.handleDoGetUsage(request);
   }
 
 }
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/meta/MetaUtil.java b/src/main/java/gov/usgs/earthquake/nshmp/www/meta/MetaUtil.java
index 271a99e43..b2153504d 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/meta/MetaUtil.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/meta/MetaUtil.java
@@ -3,23 +3,16 @@ package gov.usgs.earthquake.nshmp.www.meta;
 import java.lang.reflect.Type;
 import java.util.Collection;
 import java.util.List;
-import java.util.Optional;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 
-import com.google.common.collect.Range;
-import com.google.gson.JsonArray;
 import com.google.gson.JsonElement;
 import com.google.gson.JsonObject;
-import com.google.gson.JsonPrimitive;
 import com.google.gson.JsonSerializationContext;
 import com.google.gson.JsonSerializer;
 
 import gov.usgs.earthquake.nshmp.Maths;
 import gov.usgs.earthquake.nshmp.calc.Site;
-import gov.usgs.earthquake.nshmp.gmm.GmmInput;
-import gov.usgs.earthquake.nshmp.gmm.GmmInput.Field;
-import gov.usgs.earthquake.nshmp.internal.www.meta.ParamType;
 
 public final class MetaUtil {
 
@@ -34,26 +27,6 @@ public final class MetaUtil {
     return values.stream().map(function).collect(Collectors.toList());
   }
 
-  public static final class EnumSerializer<E extends Enum<E>> implements JsonSerializer<E> {
-
-    @Override
-    public JsonElement serialize(E src, Type type, JsonSerializationContext context) {
-
-      JsonObject jObj = new JsonObject();
-      jObj.addProperty("id", src.ordinal());
-      jObj.addProperty("value", src.name());
-      jObj.addProperty("display", src.toString());
-      jObj.addProperty("displayorder", src.ordinal());
-
-      // if (src instanceof Constrained) {
-      // Constrained cSrc = (Constrained) src;
-      // jObj.add("supports", context.serialize(cSrc.constraints()));
-      // }
-
-      return jObj;
-    }
-  }
-
   public static final class SiteSerializer implements JsonSerializer<Site> {
 
     @Override
@@ -75,69 +48,4 @@ public final class MetaUtil {
 
   }
 
-  /* Constrain all doubles to 8 decimal places */
-  public static final class DoubleSerializer implements JsonSerializer<Double> {
-    @Override
-    public JsonElement serialize(Double d, Type type, JsonSerializationContext context) {
-      if (Double.isNaN(d)) {
-        return null;
-      }
-
-      double dOut = Double.valueOf(String.format("%.8g", d));
-      return new JsonPrimitive(dOut);
-    }
-  }
-
-  /* Serialize param type enum as lowercase */
-  public static class ParamTypeSerializer implements JsonSerializer<ParamType> {
-    @Override
-    public JsonElement serialize(ParamType paramType, Type type, JsonSerializationContext context) {
-      return new JsonPrimitive(paramType.name().toLowerCase());
-    }
-  }
-
-  /* Convert NaN to null */
-  public static final class NaNSerializer implements JsonSerializer<Double> {
-    @Override
-    public JsonElement serialize(Double d, Type type, JsonSerializationContext context) {
-      return Double.isNaN(d) ? null : new JsonPrimitive(d);
-    }
-  }
-
-  public static final class ConstraintsSerializer implements JsonSerializer<GmmInput.Constraints> {
-    @Override
-    public JsonElement serialize(
-        GmmInput.Constraints constraints,
-        Type type,
-        JsonSerializationContext context) {
-      JsonArray json = new JsonArray();
-
-      for (Field field : Field.values()) {
-        Optional<?> opt = constraints.get(field);
-        if (opt.isPresent()) {
-          Range<?> value = (Range<?>) opt.get();
-          Constraint constraint = new Constraint(
-              field.id,
-              value.lowerEndpoint(),
-              value.upperEndpoint());
-          json.add(context.serialize(constraint));
-        }
-      }
-
-      return json;
-    }
-  }
-
-  private static class Constraint {
-    final String id;
-    final Object min;
-    final Object max;
-
-    Constraint(String id, Object min, Object max) {
-      this.id = id;
-      this.min = min;
-      this.max = max;
-    }
-  }
-
 }
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/meta/Metadata.java b/src/main/java/gov/usgs/earthquake/nshmp/www/meta/Metadata.java
index a358619db..fd844d51d 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/meta/Metadata.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/meta/Metadata.java
@@ -4,7 +4,6 @@ import com.google.common.base.Stopwatch;
 import com.google.common.base.Throwables;
 
 import gov.usgs.earthquake.nshmp.geo.Coordinates;
-import gov.usgs.earthquake.nshmp.internal.www.meta.Status;
 import gov.usgs.earthquake.nshmp.www.services.ServletUtil;
 
 /**
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/services/DeaggEpsilonService.java b/src/main/java/gov/usgs/earthquake/nshmp/www/services/DeaggEpsilonService.java
index a2b851e62..7e584a1cd 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/services/DeaggEpsilonService.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/services/DeaggEpsilonService.java
@@ -14,13 +14,12 @@ import gov.usgs.earthquake.nshmp.calc.Deaggregation;
 import gov.usgs.earthquake.nshmp.calc.Site;
 import gov.usgs.earthquake.nshmp.geo.Location;
 import gov.usgs.earthquake.nshmp.gmm.Imt;
-import gov.usgs.earthquake.nshmp.internal.www.NshmpMicronautServlet.UrlHelper;
-import gov.usgs.earthquake.nshmp.internal.www.Response;
-import gov.usgs.earthquake.nshmp.internal.www.WsUtils;
-import gov.usgs.earthquake.nshmp.internal.www.meta.Status;
 import gov.usgs.earthquake.nshmp.model.HazardModel;
 import gov.usgs.earthquake.nshmp.www.DeaggEpsilonController;
+import gov.usgs.earthquake.nshmp.www.Response;
+import gov.usgs.earthquake.nshmp.www.WsUtils;
 import gov.usgs.earthquake.nshmp.www.meta.Metadata;
+import gov.usgs.earthquake.nshmp.www.meta.Status;
 import gov.usgs.earthquake.nshmp.www.services.ServicesUtil.Key;
 import gov.usgs.earthquake.nshmp.www.services.SourceServices.SourceModel;
 
@@ -49,21 +48,21 @@ public final class DeaggEpsilonService {
    * @param query The query
    * @param urlHelper The URL helper
    */
-  public static HttpResponse<String> handleDoGetDeaggEpsilon(Query query, UrlHelper urlHelper) {
+  public static HttpResponse<String> handleDoGetDeaggEpsilon(HttpRequest<?> request, Query query) {
     try {
       var timer = ServletUtil.timer();
 
       if (query.isNull()) {
-        return HazardService.handleDoGetMetadata(urlHelper);
+        return HazardService.handleDoGetMetadata(request);
       }
 
       query.checkValues();
       var data = new RequestData(query, query.vs30);
-      var response = process(data, urlHelper);
+      var response = process(request, data);
       var svcResponse = ServletUtil.GSON.toJson(response);
       return HttpResponse.ok(svcResponse);
     } catch (Exception e) {
-      return ServicesUtil.handleError(e, NAME, urlHelper);
+      return ServicesUtil.handleError(e, NAME, request.getUri().getPath());
     }
   }
 
@@ -85,8 +84,8 @@ public final class DeaggEpsilonService {
   }
 
   private static Response<RequestData, ResponseData> process(
-      RequestData data,
-      UrlHelper urlHelper)
+      HttpRequest<?> request,
+      RequestData data)
       throws InterruptedException, ExecutionException {
     var configFunction = new ConfigFunction();
     var siteFunction = new SiteFunction(data);
@@ -97,7 +96,7 @@ public final class DeaggEpsilonService {
         .deagg(deagg)
         .requestData(data)
         .timer(timer)
-        .urlHelper(urlHelper)
+        .url(request)
         .build();
   }
 
@@ -219,7 +218,7 @@ public final class DeaggEpsilonService {
   }
 
   static final class ResultBuilder {
-    UrlHelper urlHelper;
+    String url;
     Stopwatch timer;
     RequestData request;
     Deaggregation deagg;
@@ -229,8 +228,8 @@ public final class DeaggEpsilonService {
       return this;
     }
 
-    ResultBuilder urlHelper(UrlHelper urlHelper) {
-      this.urlHelper = urlHelper;
+    ResultBuilder url(HttpRequest<?> request) {
+      url = request.getUri().getPath();
       return this;
     }
 
@@ -258,7 +257,7 @@ public final class DeaggEpsilonService {
       Object server = Metadata.serverData(ServletUtil.THREAD_COUNT, timer);
       var response = new ResponseData(server, responseList);
 
-      return new Response<>(Status.SUCCESS, NAME, request, response, urlHelper);
+      return new Response<>(Status.SUCCESS, NAME, request, response, url);
     }
   }
 
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/services/HazardService.java b/src/main/java/gov/usgs/earthquake/nshmp/www/services/HazardService.java
index fd8b3caec..60bb6ff58 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/services/HazardService.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/services/HazardService.java
@@ -21,20 +21,20 @@ import gov.usgs.earthquake.nshmp.data.XySequence;
 import gov.usgs.earthquake.nshmp.geo.Coordinates;
 import gov.usgs.earthquake.nshmp.geo.Location;
 import gov.usgs.earthquake.nshmp.gmm.Imt;
-import gov.usgs.earthquake.nshmp.internal.www.NshmpMicronautServlet.UrlHelper;
-import gov.usgs.earthquake.nshmp.internal.www.Response;
-import gov.usgs.earthquake.nshmp.internal.www.WsUtils;
-import gov.usgs.earthquake.nshmp.internal.www.meta.Status;
 import gov.usgs.earthquake.nshmp.model.HazardModel;
 import gov.usgs.earthquake.nshmp.model.SourceType;
 import gov.usgs.earthquake.nshmp.www.HazardController;
+import gov.usgs.earthquake.nshmp.www.Response;
+import gov.usgs.earthquake.nshmp.www.WsUtils;
 import gov.usgs.earthquake.nshmp.www.meta.DoubleParameter;
 import gov.usgs.earthquake.nshmp.www.meta.Metadata;
 import gov.usgs.earthquake.nshmp.www.meta.Parameter;
+import gov.usgs.earthquake.nshmp.www.meta.Status;
 import gov.usgs.earthquake.nshmp.www.services.ServicesUtil.ServiceQueryData;
 import gov.usgs.earthquake.nshmp.www.services.ServicesUtil.ServiceRequestData;
 import gov.usgs.earthquake.nshmp.www.services.SourceServices.SourceModel;
 
+import io.micronaut.http.HttpRequest;
 import io.micronaut.http.HttpResponse;
 
 /**
@@ -48,21 +48,22 @@ public final class HazardService {
   private static final String NAME = "Hazard Service";
 
   /** HazardController.doGetUsage() handler. */
-  public static HttpResponse<String> handleDoGetMetadata(UrlHelper urlHelper) {
+  public static HttpResponse<String> handleDoGetMetadata(HttpRequest<?> request) {
+    var url = request.getUri().getPath();
     try {
       var usage = new RequestMetadata(ServletUtil.model());// SourceServices.ResponseData();
-      var response = new Response<>(Status.USAGE, NAME, urlHelper.url, usage, urlHelper);
+      var response = new Response<>(Status.USAGE, NAME, url, usage, url);
       var svcResponse = ServletUtil.GSON.toJson(response);
       return HttpResponse.ok(svcResponse);
     } catch (Exception e) {
-      return ServicesUtil.handleError(e, NAME, urlHelper);
+      return ServicesUtil.handleError(e, NAME, url);
     }
   }
 
   /** HazardController.doGetHazard() handler. */
   public static HttpResponse<String> handleDoGetHazard(
-      QueryParameters query,
-      UrlHelper urlHelper) {
+      HttpRequest<?> request,
+      QueryParameters query) {
 
     try {
       // TODO still need to validate
@@ -71,17 +72,17 @@ public final class HazardService {
       // }
       // query.checkParameters();
       var data = new RequestData(query);
-      var response = process(data, urlHelper);
+      var response = process(request, data);
       var svcResponse = ServletUtil.GSON.toJson(response);
       return HttpResponse.ok(svcResponse);
     } catch (Exception e) {
-      return ServicesUtil.handleError(e, NAME, urlHelper);
+      return ServicesUtil.handleError(e, NAME, request.getUri().getPath());
     }
   }
 
   static Response<RequestData, ResponseData> process(
-      RequestData data,
-      UrlHelper urlHelper)
+      HttpRequest<?> request,
+      RequestData data)
       throws InterruptedException, ExecutionException {
 
     var configFunction = new ConfigFunction();
@@ -93,7 +94,7 @@ public final class HazardService {
         .hazard(hazard)
         .requestData(data)
         .timer(stopwatch)
-        .urlHelper(urlHelper)
+        .url(request)
         .build();
   }
 
@@ -267,7 +268,7 @@ public final class HazardService {
 
   private static final class ResultBuilder {
 
-    UrlHelper urlHelper;
+    String url;
     Stopwatch timer;
     RequestData request;
 
@@ -305,8 +306,8 @@ public final class HazardService {
       return this;
     }
 
-    ResultBuilder urlHelper(UrlHelper urlHelper) {
-      this.urlHelper = urlHelper;
+    ResultBuilder url(HttpRequest<?> request) {
+      url = request.getUri().getPath();
       return this;
     }
 
@@ -345,7 +346,7 @@ public final class HazardService {
       Object server = Metadata.serverData(ServletUtil.THREAD_COUNT, timer);
       var response = new ResponseData(new ResponseMetadata(server), List.copyOf(hazards));
 
-      return new Response<>(Status.SUCCESS, NAME, request, response, urlHelper);
+      return new Response<>(Status.SUCCESS, NAME, request, response, url);
     }
   }
 
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/services/RateService.java b/src/main/java/gov/usgs/earthquake/nshmp/www/services/RateService.java
index 071f31da5..4c08ef087 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/services/RateService.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/services/RateService.java
@@ -14,19 +14,19 @@ import gov.usgs.earthquake.nshmp.calc.CalcConfig;
 import gov.usgs.earthquake.nshmp.calc.EqRate;
 import gov.usgs.earthquake.nshmp.calc.Site;
 import gov.usgs.earthquake.nshmp.geo.Location;
-import gov.usgs.earthquake.nshmp.internal.www.NshmpMicronautServlet.UrlHelper;
-import gov.usgs.earthquake.nshmp.internal.www.Response;
-import gov.usgs.earthquake.nshmp.internal.www.WsUtils;
-import gov.usgs.earthquake.nshmp.internal.www.meta.Status;
 import gov.usgs.earthquake.nshmp.model.HazardModel;
 import gov.usgs.earthquake.nshmp.www.RateController;
+import gov.usgs.earthquake.nshmp.www.Response;
+import gov.usgs.earthquake.nshmp.www.WsUtils;
 import gov.usgs.earthquake.nshmp.www.meta.DoubleParameter;
 import gov.usgs.earthquake.nshmp.www.meta.Metadata;
 import gov.usgs.earthquake.nshmp.www.meta.Metadata.DefaultParameters;
+import gov.usgs.earthquake.nshmp.www.meta.Status;
 import gov.usgs.earthquake.nshmp.www.services.ServicesUtil.Key;
 import gov.usgs.earthquake.nshmp.www.services.ServicesUtil.ServiceQueryData;
 import gov.usgs.earthquake.nshmp.www.services.ServicesUtil.ServiceRequestData;
 
+import io.micronaut.http.HttpRequest;
 import io.micronaut.http.HttpResponse;
 
 /**
@@ -55,13 +55,13 @@ public final class RateService {
    * @param service The service
    * @param urlHelper The url helper
    */
-  public static HttpResponse<String> handleDoGetUsage(Service service, UrlHelper urlHelper) {
+  public static HttpResponse<String> handleDoGetUsage(HttpRequest<?> request, Service service) {
     try {
-      var response = metadata(service, urlHelper);
+      var response = metadata(request, service);
       var svcResponse = ServletUtil.GSON.toJson(response);
-      return HttpResponse.ok(String.format(svcResponse, urlHelper.urlPrefix, urlHelper.urlPrefix));
+      return HttpResponse.ok(svcResponse);
     } catch (Exception e) {
-      return ServicesUtil.handleError(e, service.name, urlHelper);
+      return ServicesUtil.handleError(e, service.name, request.getUri().getPath());
     }
   }
 
@@ -75,40 +75,47 @@ public final class RateService {
    * @param urlHelper The url helper
    * @return
    */
-  public static HttpResponse<String> handleDoGetCalc(Query query, UrlHelper urlHelper) {
+  public static HttpResponse<String> handleDoGetCalc(HttpRequest<?> request, Query query) {
     var service = query.service;
 
     try {
       var timer = ServletUtil.timer();
 
       if (query.isNull()) {
-        return handleDoGetUsage(service, urlHelper);
+        return handleDoGetUsage(request, service);
       }
 
       query.checkValues();
       var requestData = new RequestData(query);
-      var response = processRequest(service, requestData, urlHelper);
+      var response = processRequest(request, service, requestData);
       var svcResponse = ServletUtil.GSON.toJson(response);
       return HttpResponse.ok(svcResponse);
     } catch (Exception e) {
-      return ServicesUtil.handleError(e, service.name, urlHelper);
+      return ServicesUtil.handleError(e, service.name, request.getUri().getPath());
     }
   }
 
-  static Response<String, Usage> metadata(Service service, UrlHelper urlHelper) {
+  static Response<String, Usage> metadata(HttpRequest<?> request, Service service) {
     var parameters = service == Service.RATE ? new RateParameters() : new ProbabilityParameters();
     var usage = new Usage(service, parameters);
-    return new Response<>(Status.USAGE, service.name, urlHelper.url, usage, urlHelper);
+    var url = request.getUri().getPath();
+    return new Response<>(Status.USAGE, service.name, url, usage, url);
   }
 
   static Response<RequestData, ResponseData> processRequest(
+      HttpRequest<?> request,
       Service service,
-      RequestData data,
-      UrlHelper urlHelper) throws InterruptedException, ExecutionException {
+      RequestData data) throws InterruptedException, ExecutionException {
     var timer = Stopwatch.createStarted();
     var rates = calc(service, data);
     var responseData = new ResponseData(new ResponseMetadata(service, data), rates, timer);
-    return new Response<>(Status.SUCCESS, service.name, data, responseData, urlHelper);
+    return Response.<RequestData, ResponseData> builder()
+        .success()
+        .name(service.name)
+        .request(data)
+        .response(responseData)
+        .url(request.getUri().getPath())
+        .build();
   }
 
   private static EqRate calc(Service service, RequestData data)
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/services/ServicesUtil.java b/src/main/java/gov/usgs/earthquake/nshmp/www/services/ServicesUtil.java
index 7efcfbc98..855475286 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/services/ServicesUtil.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/services/ServicesUtil.java
@@ -12,11 +12,10 @@ import gov.usgs.earthquake.nshmp.calc.CalcConfig;
 import gov.usgs.earthquake.nshmp.calc.Hazard;
 import gov.usgs.earthquake.nshmp.calc.HazardCalcs;
 import gov.usgs.earthquake.nshmp.calc.Site;
-import gov.usgs.earthquake.nshmp.internal.www.NshmpMicronautServlet.UrlHelper;
-import gov.usgs.earthquake.nshmp.internal.www.Response;
-import gov.usgs.earthquake.nshmp.internal.www.WsUtils;
-import gov.usgs.earthquake.nshmp.internal.www.meta.Status;
 import gov.usgs.earthquake.nshmp.model.HazardModel;
+import gov.usgs.earthquake.nshmp.www.Response;
+import gov.usgs.earthquake.nshmp.www.WsUtils;
+import gov.usgs.earthquake.nshmp.www.meta.Status;
 
 import io.micronaut.http.HttpResponse;
 
@@ -25,9 +24,9 @@ class ServicesUtil {
   static HttpResponse<String> handleError(
       Throwable e,
       String name,
-      UrlHelper urlHelper) {
+      String url) {
     var msg = e.getMessage() + " (see logs)";
-    var svcResponse = new Response<>(Status.ERROR, name, urlHelper.url, msg, urlHelper);
+    var svcResponse = new Response<>(Status.ERROR, name, url, msg, url);
     var gson = new GsonBuilder().setPrettyPrinting().create();
     var response = gson.toJson(svcResponse);
     e.printStackTrace();
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/services/ServletUtil.java b/src/main/java/gov/usgs/earthquake/nshmp/www/services/ServletUtil.java
index ca4483047..3a4a71851 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/services/ServletUtil.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/services/ServletUtil.java
@@ -28,8 +28,8 @@ import com.google.gson.JsonSerializer;
 import gov.usgs.earthquake.nshmp.calc.Site;
 import gov.usgs.earthquake.nshmp.calc.ValueFormat;
 import gov.usgs.earthquake.nshmp.gmm.Imt;
-import gov.usgs.earthquake.nshmp.internal.www.meta.ParamType;
 import gov.usgs.earthquake.nshmp.model.HazardModel;
+import gov.usgs.earthquake.nshmp.www.WsUtils;
 import gov.usgs.earthquake.nshmp.www.meta.MetaUtil;
 
 import io.micronaut.context.annotation.Value;
@@ -72,10 +72,9 @@ public class ServletUtil {
     CALC_EXECUTOR = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(THREAD_COUNT));
     TASK_EXECUTOR = Executors.newSingleThreadExecutor();
     GSON = new GsonBuilder()
-        .registerTypeAdapter(Imt.class, new MetaUtil.EnumSerializer<Imt>())
-        .registerTypeAdapter(ValueFormat.class, new MetaUtil.EnumSerializer<ValueFormat>())
-        .registerTypeAdapter(Double.class, new MetaUtil.DoubleSerializer())
-        .registerTypeAdapter(ParamType.class, new MetaUtil.ParamTypeSerializer())
+        .registerTypeAdapter(Imt.class, new WsUtils.EnumSerializer<Imt>())
+        .registerTypeAdapter(ValueFormat.class, new WsUtils.EnumSerializer<ValueFormat>())
+        .registerTypeAdapter(Double.class, new WsUtils.DoubleSerializer())
         .registerTypeAdapter(Site.class, new MetaUtil.SiteSerializer())
         .registerTypeHierarchyAdapter(Path.class, new PathConverter())
         .disableHtmlEscaping()
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/services/SourceServices.java b/src/main/java/gov/usgs/earthquake/nshmp/www/services/SourceServices.java
index 4773a3c80..ce54b6b3a 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/services/SourceServices.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/services/SourceServices.java
@@ -10,14 +10,13 @@ import com.google.gson.GsonBuilder;
 import gov.usgs.earthquake.nshmp.gmm.Gmm;
 import gov.usgs.earthquake.nshmp.gmm.Imt;
 import gov.usgs.earthquake.nshmp.gmm.NehrpSiteClass;
-import gov.usgs.earthquake.nshmp.internal.www.NshmpMicronautServlet.UrlHelper;
-import gov.usgs.earthquake.nshmp.internal.www.Response;
-import gov.usgs.earthquake.nshmp.internal.www.meta.ParamType;
-import gov.usgs.earthquake.nshmp.internal.www.meta.Status;
 import gov.usgs.earthquake.nshmp.model.HazardModel;
-import gov.usgs.earthquake.nshmp.www.meta.MetaUtil;
+import gov.usgs.earthquake.nshmp.www.Response;
+import gov.usgs.earthquake.nshmp.www.WsUtils;
 import gov.usgs.earthquake.nshmp.www.meta.Metadata;
+import gov.usgs.earthquake.nshmp.www.meta.Status;
 
+import io.micronaut.http.HttpRequest;
 import io.micronaut.http.HttpResponse;
 
 /**
@@ -37,22 +36,22 @@ public class SourceServices {
 
   static {
     GSON = new GsonBuilder()
-        .registerTypeAdapter(Imt.class, new MetaUtil.EnumSerializer<Imt>())
-        .registerTypeAdapter(ParamType.class, new MetaUtil.ParamTypeSerializer())
+        .registerTypeAdapter(Imt.class, new WsUtils.EnumSerializer<Imt>())
         .disableHtmlEscaping()
         .serializeNulls()
         .setPrettyPrinting()
         .create();
   }
 
-  public static HttpResponse<String> handleDoGetUsage(UrlHelper urlHelper) {
+  public static HttpResponse<String> handleDoGetUsage(HttpRequest<?> request) {
+    var url = request.getUri().getPath();
     try {
       var response = new Response<>(
-          Status.USAGE, NAME, urlHelper.url, new ResponseData(), urlHelper);
+          Status.USAGE, NAME, url, new ResponseData(), url);
       var jsonString = GSON.toJson(response);
       return HttpResponse.ok(jsonString);
     } catch (Exception e) {
-      return ServicesUtil.handleError(e, NAME, urlHelper);
+      return ServicesUtil.handleError(e, NAME, url);
     }
   }
 
-- 
GitLab