graphql-ruby
graphql-ruby copied to clipboard
GraphQL Pro Defer net::ERR_INCOMPLETE_CHUNKED_ENCODING
We are using Defer in production and we are having some strange behaviour. The request bellow seems to fail randomly (maybe 10-30% of the time).
It looks to us that some chunks aren't json valid. More precisely it's sending 2 chunks including http header in one stream.
The error we are facing in the browser is Failed to load resource: net::ERR_INCOMPLETE_CHUNKED_ENCODING.
It happens in GraphiQL client and Apollo integration (v3.13.8)
Controller implementation:
def execute
authenticate!
result = batched_queries ? multiplex_query : execute_query
if result.respond_to?(:context) && (deferred = result.context[:defer])
response.headers['Last-Modified'] = Time.now.httpdate
deferred.stream_http_multipart(response, incremental: true)
elsif result.is_a?(Array)
render json: result.map(&:to_h)
else
render json: result.to_h
end
rescue Exceptions::AuthError => e
handle_auth_exceptions(e)
rescue StandardError => e
handle_exceptions(e)
ensure
response.stream.close unless response.stream.closed?
end
Query
query GetInitial3DProductInfo($id: ID!) {
node(id: $id) {
... on Product {
id
useViewerIntegration
uuid
previewUrl
isConfigurator
isDraftVersion
publishedAt
model {
allConfigurations {
totalCount
nodes {
id
parent {
id
__typename
}
configurations {
nodes {
id
__typename
}
__typename
}
variants {
totalCount
nodes {
... on Variant {
id
uuid
name
cameraPosition {
id
name
uuid
position
lookAt
__typename
}
configuration {
id
__typename
}
swatchColour
displayPosition
arAppleAsset {
... on SharedAsset {
id
uuid
updatedAt
contentType
fileMeta
fileName
fingerprint
styles {
name
url
__typename
}
__typename
}
__typename
}
arAndroidAsset {
... on SharedAsset {
id
uuid
updatedAt
contentType
fileMeta
fileName
fingerprint
styles {
name
url
__typename
}
__typename
}
__typename
}
hasChainAnnotations
status
previews {
nodes {
id
asset {
id
styles {
url
name
__typename
}
__typename
}
__typename
}
__typename
}
shadowAsset {
id
fileName
styles {
url
name
__typename
}
__typename
}
shadowMesh {
id
name
sourceAsset {
fileName
styles {
url
name
__typename
}
__typename
}
gltfAsset {
id
jsonContent
__typename
}
__typename
}
metadata
annotations @defer {
totalCount
nodes {
id
uuid
buttonText
buttonUrl
cameraLookAt
cameraPosition
content
markerPosition
title
__typename
}
__typename
}
textnodes @defer {
nodes {
id
alignment
cameraLookAt
cameraPosition
content
contentPosition
contentRotation
size
__typename
}
__typename
}
meshReplacements @defer {
totalCount
nodes {
id
uuid
replacement {
id
uuid
name
__typename
}
source {
id
uuid
name
__typename
}
__typename
}
__typename
}
materialReplacements @defer {
totalCount
nodes {
id
uuid
replacement {
id
uuid
name
__typename
}
source {
id
uuid
name
__typename
}
__typename
}
__typename
}
allMeshAssignments @defer {
totalCount
nodes {
id
uuid
name
translation
scale
rotation
material {
id
uuid
__typename
}
mesh {
id
uuid
__typename
}
group {
id
uuid
__typename
}
__typename
}
__typename
}
allMeshAssignmentGroups @defer {
totalCount
nodes {
id
uuid
name
translation
scale
rotation
parent {
id
uuid
__typename
}
__typename
}
__typename
}
__typename
}
__typename
}
__typename
}
__typename
}
__typename
}
__typename
}
__typename
}
__typename
}
}
Response on GraphiQL:
{
"errors": [
{
"message": "Expected multipart chunks to be of json type. got:\nHeaders::\n[object Object]\n\nBody::\n{\"incremental\":[{\"path\":[\"node\",\"model\",\"allConfigurations\",\"nodes\",22,\"variants\",\"nodes\",2,\"allMeshAssignmentGroups\"],\"data\":{\"totalCount\":3,\"nodes\":[{\"id\":\"R3JvdXAtMjE1YWMzZjAtMDkwOS0wMTNlLTQyNDAtNjZmNTcyN2U2YzM0\",\"uuid\":\"215ac3f0-0909-013e-4240-66f5727e6c34\",\"name\":\"0b867e53c1d233ce9fe49d54549a232320240830-4-78nb1y\",\"translation\":{\"x\":0,\"y\":0,\"z\":0},\"scale\":{\"x\":1,\"y\":1,\"z\":1},\"rotation\":{\"x\":0,\"y\":0,\"z\":0,\"w\":1},\"parent\":null,\"__typename\":\"Group\"},{\"id\":\"R3JvdXAtMjE1YjA5ODAtMDkwOS0wMTNlLTllOWMtNjZmNTcyN2U2YzM0\",\"uuid\":\"215b0980-0909-013e-9e9c-66f5727e6c34\",\"name\":\"0b867e53c1d233ce9fe49d54549a232320240830-4-kvds5x\",\"translation\":{\"x\":0,\"y\":0,\"z\":0},\"scale\":{\"x\":1,\"y\":1,\"z\":1},\"rotation\":{\"x\":0,\"y\":0,\"z\":0,\"w\":1},\"parent\":null,\"__typename\":\"Group\"},{\"id\":\"R3JvdXAtMjE1YjUwYzAtMDkwOS0wMTNlLTBiYTctNjZmNTcyN2U2YzM0\",\"uuid\":\"215b50c0-0909-013e-0ba7-66f5727e6c34\",\"name\":\"0b867e53c1d233ce9fe49d54549a232320240830-4-xv6dyj\",\"translation\":{\"x\":0,\"y\":0,\"z\":0},\"scale\":{\"x\":1,\"y\":1,\"z\":1},\"rotation\":{\"x\":0,\"y\":0,\"z\":0,\"w\":1},\"parent\":null,\"__typename\":\"Group\"}],\"__typename\":\"GroupConnection\"}}],\"hasNext\":true}\r\n---\r\nContent-Type: application/json\r\nContent-Length: 195\r\n\r\n{\"incremental\":[{\"path\":[\"node\",\"model\",\"allConfigurations\",\"nodes\",22,\"variants\",\"nodes\",3,\"annotations\"],\"data\":{\"totalCount\":0,\"nodes\":[],\"__typename\":\"AnnotationConnection\"}}],\"hasNext\":true},Headers::\n[object Object]\n\nBody::\n[object Object],Headers::\n[object Object]\n\nBody::\n[object Object],Headers::\n[object Object]\n\nBody::\n[object Object]",
"stack": "@https://api.sayduck.io/assets/graphiql/rails/application-81c86557b6f6453812b8a74649ca5c83bfc9ba6001c20ecff68dff7135286876.js:2:607692\no@https://api.sayduck.io/assets/graphiql/rails/application-81c86557b6f6453812b8a74649ca5c83bfc9ba6001c20ecff68dff7135286876.js:2:607903"
}
]
}
Manually pretty printed string:
Expected multipart chunks to be of json type. got:
Headers: :
[object Object]
Body: :
{
"incremental":[
{
"path": [
"node",
"model",
"allConfigurations",
"nodes",
22,
"variants",
"nodes",
2,
"allMeshAssignmentGroups"
],
"data": {
"totalCount":3,
"nodes": [
{
"id": "R3JvdXAtMjE1YWMzZjAtMDkwOS0wMTNlLTQyNDAtNjZmNTcyN2U2YzM0",
"uuid": "215ac3f0-0909-013e-4240-66f5727e6c34",
"name": "0b867e53c1d233ce9fe49d54549a232320240830-4-78nb1y",
"translation": {
"x": 0,
"y": 0,
"z": 0
},
"scale": {
"x": 1,
"y": 1,
"z": 1
},
"rotation": {
"x": 0,
"y": 0,
"z": 0,
"w": 1
},
"parent": null,
"__typename": "Group"
},
{
"id": "R3JvdXAtMjE1YjA5ODAtMDkwOS0wMTNlLTllOWMtNjZmNTcyN2U2YzM0",
"uuid": "215b0980-0909-013e-9e9c-66f5727e6c34",
"name": "0b867e53c1d233ce9fe49d54549a232320240830-4-kvds5x",
"translation": {
"x": 0,
"y": 0,
"z": 0
},
"scale": {
"x": 1,
"y": 1,
"z": 1
},
"rotation": {
"x": 0,
"y": 0,
"z": 0,
"w": 1
},
"parent": null,
"__typename": "Group"
},
{
"id": "R3JvdXAtMjE1YjUwYzAtMDkwOS0wMTNlLTBiYTctNjZmNTcyN2U2YzM0",
"uuid": "215b50c0-0909-013e-0ba7-66f5727e6c34",
"name": "0b867e53c1d233ce9fe49d54549a232320240830-4-xv6dyj",
"translation": {
"x": 0,
"y": 0,
"z": 0
},
"scale": {
"x": 1,
"y": 1,
"z": 1
},
"rotation": {
"x": 0,
"y": 0,
"z": 0,
"w": 1
},
"parent": null,
"__typename": "Group"
}
],
"__typename": "GroupConnection"
},
}
],
"hasNext": true
}
\r\n---\r\nContent-Type: application/json\r\nContent-Length: 195\r\n\r
{
"incremental": [
{
"path": [
"node",
"model",
"allConfigurations",
"nodes",
22,
"variants",
"nodes",
3,
"annotations"
],
"data": {
"totalCount": 0,
"nodes": [],
"__typename": "AnnotationConnection"
}
}
],
"hasNext": true
},
Headers: :
[object Object]
Body: :
[object Object],
Headers: :
[object Object]
Body: :
[object Object],
Headers: :
[object Object]
Body: :
[object Object]