Skip to content

Commit ee45869

Browse files
committed
feat(openapi): support structured syntax suffixes in for JSON MIME types.
1 parent 25b68e7 commit ee45869

File tree

3 files changed

+34
-13
lines changed

3 files changed

+34
-13
lines changed

mock/openapi/build.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ dependencies {
1717

1818
implementation "io.swagger.parser.v3:swagger-parser-v3:$version_swagger_parser"
1919
implementation "com.atlassian.oai:swagger-request-validator-core:$version_swagger_request_validator"
20+
implementation 'jakarta.activation:jakarta.activation-api:2.1.3'
2021

2122
implementation platform("com.amazonaws:aws-java-sdk-bom:$version_aws_sdk")
2223
implementation 'com.amazonaws:aws-java-sdk-s3'
@@ -26,6 +27,8 @@ dependencies {
2627
testImplementation project(':test:api-tests')
2728
testImplementation "org.testcontainers:testcontainers:$version_testcontainers"
2829
testImplementation "com.adobe.testing:s3mock-testcontainers:$version_s3mock"
30+
testImplementation "org.mockito:mockito-core:$version_mockito"
31+
testImplementation "org.mockito.kotlin:mockito-kotlin:$version_mockito_kotlin"
2932

3033
// java 11 compatibility
3134
testImplementation ("javax.xml.bind:jaxb-api:$version_jaxb_api")

mock/openapi/src/main/java/io/gatehill/imposter/plugin/openapi/service/ResponseTransmissionServiceImpl.kt

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -42,17 +42,16 @@
4242
*/
4343
package io.gatehill.imposter.plugin.openapi.service
4444

45-
import com.fasterxml.jackson.core.JsonProcessingException
4645
import io.gatehill.imposter.http.HttpExchange
4746
import io.gatehill.imposter.plugin.openapi.model.ContentTypedHolder
4847
import io.gatehill.imposter.util.HttpUtil.CONTENT_TYPE
4948
import io.gatehill.imposter.util.LogUtil
5049
import io.gatehill.imposter.util.MapUtil
5150
import io.gatehill.imposter.util.MapUtil.YAML_MAPPER
5251
import io.swagger.v3.oas.models.examples.Example
52+
import jakarta.activation.MimeType
5353
import org.apache.logging.log4j.LogManager
5454
import java.util.Objects
55-
import javax.activation.MimeType
5655

5756
/**
5857
* Serialises and transmits examples to the client.
@@ -174,26 +173,26 @@ class ResponseTransmissionServiceImpl : ResponseTransmissionService {
174173
}
175174
}
176175
exampleResponse
177-
} catch (e: JsonProcessingException) {
178-
LOGGER.error("Error building example response", e)
179-
""
176+
} catch (e: Exception) {
177+
LOGGER.error("Error serialising response", e)
178+
example.toString()
180179
}
181180
}
182181

182+
/**
183+
* Extension method to check MIME type compatibility.
184+
* Supports RFC 6838 structured syntax suffixes.
185+
*/
183186
private fun MimeType.compatibleWith(other: MimeType): Boolean {
184-
return this.primaryType == other.primaryType && (
185-
this.subType == other.subType
186-
|| this.subType.endsWith("+${other.subType}")
187-
|| other.subType.endsWith("+${this.subType}")
188-
)
187+
return (this.primaryType == other.primaryType && this.subType == other.subType) ||
188+
this.subType.endsWith("+${other.subType}") ||
189+
other.subType.endsWith("+${this.subType}")
189190
}
190191

191192
companion object {
192193
private val LOGGER = LogManager.getLogger(ResponseTransmissionServiceImpl::class.java)
193194
private val JSON_CONTENT_TYPE = MimeType("application/json")
194195
private val YAML_CONTENT_TYPES = setOf("text/x-yaml", "application/yaml", "application/x-yaml")
195-
.map{ MimeType(it) }
196-
197-
196+
.map { MimeType(it) }
198197
}
199198
}

mock/openapi/src/test/java/io/gatehill/imposter/plugin/openapi/service/ResponseTransmissionServiceImplTest.kt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,25 @@ class ResponseTransmissionServiceImplTest {
138138
assertTrue(response.contains("\"data\""))
139139
}
140140

141+
@Test
142+
fun `should serialise as JSON for non-application json types with json suffix`() {
143+
val httpExchange = createMockHttpExchange()
144+
val testData = mapOf("metadata" to "test")
145+
val example = ContentTypedHolder("text/vnd.something+json", testData)
146+
147+
service.transmitExample(httpExchange, example)
148+
149+
verify(httpExchange.response).putHeader("Content-Type", "text/vnd.something+json")
150+
151+
val responseCaptor = argumentCaptor<String>()
152+
verify(httpExchange.response).end(responseCaptor.capture())
153+
val response = responseCaptor.firstValue
154+
155+
// Verify it's JSON format
156+
assertTrue(response.contains("\"metadata\""))
157+
assertTrue(response.contains("\"test\""))
158+
}
159+
141160
@Test
142161
fun `should serialise as YAML for YAML content types`() {
143162
val httpExchange = createMockHttpExchange()

0 commit comments

Comments
 (0)