Skip to content

Commit

Permalink
feat: move invalid response detection from xen-api to xapi
Browse files Browse the repository at this point in the history
Introduced in ea5358e

Fixes https://xcp-ng.org/forum/post/83157

The detection taints the stream and makes helpers like `body.text()` unusable.
  • Loading branch information
julien-f committed Sep 29, 2024
1 parent cfea2b3 commit 030b3ad
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 29 deletions.
1 change: 1 addition & 0 deletions @xen-orchestra/xapi/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"@vates/async-each": "^1.0.0",
"@vates/decorate-with": "^2.1.0",
"@vates/nbd-client": "^3.1.0",
"@vates/read-chunk": "^1.2.0",
"@vates/task": "^0.4.0",
"@xen-orchestra/async-map": "^0.1.2",
"@xen-orchestra/log": "^0.6.0",
Expand Down
34 changes: 34 additions & 0 deletions @xen-orchestra/xapi/vdi.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { createLogger } from '@xen-orchestra/log'
import { createVhdStreamWithLength } from 'vhd-lib'
import { decorateClass } from '@vates/decorate-with'
import { defer } from 'golike-defer'
import { readChunk } from '@vates/read-chunk'
import { strict as assert } from 'node:assert'

import MultiNbdClient from '@vates/nbd-client/multi.mjs'
Expand All @@ -14,6 +15,34 @@ import { finished } from 'node:stream'

const { warn, info } = createLogger('xo:xapi:vdi')

// 2024-09-26 - Work-around a XAPI bug: sometimes the response status is
// `200 OK` but the body contains a full HTTP response
//
// Example:
//
// ```http
// HTTP/1.1 500 Internal Error
// content-length: 357
// content-type:text/html
// connection:close
// cache-control:no-cache, no-store
//
// <html><body><h1>HTTP 500 internal server error</h1>An unexpected error occurred; please wait a while and try again. If the problem persists, please contact your support representative.<h1> Additional information </h1>SR_BACKEND_FAILURE_46: [ ; The VDI is not available [opterr=VDI d63513c8-b662-41cd-a355-a63efb5f073f not detached cleanly]; ]</body></html>
// ```
//
// Related GitHub issue: https://github.com/xapi-project/xen-api/issues/4603
//
// This function detects this and throw an error
async function checkVdiExport(stream) {
const chunk = await readChunk(stream, 5)
stream.unshift(chunk)
if (String(chunk) === 'HTTP/') {
const error = new Error('invalid HTTP header in response body')
Object.defineProperty(error, 'response', { body: await readChunk(stream, 1024) })
throw error
}
}

const noop = Function.prototype
class Vdi {
async clone(vdiRef) {
Expand Down Expand Up @@ -157,6 +186,9 @@ class Vdi {
query,
task: await this.task_create(`Exporting content of VDI ${vdiName}`),
})

await checkVdiExport(body)

return body
}

Expand Down Expand Up @@ -215,6 +247,8 @@ class Vdi {
})
).body

await checkVdiExport(stream)

$defer.onFailure(() => {
exportStream.on('error', noop).destroy()
})
Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG.unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,7 @@
<!--packages-start-->

- @xen-orchestra/xapi patch
- xen-api patch

<!--packages-end-->
28 changes: 0 additions & 28 deletions packages/xen-api/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import makeCallSetting from './_makeCallSetting.mjs'
import parseUrl from './_parseUrl.mjs'
import Ref from './_Ref.mjs'
import transports from './transports/index.mjs'
import { readChunk } from '@vates/read-chunk'

const { debug } = createLogger('xen-api')

Expand Down Expand Up @@ -478,33 +477,6 @@ export class Xapi extends EventEmitter {
)
)

// 2024-09-26 - Work-around a XAPI bug: sometimes the response status is
// `200 OK` but the body contains a full HTTP response
//
// Example:
//
// ```http
// HTTP/1.1 500 Internal Error
// content-length: 357
// content-type:text/html
// connection:close
// cache-control:no-cache, no-store
//
// <html><body><h1>HTTP 500 internal server error</h1>An unexpected error occurred; please wait a while and try again. If the problem persists, please contact your support representative.<h1> Additional information </h1>SR_BACKEND_FAILURE_46: [ ; The VDI is not available [opterr=VDI d63513c8-b662-41cd-a355-a63efb5f073f not detached cleanly]; ]</body></html>
// ```
//
// Related GitHub issue: https://github.com/xapi-project/xen-api/issues/4603
//
// This code detects this and throw an error
const { body } = response
const chunk = await readChunk(body, 5)
body.unshift(chunk)
if (String(chunk) === 'HTTP/') {
const error = new Error('invalid HTTP header in response body')
Object.defineProperty(error, 'response', { value: response })
throw error
}

if (pTaskResult !== undefined) {
response.task = pTaskResult
}
Expand Down
1 change: 0 additions & 1 deletion packages/xen-api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
"@vates/decorate-with": "^2.1.0",
"@vates/json-hash": "^0.2.0",
"@vates/obfuscate": "^0.1.0",
"@vates/read-chunk": "^1.2.0",
"@vates/xml": "^2.0.0",
"@vates/xml-rpc": "^1.0.0",
"@xen-orchestra/log": "^0.6.0",
Expand Down

0 comments on commit 030b3ad

Please sign in to comment.