Skip to content

'Content-Length' value returned by TSServer is one off on Windows #3403

@micbou

Description

@micbou

The 'Content-Length' value returned by TSServer does not take into account that newlines on Windows are two characters \r\n instead of \n. The issue was found in PR ycm-core/ycmd#156.

Here's a minimal example. Create a dummy test.ts file and a Python script with the following lines:

#!/usr/bin/env python

import json
import subprocess


class TypeScript():
    _tsserver_handle = subprocess.Popen(
      'tsserver.cmd',
      stdout = subprocess.PIPE,
      stdin = subprocess.PIPE
    )

    def SendRequest(self, command, arguments=None):
        request = {
            'seq': 0,
            'type': 'request',
            'command': command
        }
        if arguments:
            request['arguments'] = arguments

        self._tsserver_handle.stdin.write(json.dumps(request) + '\n')


    def ReadResponse(self):
        headers = {}
        while True:
            headerline = self._tsserver_handle.stdout.readline().strip()
            if not headerline:
                break
            key, value = headerline.split( ':', 1 )
            headers[ key.strip() ] = value.strip()

        if 'Content-Length' not in headers:
          raise RuntimeError( "Missing 'Content-Length' header" )
        contentlength = int( headers[ 'Content-Length' ] )
        output = self._tsserver_handle.stdout.read( contentlength )
        print( repr( output ) )


def Main():
    typescript = TypeScript()
    test_file = 'test.ts'

    command = 'open'
    arguments = { 'file': test_file }

    typescript.SendRequest(command, arguments)

    command = 'reload'
    arguments = { 'tmpfile': test_file, 'file': test_file }

    typescript.SendRequest(command, arguments)
    typescript.ReadResponse()

    command = 'reload'
    arguments = { 'tmpfile': test_file, 'file': test_file }

    typescript.SendRequest(command, arguments)
    typescript.ReadResponse()


if __name__ == '__main__':
    Main()

This script sends requests to TSServer and tries to read them. An exception is raised if no Content-Length key in header is found.

On Linux, the output is:

'{"seq":0,"type":"response","command":"reload","request_seq":0,"success":true}\n'
'{"seq":0,"type":"response","command":"reload","request_seq":0,"success":true}\n'

On Windows:

'{"seq":0,"type":"response","command":"reload","request_seq":0,"success":true}\r'
Traceback (most recent call last):
  File "./typescript.py", line 68, in <module>
    Main()
  File "./typescript.py", line 64, in Main
    typescript.ReadResponse()
  File "./typescript.py", line 36, in ReadResponse
    raise RuntimeError( "Missing 'Content-Length' header" )
RuntimeError: Missing 'Content-Length' header

If contentlength is incremented by one:

'{"seq":0,"type":"response","command":"reload","request_seq":0,"success":true}\r\n'
'{"seq":0,"type":"response","command":"reload","request_seq":0,"success":true}\r\n'

In all these cases, TSServer returns a length of 78 characters ({"seq":0,"type":"response","command":"reload","request_seq":0,"success":true} is 77 long). It should return a length of 79 characters on Windows.

Metadata

Metadata

Assignees

No one assigned

    Labels

    APIRelates to the public API for TypeScriptBugA bug in TypeScriptHelp WantedYou can do this

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions