Skip to content

Commit bccb1ad

Browse files
authored
Merge bbcc7c7 into 2b0a22b
2 parents 2b0a22b + bbcc7c7 commit bccb1ad

5 files changed

Lines changed: 42 additions & 10 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## Unreleased
4+
5+
### Fixes
6+
7+
- Base64 encode internal Apollo3 Headers ([#2707](https://github.com/getsentry/sentry-java/pull/2707))
8+
39
## 6.19.0
410

511
### Features

sentry-apollo-3/src/main/java/io/sentry/apollo3/SentryApollo3HttpInterceptor.kt

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import io.sentry.SpanStatus
2020
import io.sentry.TypeCheckHint
2121
import io.sentry.util.PropagationTargetsUtils
2222
import io.sentry.util.UrlUtils
23+
import io.sentry.vendor.Base64
2324

2425
class SentryApollo3HttpInterceptor @JvmOverloads constructor(private val hub: IHub = HubAdapter.getInstance(), private val beforeSpan: BeforeSpanCallback? = null) :
2526
HttpInterceptor, IntegrationName {
@@ -96,10 +97,14 @@ class SentryApollo3HttpInterceptor @JvmOverloads constructor(private val hub: IH
9697
val method = request.method
9798

9899
val operationName = operationNameFromHeaders(request)
99-
val operationType = request.valueForHeader(SENTRY_APOLLO_3_OPERATION_TYPE)
100+
val operationType = request.valueForHeader(SENTRY_APOLLO_3_OPERATION_TYPE)?.let {
101+
String(Base64.decode(it, Base64.DEFAULT))
102+
}
100103
val operation = if (operationType != null) "http.graphql.$operationType" else "http.graphql"
101104
val operationId = request.valueForHeader("X-APOLLO-OPERATION-ID")
102-
val variables = request.valueForHeader(SENTRY_APOLLO_3_VARIABLES)
105+
val variables = request.valueForHeader(SENTRY_APOLLO_3_VARIABLES)?.let {
106+
String(Base64.decode(it, Base64.DEFAULT))
107+
}
103108
val description = "${operationType ?: method} ${operationName ?: urlDetails.urlOrFallback}"
104109

105110
return activeSpan.startChild(operation, description).apply {
@@ -116,7 +121,9 @@ class SentryApollo3HttpInterceptor @JvmOverloads constructor(private val hub: IH
116121
}
117122

118123
private fun operationNameFromHeaders(request: HttpRequest): String? {
119-
return request.valueForHeader(SENTRY_APOLLO_3_OPERATION_NAME) ?: request.valueForHeader("X-APOLLO-OPERATION-NAME")
124+
return request.valueForHeader(SENTRY_APOLLO_3_OPERATION_NAME)?.let {
125+
String(Base64.decode(it, Base64.DEFAULT))
126+
} ?: request.valueForHeader("X-APOLLO-OPERATION-NAME")
120127
}
121128

122129
private fun HttpRequest.valueForHeader(key: String) = headers.firstOrNull { it.name == key }?.value

sentry-apollo-3/src/main/java/io/sentry/apollo3/SentryApollo3Interceptor.kt

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ import com.apollographql.apollo3.api.Subscription
1010
import com.apollographql.apollo3.api.variables
1111
import com.apollographql.apollo3.interceptor.ApolloInterceptor
1212
import com.apollographql.apollo3.interceptor.ApolloInterceptorChain
13+
import io.sentry.apollo3.SentryApollo3HttpInterceptor.Companion.SENTRY_APOLLO_3_OPERATION_NAME
14+
import io.sentry.apollo3.SentryApollo3HttpInterceptor.Companion.SENTRY_APOLLO_3_OPERATION_TYPE
15+
import io.sentry.apollo3.SentryApollo3HttpInterceptor.Companion.SENTRY_APOLLO_3_VARIABLES
16+
import io.sentry.vendor.Base64
1317
import kotlinx.coroutines.flow.Flow
1418

1519
class SentryApollo3Interceptor : ApolloInterceptor {
@@ -19,11 +23,11 @@ class SentryApollo3Interceptor : ApolloInterceptor {
1923
chain: ApolloInterceptorChain
2024
): Flow<ApolloResponse<D>> {
2125
val builder = request.newBuilder()
22-
.addHttpHeader(SentryApollo3HttpInterceptor.SENTRY_APOLLO_3_OPERATION_TYPE, operationType(request))
23-
.addHttpHeader(SentryApollo3HttpInterceptor.SENTRY_APOLLO_3_OPERATION_NAME, request.operation.name())
26+
.addHttpHeader(SENTRY_APOLLO_3_OPERATION_TYPE, Base64.encodeToString(operationType(request).toByteArray(), Base64.DEFAULT))
27+
.addHttpHeader(SENTRY_APOLLO_3_OPERATION_NAME, Base64.encodeToString(request.operation.name().toByteArray(), Base64.DEFAULT))
2428

2529
request.scalarAdapters?.let {
26-
builder.addHttpHeader(SentryApollo3HttpInterceptor.SENTRY_APOLLO_3_VARIABLES, request.operation.variables(it).valueMap.toString())
30+
builder.addHttpHeader(SENTRY_APOLLO_3_VARIABLES, Base64.encodeToString(request.operation.variables(it).valueMap.toString().toByteArray(), Base64.DEFAULT))
2731
}
2832
return chain.proceed(builder.build())
2933
}

sentry-apollo-3/src/test/java/io/sentry/apollo3/SentryApollo3InterceptorTest.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ class SentryApollo3InterceptorTest {
265265
}
266266
}
267267

268-
private fun executeQuery(sut: ApolloClient = fixture.getSut(), isSpanActive: Boolean = true) = runBlocking {
268+
private fun executeQuery(sut: ApolloClient = fixture.getSut(), isSpanActive: Boolean = true, id: String = "83") = runBlocking {
269269
var tx: ITransaction? = null
270270
if (isSpanActive) {
271271
tx = SentryTracer(TransactionContext("op", "desc", TracesSamplingDecision(true)), fixture.hub)
@@ -274,7 +274,7 @@ class SentryApollo3InterceptorTest {
274274

275275
val coroutine = launch {
276276
try {
277-
sut.query(LaunchDetailsQuery("83")).execute()
277+
sut.query(LaunchDetailsQuery(id)).execute()
278278
} catch (e: ApolloException) {
279279
return@launch
280280
}

sentry-apollo-3/src/test/java/io/sentry/apollo3/SentryApollo3InterceptorWithVariablesTest.kt

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,21 @@ class SentryApollo3InterceptorWithVariablesTest {
120120
)
121121
}
122122

123+
@Test
124+
fun `handles non-ascii header values correctly`() {
125+
executeQuery(id = "á")
126+
127+
verify(fixture.hub).captureTransaction(
128+
check {
129+
assertTransactionDetails(it)
130+
assertEquals(SpanStatus.OK, it.spans.first().status)
131+
},
132+
anyOrNull<TraceContext>(),
133+
anyOrNull(),
134+
anyOrNull()
135+
)
136+
}
137+
123138
@Test
124139
fun `adds breadcrumb when http calls succeeds`() {
125140
executeQuery(fixture.getSut())
@@ -153,7 +168,7 @@ class SentryApollo3InterceptorWithVariablesTest {
153168
}
154169
}
155170

156-
private fun executeQuery(sut: ApolloClient = fixture.getSut(), isSpanActive: Boolean = true) = runBlocking {
171+
private fun executeQuery(sut: ApolloClient = fixture.getSut(), isSpanActive: Boolean = true, id: String = "83") = runBlocking {
157172
var tx: ITransaction? = null
158173
if (isSpanActive) {
159174
tx = SentryTracer(TransactionContext("op", "desc", TracesSamplingDecision(true)), fixture.hub)
@@ -162,7 +177,7 @@ class SentryApollo3InterceptorWithVariablesTest {
162177

163178
val coroutine = launch {
164179
try {
165-
sut.query(LaunchDetailsQuery("83")).execute()
180+
sut.query(LaunchDetailsQuery(id)).execute()
166181
} catch (e: ApolloException) {
167182
return@launch
168183
}

0 commit comments

Comments
 (0)