Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: do not treat utf8 requests as binary #15946

Merged
merged 12 commits into from
Apr 22, 2021
2 changes: 0 additions & 2 deletions packages/driver/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ You can also run all of the driver's tests locally. We don't really recommend th
It's usually easier to run the tests in the GUI, commit, and then see if anything broke elsewhere.

```bash
yarn workspace @packages/driver start

# in separate terminal
yarn workspace @packages/driver cypress:run

Expand Down
10 changes: 8 additions & 2 deletions packages/net-stubbing/lib/server/middleware/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import _ from 'lodash'
import { concatStream } from '@packages/network'
import Debug from 'debug'
import url from 'url'
import { getEncoding } from 'istextorbinary'

import {
RequestMiddleware,
Expand All @@ -16,6 +15,7 @@ import {
sendStaticResponse,
setDefaultHeaders,
mergeDeletedHeaders,
getBodyEncoding,
} from '../util'
import { InterceptedRequest } from '../intercepted-request'
import { BackendRoute } from '../types'
Expand Down Expand Up @@ -118,7 +118,13 @@ export const InterceptRequest: RequestMiddleware = async function () {
throw new Error('req.body must be a string or a Buffer')
}

if (getEncoding(req.body) !== 'binary') {
const encoding = getBodyEncoding(req)

debug('req.body encoding', encoding)

// leave the requests that send a binary buffer unchanged
// but we can work with the "normal" string requests
if (encoding !== 'binary') {
req.body = req.body.toString('utf8')
}

Expand Down
20 changes: 20 additions & 0 deletions packages/net-stubbing/lib/server/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { InterceptedRequest } from './intercepted-request'
// TODO: move this into net-stubbing once cy.route is removed
import { parseContentType } from '@packages/server/lib/controllers/xhrs'
import { CyHttpMessages } from '../external-types'
import { getEncoding } from 'istextorbinary'

const debug = Debug('cypress:net-stubbing:server:util')

Expand Down Expand Up @@ -208,3 +209,22 @@ export function mergeDeletedHeaders (before: CyHttpMessages.BaseMessage, after:
!after.headers[k] && delete before.headers[k]
}
}

type BodyEncoding = 'utf8' | 'binary' | null

export function getBodyEncoding (req: CyHttpMessages.IncomingRequest): BodyEncoding {
if (!req.body) {
return null
}

// a simple heuristic for detecting UTF8 encoded requests
if (req.headers && req.headers['content-type']) {
if (req.headers['content-type'].includes('charset=UTF-8')) {
return 'utf8'
}
}

// with fallback to inspecting the buffer using
// https://github.com/bevry/istextorbinary
return getEncoding(req.body)
}
14 changes: 14 additions & 0 deletions packages/server/test/e2e/7_issue_15901_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
const e2e = require('../support/helpers/e2e').default
const Fixtures = require('../support/helpers/fixtures')

// https://github.com/cypress-io/cypress/issues/15901
describe('issue 15901', () => {
e2e.setup()

it('does not crash', function () {
return e2e.exec(this, {
project: Fixtures.projectPath('issue-15901'),
expectedExitCode: 0,
})
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"fixturesFolder": false,
"supportFile": false,
"pluginsFile": false,
"video": false
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// @see https://github.com/cypress-io/cypress/issues/15901
it('does not crash', () => {
cy.intercept('POST', 'http://localhost:5000/api/sample')
cy.visit('index.html')
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<script>
// the actual server response does not matter
// just trying to verify the network layer does not crash
// https://github.com/cypress-io/cypress/issues/15901
fetch('http://localhost:5000/api/sample', {
method: 'POST',
body: JSON.stringify({
// does not crash
// first: 'hello'
// crash
first: '東京都新東東'
})
}).catch(r => {
console.log(r)
})
</script>