After updating the msw package from 0.15.5 to 0.19.0 and update the mockServiceWorker.js file, the service worker started throwing the following error
Uncaught (in promise) SyntaxError: Unexpected end of input at line 111
After some debugging I was able to fix the issue ( at least for me ) by replacing
const body = request.headers.get('content-type')?.includes('json')
? await request.json()
: await request.text()
with
const isJSONContentType = request.headers.get('content-type')?.includes('json')
let body;
if (isJSONContentType) {
try {
body = await request.json()
} catch (error) {
console.warn(error)
body = await request.text()
console.log({body,headers: Object.fromEntries(request.headers.entries()), url: request.url})
}
} else {
body = await request.text()
}
with this fix I'm getting the correct mocked responses but what I don't understand is why the body is showing up empty
msw: 0.19.0nodejs: 12.13.1npm: 6.14.5webpack: 4.42.1webpack-dev-server: 3.10.3The requests that are failing match with a Webpack DevServer proxy that I have in my environment.
The proxy takes every request url starting with "/api" to a live server
Webpack devServer config:
devServer: {
contentBase: "./public",
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "Origin, X-Requested-With, Content-Type, Accept"
},
host: !process.argv.join(" ").includes("--sw") && require("ip").address(),
disableHostCheck: true,
open: true,
hot: false,
port,
proxy: {
"/api": {
target: "https://live.server.domain.cloud",
secure: false,
changeOrigin: true,
withCredentials: true,
}
}
},
Please also provide your browser version.
Chrome 83.0.4103.61
Steps to reproduce the behaviour:
Uncaught (in promise) SyntaxError: Unexpected end of inputShouldn't throw if the suspected response has the Content-Type header containing "json" and the body is empty
Original error

chrome console after I added some logs and error handling on mockServiceWorker.js

Network tab of the same session / request after the fix showing expected mocked data

Hey, @mouhannad-sh. Thanks for reporting this.
Let me clarify: is the empty body ("") intended, or is the actual body set, but for some reason is being empty in the worker?
Historically, there has been a fallback from a failed
.json()to.text()when retrieving a body. However, we wanted to encourage developers to respect theContent-Typeheader, so when it's set to*/jsonthe body must be a valid JSON. Now I see that this doesn't cover the empty body scenario.
I'm thinking whether we even need to determine if it's JSON or not. Thing is, right after retrieving the body, it gets stringified in sentToClient anyway. It should be much safer and error-prone to always get the textual body, send it to the client, and _then_ figure out whether to parse or not.
Error handling in such case is delegated to the client, which makes any potential issues solvable on the client-side library, without having to touch the worker file. The intention is that the worker file should be the bare minimum, the one that needs almost no maintenance at all.
Additionally, in the current implementation of the client-side parsing of the worker message, we already check for empty strings, and prevent parsing as JSON in that case:
I really think we should do only this when handling request body in the worker:
const reqBody = await request.text()
I'd expect that to handle even the binary files, converting blobs to text, and then letting the client-side library parsing to decide how to parse that.
@mouhannad-sh, please, would you be interested in helping me with this fix? I'd gladly assist in code reviews and share any necessary insights about the library.
Thanks for the quick response @kettanaito 馃憤
I'm currently on the go, I'll put up a PR for this ASAP
@mouhannad-sh, hey, no worries! Whenever you have a spare time for this.
Your involvement is highly appreciated! Thank you.
Let me clarify: is the empty body ("") intended, or is the actual body set, but for some reason is being empty in the worker?
unfortunately It's the latter, even though everything in the browser is working as expected, all of my mocked responses are coming in correctly in the network tab, the empty responses are only showing in the worker file
Having the same issue. I suppose it's because of the dev proxy server. I use create-react-app and this is my setupProxy.js file:
const { createProxyMiddleware } = require('http-proxy-middleware')
module.exports = function (app) {
app.use(
['/auth', '/api'],
createProxyMiddleware({
target: process.env.DEV_PROXY,
changeOrigin: true,
}),
)
}
This is how I make a request:
window.fetch(url, {
headers: {
'Content-Type': 'application/json',
},
})
Before the setupProxy.js file was created, msw worked fine.
Most helpful comment
Having the same issue. I suppose it's because of the dev proxy server. I use
create-react-appand this is mysetupProxy.jsfile:This is how I make a request:
Before the
setupProxy.jsfile was created,mswworked fine.