docs: def get_events(environment, start_response, headers):
    """
    Retrieve events
    POST body should contain a JSON encoded version of:
      { namespace: namespace_name (optional),
        stream : stream_name,
        start_time : starting_time_as_kronos_time,
        end_time : ending_time_as_kronos_time,
        start_id : only_return_events_with_id_greater_than_me,
        limit: optional_maximum_number_of_events,
        order: ResultOrder.ASCENDING or ResultOrder.DESCENDING (default
               ResultOrder.ASCENDING)
      }
    Either start_time or start_id should be specified. If a retrieval breaks
    while returning results, you can send another retrieval request and specify
    start_id as the last id that you saw. Kronos will only return events that
    occurred after the event with that id.
    """
    request_json = environment['json']
    try:
      stream = request_json['stream']
      validate_stream(stream)
    except Exception, e:
      log.exception('get_events: stream validation failed for `%s`',
                    request_json.get('stream'))
      start_response('400 Bad Request', headers)
      yield marshal.dumps({ERRORS_FIELD: [repr(e)],
                           SUCCESS_FIELD: False})
      return
  
    namespace = request_json.get('namespace', settings.default_namespace)
    limit = int(request_json.get('limit', MAX_LIMIT))
    if limit <= 0:
      events = []
    else:
      backend, configuration = router.backend_to_retrieve(namespace, stream)
      events = backend.retrieve(
        namespace,
        stream,
        long(request_json.get('start_time', 0)),
        long(request_json['end_time']),
        request_json.get('start_id'),
        configuration,
        order=request_json.get('order', ResultOrder.ASCENDING),
        limit=limit)
  
    start_response('200 OK', headers)
  
    string_buffer = StringIO()
    for event in events:
      # TODO(usmanm): Once all backends start respecting limit, remove this check.
      if limit <= 0:
        break
      if string_buffer.tell() >= settings.node.flush_size:
        yield string_buffer.getvalue()
        string_buffer.close()
        string_buffer = StringIO()
      string_buffer.write(event)
      string_buffer.write('\r\n')
      limit -= 1
    if string_buffer.tell():
      yield string_buffer.getvalue()
    string_buffer.close()
    yield ''