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

[HttpConnection] Handles malformed HTTP (HEAD) responses #69

Merged
merged 1 commit into from
Aug 10, 2023

Conversation

afharo
Copy link
Member

@afharo afharo commented Aug 10, 2023

We learned that attempting to perform a HEAD request to an HTTP server that doesn't comply with the HTTP spec may lead to crashing the app.

This is because the HTTP client cleans the error listener of the request object once we receive the response object, but Node.js emits the malformed error on the request object.

This PR adds a no-op handler to silence those spec-parse errors.

Testing

To prove the fix works, comment line 132 in src/connection/HttpConnection.ts and see how the test crashes.

@afharo afharo added the bug Something isn't working label Aug 10, 2023
@afharo afharo self-assigned this Aug 10, 2023
Copy link
Member

@azasypkin azasypkin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested with Kibana and everything seems to be working as expected, so LGTM from the Kibana point of view. Thanks!

Copy link
Member

@JoshMock JoshMock left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change looks good to me.

I know Kibana isn't using UndiciConnection still, so I'll have to investigate whether we need to include a similar fix there.

@afharo
Copy link
Member Author

afharo commented Aug 10, 2023

I know Kibana isn't using UndiciConnection still, so I'll have to investigate whether we need to include a similar fix there.

@JoshMock, I tested the issue in this code snippet:

const elasticsearch = require('@elastic/elasticsearch');
const net = require('net');

const HOST = 'http://localhost:8080';

function createTcpServer() {
  const server = net.createServer();
  server.on('connection', (socket) => {
    socket.write(`HTTP/1.1 200 OK\r\n`)
    socket.write(`Content-Type: text/html\r\n`)
    socket.write(`Content-Length: 155\r\n`)
    socket.write(`\r\n`)
    socket.write(`<!DOCTYPE html>
<html>
<head>
 <meta charset="UTF-8">
</head>
<body>
<h1>Hi there</h1>
<p>This is a bad implementation of an HTTP server</p></body>
</html>`)

    socket.end()
  })
  return new Promise((resolve) => server.listen(8080, resolve));
}

async function main() {
  await createTcpServer();

  try {
    console.info('Running Elasticsearch.ping...');
    const esClient = new elasticsearch.Client({
      nodes: [HOST],
      username: '',
      password: '',
      ssl: { verificationMode: 'none' },
      Connection: elasticsearch.HttpConnection,
      ConnectionPool: elasticsearch.ClusterConnectionPool,
    });
    await esClient.ping();
    console.info('Ping succeeded');
  } catch (err) {
    console.error('Elasticsearch.ping', err);
  }
}

main();

// Keep the program running forever to make it super-obvious when it crashes.
setInterval(() => { }, 1000)

Changing the Connection to elasticsearch.UndiciConnection (or even not setting it at all and leaving the default) handles the issue correctly.

@afharo afharo merged commit dafdc56 into elastic:main Aug 10, 2023
18 checks passed
@afharo afharo deleted the handle-malformed-head-responses branch August 10, 2023 16:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants