diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 07fd960c4..17b413b73 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -24,6 +24,8 @@ jobs: uses: actions/setup-java@v1 with: java-version: 11 + - name: Prepare Mock server for SCE ApiRequestEnrichmentIntegrationTest (launch in background) + run: python integration-tests/api-lookup-test.py 8002 & - name: Prepare Mock server for SCE ApiRequestEnrichmentIntegrationTest (launch in background) run: python integration-tests/sce-api-lookup-test.py 8001 & - name: Prepare Mock server for BE ApiRequestEnrichmentIntegrationTest (launch in background) diff --git a/integration-tests/api-lookup-test.py b/integration-tests/api-lookup-test.py index 9191462e9..db2873f20 100755 --- a/integration-tests/api-lookup-test.py +++ b/integration-tests/api-lookup-test.py @@ -72,7 +72,7 @@ def generate_response(self, method, auth=None): } } else: - response = { "serviceName": "sp-api-request-enrichment" } + response = { "latitude": 33.2296 } return json.dumps(response) diff --git a/modules/common/src/main/scala/com.snowplowanalytics.snowplow.enrich/common/enrichments/registry/apirequest/Output.scala b/modules/common/src/main/scala/com.snowplowanalytics.snowplow.enrich/common/enrichments/registry/apirequest/Output.scala index 253db43d4..a0ed7d7f4 100644 --- a/modules/common/src/main/scala/com.snowplowanalytics.snowplow.enrich/common/enrichments/registry/apirequest/Output.scala +++ b/modules/common/src/main/scala/com.snowplowanalytics.snowplow.enrich/common/enrichments/registry/apirequest/Output.scala @@ -15,7 +15,6 @@ package enrichments.registry.apirequest import cats.syntax.either._ import io.circe._ -import io.circe.parser._ import io.circe.syntax._ import utils.JsonPath.{query, wrapArray} @@ -117,6 +116,5 @@ final case class JsonOutput(jsonPath: String) extends ApiOutput[Json] { case other => other.leftMap(JsonPathException.apply) } - def parseResponse(response: String): Either[Throwable, Json] = - parse(response) + def parseResponse(response: String): Either[Throwable, Json] = io.circe.jackson.enrich.parse(response) } diff --git a/modules/common/src/main/scala/io/circe/jackson/enrich/JacksonParser.scala b/modules/common/src/main/scala/io/circe/jackson/enrich/JacksonParser.scala new file mode 100644 index 000000000..5bf108d15 --- /dev/null +++ b/modules/common/src/main/scala/io/circe/jackson/enrich/JacksonParser.scala @@ -0,0 +1,40 @@ +package io.circe.jackson.enrich + +import java.io.File + +import cats.data.ValidatedNel +import io.circe.{Decoder, Error, Json, Parser, ParsingFailure} + +import scala.util.control.NonFatal + +trait JacksonParser extends Parser { this: WithJacksonMapper => + final def parse(input: String): Either[ParsingFailure, Json] = + try Right(mapper.readValue(jsonStringParser(input), classOf[Json])) + catch { + case NonFatal(error) => Left(ParsingFailure(error.getMessage, error)) + } + + final def parseFile(file: File): Either[ParsingFailure, Json] = + try Right(mapper.readValue(jsonFileParser(file), classOf[Json])) + catch { + case NonFatal(error) => Left(ParsingFailure(error.getMessage, error)) + } + + final def parseByteArray(bytes: Array[Byte]): Either[ParsingFailure, Json] = + try Right(mapper.readValue(jsonBytesParser(bytes), classOf[Json])) + catch { + case NonFatal(error) => Left(ParsingFailure(error.getMessage, error)) + } + + final def decodeByteArray[A: Decoder](bytes: Array[Byte]): Either[Error, A] = + finishDecode[A](parseByteArray(bytes)) + + final def decodeByteArrayAccumulating[A: Decoder](bytes: Array[Byte]): ValidatedNel[Error, A] = + finishDecodeAccumulating[A](parseByteArray(bytes)) + + final def decodeFile[A: Decoder](file: File): Either[Error, A] = + finishDecode[A](parseFile(file)) + + final def decodeFileAccumulating[A: Decoder](file: File): ValidatedNel[Error, A] = + finishDecodeAccumulating[A](parseFile(file)) +} diff --git a/modules/common/src/main/scala/io/circe/jackson/enrich/WithJacksonMapper.scala b/modules/common/src/main/scala/io/circe/jackson/enrich/WithJacksonMapper.scala new file mode 100644 index 000000000..1f338d4f8 --- /dev/null +++ b/modules/common/src/main/scala/io/circe/jackson/enrich/WithJacksonMapper.scala @@ -0,0 +1,18 @@ +package io.circe.jackson.enrich + +import java.io.{File, Writer} + +import com.fasterxml.jackson.core.{JsonFactory, JsonParser} +import com.fasterxml.jackson.databind.ObjectMapper +import com.snowplowanalytics.snowplow.enrich.common.utils.CirceUtils + +class WithJacksonMapper { + final val mapper: ObjectMapper = CirceUtils.mapper + private[this] final val jsonFactory: JsonFactory = new JsonFactory(mapper) + + protected final def jsonStringParser(input: String): JsonParser = jsonFactory.createParser(input) + protected final def jsonFileParser(file: File): JsonParser = jsonFactory.createParser(file) + protected final def jsonBytesParser(bytes: Array[Byte]): JsonParser = + jsonFactory.createParser(bytes) + protected final def jsonGenerator(out: Writer) = jsonFactory.createGenerator(out) +} diff --git a/modules/common/src/main/scala/io/circe/jackson/enrich/package.scala b/modules/common/src/main/scala/io/circe/jackson/enrich/package.scala new file mode 100644 index 000000000..9d3e8ce51 --- /dev/null +++ b/modules/common/src/main/scala/io/circe/jackson/enrich/package.scala @@ -0,0 +1,3 @@ +package io.circe.jackson + +package object enrich extends WithJacksonMapper with JacksonParser with JacksonCompat {} diff --git a/modules/common/src/test/resources/iglu-schemas/schemas/com.acme/geo/jsonschema/1-0-0 b/modules/common/src/test/resources/iglu-schemas/schemas/com.acme/geo/jsonschema/1-0-0 new file mode 100644 index 000000000..99699568b --- /dev/null +++ b/modules/common/src/test/resources/iglu-schemas/schemas/com.acme/geo/jsonschema/1-0-0 @@ -0,0 +1,18 @@ +{ + "$schema": "http://iglucentral.com/schemas/com.snowplowanalytics.self-desc/schema/jsonschema/1-0-0#", + "description": "Schema for acme stuff", + "self": { + "vendor": "com.acme", + "name": "geo", + "format": "jsonschema", + "version": "1-0-0" + }, + "type": "object", + "properties": { + "latitude": { + "type": "number" + } + }, + "required": ["latitude"], + "additionalProperties": false +} diff --git a/modules/common/src/test/scala/com.snowplowanalytics.snowplow.enrich.common/enrichments/registry/apirequest/ApiRequestEnrichmentIntegrationTest.scala b/modules/common/src/test/scala/com.snowplowanalytics.snowplow.enrich.common/enrichments/registry/apirequest/ApiRequestEnrichmentIntegrationTest.scala index 2e7f815cb..0cbd86e8a 100644 --- a/modules/common/src/test/scala/com.snowplowanalytics.snowplow.enrich.common/enrichments/registry/apirequest/ApiRequestEnrichmentIntegrationTest.scala +++ b/modules/common/src/test/scala/com.snowplowanalytics.snowplow.enrich.common/enrichments/registry/apirequest/ApiRequestEnrichmentIntegrationTest.scala @@ -49,30 +49,17 @@ class ApiRequestEnrichmentIntegrationTest extends Specification { "name": "api_request_enrichment_config", "enabled": true, "parameters": { - "inputs": [ - { - "key": "user", - "pojo": { - "field": "user_id" - } - }, - { - "key": "client", - "pojo": { - "field": "app_id" - } - } - ], + "inputs": [], "api": { "http": { "method": "GET", - "uri": "http://localhost:8001/guest/api/{{client}}/{{user}}?format=json", - "timeout": 5000, + "uri": "http://localhost:8002/guest", + "timeout": 5000, "authentication": {} } }, "outputs": [{ - "schema": "iglu:com.acme/unauth/jsonschema/1-0-0", + "schema": "iglu:com.acme/geo/jsonschema/1-0-0", "json": { "jsonPath": "$$" } @@ -86,8 +73,7 @@ class ApiRequestEnrichmentIntegrationTest extends Specification { val correctResultContext = SelfDescribingData( - SchemaKey("com.acme", "unauth", "jsonschema", SchemaVer.Full(1, 0, 0)), - json"""{"path": "/guest/api/lookup-test/snowplower?format=json", "message": "unauthorized", "method": "GET"}""" + SchemaKey("com.acme", "geo", "jsonschema", SchemaVer.Full(1, 0, 0)), json"""{"latitude": 33.2296 }""" ) val configuration2 = json"""{