Skip to content

Intercept resets compatible content type when body is an object #17084

@Lakitna

Description

@Lakitna

Current behavior

The following test passes:

const axios = require('axios');

it('overwrites the content-type header', () => {
    cy.intercept('http://localhost:3000', (req) => {
        req.on('response', (res) => {
            res.send({
                statusCode: 500,
                headers: {
                    // A variant of the normal json content type specifically designed
                    // for error messages.
                    'content-type': 'application/problem+json',
                    'access-control-allow-origin': '*',
                },
                body: {
                    status: 500,
                    title: 'Internal Server Error',
                },
            });
        });
    });

    axios
        .get('http://localhost:3000')
        .catch((error) => {
            // Note that this asserts the standard json content type
            expect(error.response.headers['content-type']).to.equal('application/json');
        });
});

image

Desired behavior

.intercept() should not overwrite the content type if I explicitly provide one. Especially if my content type matches the response body.

Or, in other words. The following test should pass:

The test
const axios = require('axios');

it('does not overwrite the content-type header', () => {
  cy.intercept('http://localhost:3000', (req) => {
      req.on('response', (res) => {
          res.send({
              statusCode: 500,
              headers: {
                  'content-type': 'application/problem+json',
                  'access-control-allow-origin': '*',
              },
              body: {
                  status: 500,
                  title: 'Internal Server Error',
              },
          });
      });
  });

  axios
      .get('http://localhost:3000')
      .catch((error) => {
          // Now asserts the content type for Problem JSON
          expect(error.response.headers['content-type']).to.equal('application/problem+json');
      });
});

Test code to reproduce

As above :)

I also have a random server up at http://localhost:3000. Since we're replacing the response of the server anyway, it really doesn't matter what's running there. My server is an Express Hello World :)

const express = require('express')
const app = express()
const port = 3000

app.get('/', (req, res) => {
    res.send('Hello World!')
})

app.listen(port, () => {
    console.log(`Example app listening at http://localhost:${port}`)
})

Versions

Cypress: 7.5.0

Workaround

I already found a workaround. I'll share it in case it helps someone else.

This only happens when your response body is an object, so all you have to do is stringify it like so:

const axios = require('axios');

it('overwrites the content-type header', () => {
    cy.intercept('http://localhost:3000', (req) => {
        req.on('response', (res) => {
            res.send({
                statusCode: 500,
                headers: {
                    'content-type': 'application/problem+json',
                    'access-control-allow-origin': '*',
                },
                // Stringify as a workaround. This issue only happens when body is an
                // object. `JSON.stringify` turns it into a string instead.
                body: JSON.stringify({
                    status: 500,
                    title: 'Internal Server Error',
                }),
            });
        });
    });

    axios
        .get('http://localhost:3000')
        .catch((error) => {
            expect(error.response.headers['content-type']).to.equal('application/problem+json');
        });
});

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions