We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
ycmd should return valid JSON instead of empty HTML for 2 requests
/load_extra_conf_file and /ignore_extra_conf_file requests currently return an empty body
in case of success, which is not valid JSON. Instead, ycmd should return valid JSON body, for example just "true".


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `ycmd/handlers.py`
Content:
```
1 # Copyright (C) 2013 Google Inc.
2 #
3 # This file is part of ycmd.
4 #
5 # ycmd is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
9 #
10 # ycmd is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with ycmd.  If not, see <http://www.gnu.org/licenses/>.
17 
18 from __future__ import absolute_import
19 from __future__ import unicode_literals
20 from __future__ import print_function
21 from __future__ import division
22 from future import standard_library
23 standard_library.install_aliases()
24 from builtins import *  # noqa
25 
26 import atexit
27 import bottle
28 import json
29 import logging
30 import traceback
31 from bottle import request
32 
33 import ycm_core
34 from ycmd import extra_conf_store, hmac_plugin, server_state, user_options_store
35 from ycmd.responses import BuildExceptionResponse, BuildCompletionResponse
36 from ycmd.request_wrap import RequestWrap
37 from ycmd.bottle_utils import SetResponseHeader
38 from ycmd.completers.completer_utils import FilterAndSortCandidatesWrap
39 
40 
41 # num bytes for the request body buffer; request.json only works if the request
42 # size is less than this
43 bottle.Request.MEMFILE_MAX = 1000 * 1024
44 
45 _server_state = None
46 _hmac_secret = bytes()
47 _logger = logging.getLogger( __name__ )
48 app = bottle.Bottle()
49 
50 
51 @app.post( '/event_notification' )
52 def EventNotification():
53   _logger.info( 'Received event notification' )
54   request_data = RequestWrap( request.json )
55   event_name = request_data[ 'event_name' ]
56   _logger.debug( 'Event name: %s', event_name )
57 
58   event_handler = 'On' + event_name
59   getattr( _server_state.GetGeneralCompleter(), event_handler )( request_data )
60 
61   filetypes = request_data[ 'filetypes' ]
62   response_data = None
63   if _server_state.FiletypeCompletionUsable( filetypes ):
64     response_data = getattr( _server_state.GetFiletypeCompleter( filetypes ),
65                              event_handler )( request_data )
66 
67   if response_data:
68     return _JsonResponse( response_data )
69   return _JsonResponse( {} )
70 
71 
72 @app.post( '/run_completer_command' )
73 def RunCompleterCommand():
74   _logger.info( 'Received command request' )
75   request_data = RequestWrap( request.json )
76   completer = _GetCompleterForRequestData( request_data )
77 
78   return _JsonResponse( completer.OnUserCommand(
79       request_data[ 'command_arguments' ],
80       request_data ) )
81 
82 
83 @app.post( '/completions' )
84 def GetCompletions():
85   _logger.info( 'Received completion request' )
86   request_data = RequestWrap( request.json )
87   ( do_filetype_completion, forced_filetype_completion ) = (
88                     _server_state.ShouldUseFiletypeCompleter( request_data ) )
89   _logger.debug( 'Using filetype completion: %s', do_filetype_completion )
90 
91   errors = None
92   completions = None
93 
94   if do_filetype_completion:
95     try:
96       completions = ( _server_state.GetFiletypeCompleter(
97                                   request_data[ 'filetypes' ] )
98                                  .ComputeCandidates( request_data ) )
99 
100     except Exception as exception:
101       if forced_filetype_completion:
102         # user explicitly asked for semantic completion, so just pass the error
103         # back
104         raise
105       else:
106         # store the error to be returned with results from the identifier
107         # completer
108         stack = traceback.format_exc()
109         _logger.error( 'Exception from semantic completer (using general): ' +
110                         "".join( stack ) )
111         errors = [ BuildExceptionResponse( exception, stack ) ]
112 
113   if not completions and not forced_filetype_completion:
114     completions = ( _server_state.GetGeneralCompleter()
115                                  .ComputeCandidates( request_data ) )
116 
117   return _JsonResponse(
118       BuildCompletionResponse( completions if completions else [],
119                                request_data.CompletionStartColumn(),
120                                errors = errors ) )
121 
122 
123 @app.post( '/filter_and_sort_candidates' )
124 def FilterAndSortCandidates():
125   _logger.info( 'Received filter & sort request' )
126   # Not using RequestWrap because no need and the requests coming in aren't like
127   # the usual requests we handle.
128   request_data = request.json
129 
130   return _JsonResponse( FilterAndSortCandidatesWrap(
131     request_data[ 'candidates'],
132     request_data[ 'sort_property' ],
133     request_data[ 'query' ] ) )
134 
135 
136 @app.get( '/healthy' )
137 def GetHealthy():
138   _logger.info( 'Received health request' )
139   if request.query.include_subservers:
140     cs_completer = _server_state.GetFiletypeCompleter( ['cs'] )
141     return _JsonResponse( cs_completer.ServerIsHealthy() )
142   return _JsonResponse( True )
143 
144 
145 @app.get( '/ready' )
146 def GetReady():
147   _logger.info( 'Received ready request' )
148   if request.query.subserver:
149     filetype = request.query.subserver
150     return _JsonResponse( _IsSubserverReady( filetype ) )
151   if request.query.include_subservers:
152     return _JsonResponse( _IsSubserverReady( 'cs' ) )
153   return _JsonResponse( True )
154 
155 
156 def _IsSubserverReady( filetype ):
157   completer = _server_state.GetFiletypeCompleter( [filetype] )
158   return completer.ServerIsReady()
159 
160 
161 @app.post( '/semantic_completion_available' )
162 def FiletypeCompletionAvailable():
163   _logger.info( 'Received filetype completion available request' )
164   return _JsonResponse( _server_state.FiletypeCompletionAvailable(
165       RequestWrap( request.json )[ 'filetypes' ] ) )
166 
167 
168 @app.post( '/defined_subcommands' )
169 def DefinedSubcommands():
170   _logger.info( 'Received defined subcommands request' )
171   completer = _GetCompleterForRequestData( RequestWrap( request.json ) )
172 
173   return _JsonResponse( completer.DefinedSubcommands() )
174 
175 
176 @app.post( '/detailed_diagnostic' )
177 def GetDetailedDiagnostic():
178   _logger.info( 'Received detailed diagnostic request' )
179   request_data = RequestWrap( request.json )
180   completer = _GetCompleterForRequestData( request_data )
181 
182   return _JsonResponse( completer.GetDetailedDiagnostic( request_data ) )
183 
184 
185 @app.post( '/load_extra_conf_file' )
186 def LoadExtraConfFile():
187   _logger.info( 'Received extra conf load request' )
188   request_data = RequestWrap( request.json, validate = False )
189   extra_conf_store.Load( request_data[ 'filepath' ], force = True )
190 
191 
192 @app.post( '/ignore_extra_conf_file' )
193 def IgnoreExtraConfFile():
194   _logger.info( 'Received extra conf ignore request' )
195   request_data = RequestWrap( request.json, validate = False )
196   extra_conf_store.Disable( request_data[ 'filepath' ] )
197 
198 
199 @app.post( '/debug_info' )
200 def DebugInfo():
201   _logger.info( 'Received debug info request' )
202 
203   output = []
204   has_clang_support = ycm_core.HasClangSupport()
205   output.append( 'Server has Clang support compiled in: {0}'.format(
206     has_clang_support ) )
207 
208   if has_clang_support:
209     output.append( 'Clang version: ' + ycm_core.ClangVersion() )
210 
211   request_data = RequestWrap( request.json )
212   try:
213     output.append(
214         _GetCompleterForRequestData( request_data ).DebugInfo( request_data ) )
215   except Exception:
216     _logger.debug( 'Exception in debug info request: '
217                    + traceback.format_exc() )
218 
219   return _JsonResponse( '\n'.join( output ) )
220 
221 
222 # The type of the param is Bottle.HTTPError
223 def ErrorHandler( httperror ):
224   body = _JsonResponse( BuildExceptionResponse( httperror.exception,
225                                                 httperror.traceback ) )
226   hmac_plugin.SetHmacHeader( body, _hmac_secret )
227   return body
228 
229 # For every error Bottle encounters it will use this as the default handler
230 app.default_error_handler = ErrorHandler
231 
232 
233 def _JsonResponse( data ):
234   SetResponseHeader( 'Content-Type', 'application/json' )
235   return json.dumps( data, default = _UniversalSerialize )
236 
237 
238 def _UniversalSerialize( obj ):
239   try:
240     serialized = obj.__dict__.copy()
241     serialized[ 'TYPE' ] = type( obj ).__name__
242     return serialized
243   except AttributeError:
244     return str( obj )
245 
246 
247 def _GetCompleterForRequestData( request_data ):
248   completer_target = request_data.get( 'completer_target', None )
249 
250   if completer_target == 'identifier':
251     return _server_state.GetGeneralCompleter().GetIdentifierCompleter()
252   elif completer_target == 'filetype_default' or not completer_target:
253     return _server_state.GetFiletypeCompleter( request_data[ 'filetypes' ] )
254   else:
255     return _server_state.GetFiletypeCompleter( [ completer_target ] )
256 
257 
258 @atexit.register
259 def ServerShutdown():
260   _logger.info( 'Server shutting down' )
261   if _server_state:
262     _server_state.Shutdown()
263     extra_conf_store.Shutdown()
264 
265 
266 def SetHmacSecret( hmac_secret ):
267   global _hmac_secret
268   _hmac_secret = hmac_secret
269 
270 
271 def UpdateUserOptions( options ):
272   global _server_state
273 
274   if not options:
275     return
276 
277   # This should never be passed in, but let's try to remove it just in case.
278   options.pop( 'hmac_secret', None )
279   user_options_store.SetAll( options )
280   _server_state = server_state.ServerState( options )
281 
282 
283 def SetServerStateToDefaults():
284   global _server_state, _logger
285   _logger = logging.getLogger( __name__ )
286   user_options_store.LoadDefaults()
287   _server_state = server_state.ServerState( user_options_store.GetAll() )
288   extra_conf_store.Reset()
289
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/ycmd/handlers.py b/ycmd/handlers.py
--- a/ycmd/handlers.py
+++ b/ycmd/handlers.py
@@ -188,6 +188,8 @@
   request_data = RequestWrap( request.json, validate = False )
   extra_conf_store.Load( request_data[ 'filepath' ], force = True )
 
+  return _JsonResponse( True )
+
 
 @app.post( '/ignore_extra_conf_file' )
 def IgnoreExtraConfFile():
@@ -195,6 +197,8 @@
   request_data = RequestWrap( request.json, validate = False )
   extra_conf_store.Disable( request_data[ 'filepath' ] )
 
+  return _JsonResponse( True )
+
 
 @app.post( '/debug_info' )
 def DebugInfo():

{"golden_diff": "diff --git a/ycmd/handlers.py b/ycmd/handlers.py\n--- a/ycmd/handlers.py\n+++ b/ycmd/handlers.py\n@@ -188,6 +188,8 @@\n   request_data = RequestWrap( request.json, validate = False )\n   extra_conf_store.Load( request_data[ 'filepath' ], force = True )\n \n+  return _JsonResponse( True )\n+\n \n @app.post( '/ignore_extra_conf_file' )\n def IgnoreExtraConfFile():\n@@ -195,6 +197,8 @@\n   request_data = RequestWrap( request.json, validate = False )\n   extra_conf_store.Disable( request_data[ 'filepath' ] )\n \n+  return _JsonResponse( True )\n+\n \n @app.post( '/debug_info' )\n def DebugInfo():\n", "issue": "ycmd should return valid JSON instead of empty HTML for 2 requests\n/load_extra_conf_file and /ignore_extra_conf_file requests currently return an empty body\nin case of success, which is not valid JSON. Instead, ycmd should return valid JSON body, for example just \"true\".\n\n", "before_files": [{"content": "# Copyright (C) 2013 Google Inc.\n#\n# This file is part of ycmd.\n#\n# ycmd is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# ycmd is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with ycmd.  If not, see <http://www.gnu.org/licenses/>.\n\nfrom __future__ import absolute_import\nfrom __future__ import unicode_literals\nfrom __future__ import print_function\nfrom __future__ import division\nfrom future import standard_library\nstandard_library.install_aliases()\nfrom builtins import *  # noqa\n\nimport atexit\nimport bottle\nimport json\nimport logging\nimport traceback\nfrom bottle import request\n\nimport ycm_core\nfrom ycmd import extra_conf_store, hmac_plugin, server_state, user_options_store\nfrom ycmd.responses import BuildExceptionResponse, BuildCompletionResponse\nfrom ycmd.request_wrap import RequestWrap\nfrom ycmd.bottle_utils import SetResponseHeader\nfrom ycmd.completers.completer_utils import FilterAndSortCandidatesWrap\n\n\n# num bytes for the request body buffer; request.json only works if the request\n# size is less than this\nbottle.Request.MEMFILE_MAX = 1000 * 1024\n\n_server_state = None\n_hmac_secret = bytes()\n_logger = logging.getLogger( __name__ )\napp = bottle.Bottle()\n\n\n@app.post( '/event_notification' )\ndef EventNotification():\n  _logger.info( 'Received event notification' )\n  request_data = RequestWrap( request.json )\n  event_name = request_data[ 'event_name' ]\n  _logger.debug( 'Event name: %s', event_name )\n\n  event_handler = 'On' + event_name\n  getattr( _server_state.GetGeneralCompleter(), event_handler )( request_data )\n\n  filetypes = request_data[ 'filetypes' ]\n  response_data = None\n  if _server_state.FiletypeCompletionUsable( filetypes ):\n    response_data = getattr( _server_state.GetFiletypeCompleter( filetypes ),\n                             event_handler )( request_data )\n\n  if response_data:\n    return _JsonResponse( response_data )\n  return _JsonResponse( {} )\n\n\n@app.post( '/run_completer_command' )\ndef RunCompleterCommand():\n  _logger.info( 'Received command request' )\n  request_data = RequestWrap( request.json )\n  completer = _GetCompleterForRequestData( request_data )\n\n  return _JsonResponse( completer.OnUserCommand(\n      request_data[ 'command_arguments' ],\n      request_data ) )\n\n\n@app.post( '/completions' )\ndef GetCompletions():\n  _logger.info( 'Received completion request' )\n  request_data = RequestWrap( request.json )\n  ( do_filetype_completion, forced_filetype_completion ) = (\n                    _server_state.ShouldUseFiletypeCompleter( request_data ) )\n  _logger.debug( 'Using filetype completion: %s', do_filetype_completion )\n\n  errors = None\n  completions = None\n\n  if do_filetype_completion:\n    try:\n      completions = ( _server_state.GetFiletypeCompleter(\n                                  request_data[ 'filetypes' ] )\n                                 .ComputeCandidates( request_data ) )\n\n    except Exception as exception:\n      if forced_filetype_completion:\n        # user explicitly asked for semantic completion, so just pass the error\n        # back\n        raise\n      else:\n        # store the error to be returned with results from the identifier\n        # completer\n        stack = traceback.format_exc()\n        _logger.error( 'Exception from semantic completer (using general): ' +\n                        \"\".join( stack ) )\n        errors = [ BuildExceptionResponse( exception, stack ) ]\n\n  if not completions and not forced_filetype_completion:\n    completions = ( _server_state.GetGeneralCompleter()\n                                 .ComputeCandidates( request_data ) )\n\n  return _JsonResponse(\n      BuildCompletionResponse( completions if completions else [],\n                               request_data.CompletionStartColumn(),\n                               errors = errors ) )\n\n\n@app.post( '/filter_and_sort_candidates' )\ndef FilterAndSortCandidates():\n  _logger.info( 'Received filter & sort request' )\n  # Not using RequestWrap because no need and the requests coming in aren't like\n  # the usual requests we handle.\n  request_data = request.json\n\n  return _JsonResponse( FilterAndSortCandidatesWrap(\n    request_data[ 'candidates'],\n    request_data[ 'sort_property' ],\n    request_data[ 'query' ] ) )\n\n\n@app.get( '/healthy' )\ndef GetHealthy():\n  _logger.info( 'Received health request' )\n  if request.query.include_subservers:\n    cs_completer = _server_state.GetFiletypeCompleter( ['cs'] )\n    return _JsonResponse( cs_completer.ServerIsHealthy() )\n  return _JsonResponse( True )\n\n\n@app.get( '/ready' )\ndef GetReady():\n  _logger.info( 'Received ready request' )\n  if request.query.subserver:\n    filetype = request.query.subserver\n    return _JsonResponse( _IsSubserverReady( filetype ) )\n  if request.query.include_subservers:\n    return _JsonResponse( _IsSubserverReady( 'cs' ) )\n  return _JsonResponse( True )\n\n\ndef _IsSubserverReady( filetype ):\n  completer = _server_state.GetFiletypeCompleter( [filetype] )\n  return completer.ServerIsReady()\n\n\n@app.post( '/semantic_completion_available' )\ndef FiletypeCompletionAvailable():\n  _logger.info( 'Received filetype completion available request' )\n  return _JsonResponse( _server_state.FiletypeCompletionAvailable(\n      RequestWrap( request.json )[ 'filetypes' ] ) )\n\n\n@app.post( '/defined_subcommands' )\ndef DefinedSubcommands():\n  _logger.info( 'Received defined subcommands request' )\n  completer = _GetCompleterForRequestData( RequestWrap( request.json ) )\n\n  return _JsonResponse( completer.DefinedSubcommands() )\n\n\n@app.post( '/detailed_diagnostic' )\ndef GetDetailedDiagnostic():\n  _logger.info( 'Received detailed diagnostic request' )\n  request_data = RequestWrap( request.json )\n  completer = _GetCompleterForRequestData( request_data )\n\n  return _JsonResponse( completer.GetDetailedDiagnostic( request_data ) )\n\n\n@app.post( '/load_extra_conf_file' )\ndef LoadExtraConfFile():\n  _logger.info( 'Received extra conf load request' )\n  request_data = RequestWrap( request.json, validate = False )\n  extra_conf_store.Load( request_data[ 'filepath' ], force = True )\n\n\n@app.post( '/ignore_extra_conf_file' )\ndef IgnoreExtraConfFile():\n  _logger.info( 'Received extra conf ignore request' )\n  request_data = RequestWrap( request.json, validate = False )\n  extra_conf_store.Disable( request_data[ 'filepath' ] )\n\n\n@app.post( '/debug_info' )\ndef DebugInfo():\n  _logger.info( 'Received debug info request' )\n\n  output = []\n  has_clang_support = ycm_core.HasClangSupport()\n  output.append( 'Server has Clang support compiled in: {0}'.format(\n    has_clang_support ) )\n\n  if has_clang_support:\n    output.append( 'Clang version: ' + ycm_core.ClangVersion() )\n\n  request_data = RequestWrap( request.json )\n  try:\n    output.append(\n        _GetCompleterForRequestData( request_data ).DebugInfo( request_data ) )\n  except Exception:\n    _logger.debug( 'Exception in debug info request: '\n                   + traceback.format_exc() )\n\n  return _JsonResponse( '\\n'.join( output ) )\n\n\n# The type of the param is Bottle.HTTPError\ndef ErrorHandler( httperror ):\n  body = _JsonResponse( BuildExceptionResponse( httperror.exception,\n                                                httperror.traceback ) )\n  hmac_plugin.SetHmacHeader( body, _hmac_secret )\n  return body\n\n# For every error Bottle encounters it will use this as the default handler\napp.default_error_handler = ErrorHandler\n\n\ndef _JsonResponse( data ):\n  SetResponseHeader( 'Content-Type', 'application/json' )\n  return json.dumps( data, default = _UniversalSerialize )\n\n\ndef _UniversalSerialize( obj ):\n  try:\n    serialized = obj.__dict__.copy()\n    serialized[ 'TYPE' ] = type( obj ).__name__\n    return serialized\n  except AttributeError:\n    return str( obj )\n\n\ndef _GetCompleterForRequestData( request_data ):\n  completer_target = request_data.get( 'completer_target', None )\n\n  if completer_target == 'identifier':\n    return _server_state.GetGeneralCompleter().GetIdentifierCompleter()\n  elif completer_target == 'filetype_default' or not completer_target:\n    return _server_state.GetFiletypeCompleter( request_data[ 'filetypes' ] )\n  else:\n    return _server_state.GetFiletypeCompleter( [ completer_target ] )\n\n\n@atexit.register\ndef ServerShutdown():\n  _logger.info( 'Server shutting down' )\n  if _server_state:\n    _server_state.Shutdown()\n    extra_conf_store.Shutdown()\n\n\ndef SetHmacSecret( hmac_secret ):\n  global _hmac_secret\n  _hmac_secret = hmac_secret\n\n\ndef UpdateUserOptions( options ):\n  global _server_state\n\n  if not options:\n    return\n\n  # This should never be passed in, but let's try to remove it just in case.\n  options.pop( 'hmac_secret', None )\n  user_options_store.SetAll( options )\n  _server_state = server_state.ServerState( options )\n\n\ndef SetServerStateToDefaults():\n  global _server_state, _logger\n  _logger = logging.getLogger( __name__ )\n  user_options_store.LoadDefaults()\n  _server_state = server_state.ServerState( user_options_store.GetAll() )\n  extra_conf_store.Reset()\n", "path": "ycmd/handlers.py"}], "after_files": [{"content": "# Copyright (C) 2013 Google Inc.\n#\n# This file is part of ycmd.\n#\n# ycmd is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# ycmd is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with ycmd.  If not, see <http://www.gnu.org/licenses/>.\n\nfrom __future__ import absolute_import\nfrom __future__ import unicode_literals\nfrom __future__ import print_function\nfrom __future__ import division\nfrom future import standard_library\nstandard_library.install_aliases()\nfrom builtins import *  # noqa\n\nimport atexit\nimport bottle\nimport json\nimport logging\nimport traceback\nfrom bottle import request\n\nimport ycm_core\nfrom ycmd import extra_conf_store, hmac_plugin, server_state, user_options_store\nfrom ycmd.responses import BuildExceptionResponse, BuildCompletionResponse\nfrom ycmd.request_wrap import RequestWrap\nfrom ycmd.bottle_utils import SetResponseHeader\nfrom ycmd.completers.completer_utils import FilterAndSortCandidatesWrap\n\n\n# num bytes for the request body buffer; request.json only works if the request\n# size is less than this\nbottle.Request.MEMFILE_MAX = 1000 * 1024\n\n_server_state = None\n_hmac_secret = bytes()\n_logger = logging.getLogger( __name__ )\napp = bottle.Bottle()\n\n\n@app.post( '/event_notification' )\ndef EventNotification():\n  _logger.info( 'Received event notification' )\n  request_data = RequestWrap( request.json )\n  event_name = request_data[ 'event_name' ]\n  _logger.debug( 'Event name: %s', event_name )\n\n  event_handler = 'On' + event_name\n  getattr( _server_state.GetGeneralCompleter(), event_handler )( request_data )\n\n  filetypes = request_data[ 'filetypes' ]\n  response_data = None\n  if _server_state.FiletypeCompletionUsable( filetypes ):\n    response_data = getattr( _server_state.GetFiletypeCompleter( filetypes ),\n                             event_handler )( request_data )\n\n  if response_data:\n    return _JsonResponse( response_data )\n  return _JsonResponse( {} )\n\n\n@app.post( '/run_completer_command' )\ndef RunCompleterCommand():\n  _logger.info( 'Received command request' )\n  request_data = RequestWrap( request.json )\n  completer = _GetCompleterForRequestData( request_data )\n\n  return _JsonResponse( completer.OnUserCommand(\n      request_data[ 'command_arguments' ],\n      request_data ) )\n\n\n@app.post( '/completions' )\ndef GetCompletions():\n  _logger.info( 'Received completion request' )\n  request_data = RequestWrap( request.json )\n  ( do_filetype_completion, forced_filetype_completion ) = (\n                    _server_state.ShouldUseFiletypeCompleter( request_data ) )\n  _logger.debug( 'Using filetype completion: %s', do_filetype_completion )\n\n  errors = None\n  completions = None\n\n  if do_filetype_completion:\n    try:\n      completions = ( _server_state.GetFiletypeCompleter(\n                                  request_data[ 'filetypes' ] )\n                                 .ComputeCandidates( request_data ) )\n\n    except Exception as exception:\n      if forced_filetype_completion:\n        # user explicitly asked for semantic completion, so just pass the error\n        # back\n        raise\n      else:\n        # store the error to be returned with results from the identifier\n        # completer\n        stack = traceback.format_exc()\n        _logger.error( 'Exception from semantic completer (using general): ' +\n                        \"\".join( stack ) )\n        errors = [ BuildExceptionResponse( exception, stack ) ]\n\n  if not completions and not forced_filetype_completion:\n    completions = ( _server_state.GetGeneralCompleter()\n                                 .ComputeCandidates( request_data ) )\n\n  return _JsonResponse(\n      BuildCompletionResponse( completions if completions else [],\n                               request_data.CompletionStartColumn(),\n                               errors = errors ) )\n\n\n@app.post( '/filter_and_sort_candidates' )\ndef FilterAndSortCandidates():\n  _logger.info( 'Received filter & sort request' )\n  # Not using RequestWrap because no need and the requests coming in aren't like\n  # the usual requests we handle.\n  request_data = request.json\n\n  return _JsonResponse( FilterAndSortCandidatesWrap(\n    request_data[ 'candidates'],\n    request_data[ 'sort_property' ],\n    request_data[ 'query' ] ) )\n\n\n@app.get( '/healthy' )\ndef GetHealthy():\n  _logger.info( 'Received health request' )\n  if request.query.include_subservers:\n    cs_completer = _server_state.GetFiletypeCompleter( ['cs'] )\n    return _JsonResponse( cs_completer.ServerIsHealthy() )\n  return _JsonResponse( True )\n\n\n@app.get( '/ready' )\ndef GetReady():\n  _logger.info( 'Received ready request' )\n  if request.query.subserver:\n    filetype = request.query.subserver\n    return _JsonResponse( _IsSubserverReady( filetype ) )\n  if request.query.include_subservers:\n    return _JsonResponse( _IsSubserverReady( 'cs' ) )\n  return _JsonResponse( True )\n\n\ndef _IsSubserverReady( filetype ):\n  completer = _server_state.GetFiletypeCompleter( [filetype] )\n  return completer.ServerIsReady()\n\n\n@app.post( '/semantic_completion_available' )\ndef FiletypeCompletionAvailable():\n  _logger.info( 'Received filetype completion available request' )\n  return _JsonResponse( _server_state.FiletypeCompletionAvailable(\n      RequestWrap( request.json )[ 'filetypes' ] ) )\n\n\n@app.post( '/defined_subcommands' )\ndef DefinedSubcommands():\n  _logger.info( 'Received defined subcommands request' )\n  completer = _GetCompleterForRequestData( RequestWrap( request.json ) )\n\n  return _JsonResponse( completer.DefinedSubcommands() )\n\n\n@app.post( '/detailed_diagnostic' )\ndef GetDetailedDiagnostic():\n  _logger.info( 'Received detailed diagnostic request' )\n  request_data = RequestWrap( request.json )\n  completer = _GetCompleterForRequestData( request_data )\n\n  return _JsonResponse( completer.GetDetailedDiagnostic( request_data ) )\n\n\n@app.post( '/load_extra_conf_file' )\ndef LoadExtraConfFile():\n  _logger.info( 'Received extra conf load request' )\n  request_data = RequestWrap( request.json, validate = False )\n  extra_conf_store.Load( request_data[ 'filepath' ], force = True )\n\n  return _JsonResponse( True )\n\n\n@app.post( '/ignore_extra_conf_file' )\ndef IgnoreExtraConfFile():\n  _logger.info( 'Received extra conf ignore request' )\n  request_data = RequestWrap( request.json, validate = False )\n  extra_conf_store.Disable( request_data[ 'filepath' ] )\n\n  return _JsonResponse( True )\n\n\n@app.post( '/debug_info' )\ndef DebugInfo():\n  _logger.info( 'Received debug info request' )\n\n  output = []\n  has_clang_support = ycm_core.HasClangSupport()\n  output.append( 'Server has Clang support compiled in: {0}'.format(\n    has_clang_support ) )\n\n  if has_clang_support:\n    output.append( 'Clang version: ' + ycm_core.ClangVersion() )\n\n  request_data = RequestWrap( request.json )\n  try:\n    output.append(\n        _GetCompleterForRequestData( request_data ).DebugInfo( request_data ) )\n  except Exception:\n    _logger.debug( 'Exception in debug info request: '\n                   + traceback.format_exc() )\n\n  return _JsonResponse( '\\n'.join( output ) )\n\n\n# The type of the param is Bottle.HTTPError\ndef ErrorHandler( httperror ):\n  body = _JsonResponse( BuildExceptionResponse( httperror.exception,\n                                                httperror.traceback ) )\n  hmac_plugin.SetHmacHeader( body, _hmac_secret )\n  return body\n\n# For every error Bottle encounters it will use this as the default handler\napp.default_error_handler = ErrorHandler\n\n\ndef _JsonResponse( data ):\n  SetResponseHeader( 'Content-Type', 'application/json' )\n  return json.dumps( data, default = _UniversalSerialize )\n\n\ndef _UniversalSerialize( obj ):\n  try:\n    serialized = obj.__dict__.copy()\n    serialized[ 'TYPE' ] = type( obj ).__name__\n    return serialized\n  except AttributeError:\n    return str( obj )\n\n\ndef _GetCompleterForRequestData( request_data ):\n  completer_target = request_data.get( 'completer_target', None )\n\n  if completer_target == 'identifier':\n    return _server_state.GetGeneralCompleter().GetIdentifierCompleter()\n  elif completer_target == 'filetype_default' or not completer_target:\n    return _server_state.GetFiletypeCompleter( request_data[ 'filetypes' ] )\n  else:\n    return _server_state.GetFiletypeCompleter( [ completer_target ] )\n\n\n@atexit.register\ndef ServerShutdown():\n  _logger.info( 'Server shutting down' )\n  if _server_state:\n    _server_state.Shutdown()\n    extra_conf_store.Shutdown()\n\n\ndef SetHmacSecret( hmac_secret ):\n  global _hmac_secret\n  _hmac_secret = hmac_secret\n\n\ndef UpdateUserOptions( options ):\n  global _server_state\n\n  if not options:\n    return\n\n  # This should never be passed in, but let's try to remove it just in case.\n  options.pop( 'hmac_secret', None )\n  user_options_store.SetAll( options )\n  _server_state = server_state.ServerState( options )\n\n\ndef SetServerStateToDefaults():\n  global _server_state, _logger\n  _logger = logging.getLogger( __name__ )\n  user_options_store.LoadDefaults()\n  _server_state = server_state.ServerState( user_options_store.GetAll() )\n  extra_conf_store.Reset()\n", "path": "ycmd/handlers.py"}]}