NoMethodError: неопределенный метод `bytesize 'Синатры

Я получаю сообщение об ошибке NoMethodError: undefined method 'bytesize', когда пытаюсь подключиться к моему серверу ruby ​​sinatra через java.

Это мой рубиновый код, я подозреваю, что мне нужен какой-то метод, который запускается, когда клиент подключается, но я не уверен:

require 'sinatra'

get '/hello' do
'this page displays hello'
end

get '/' do
'this page is the main page'
end

А вот код моего java-приложения:

private static Socket connect;
private static OutputStream output;
private static InputStream input;

public static void main(String[] args) throws IOException {
    System.out.println("Connecting...");
    connect = new Socket(InetAddress.getByName("localhost"), 4567);
    System.out.println("Connected to: " + connect.getInetAddress().getHostName());

    output = new ObjectOutputStream(connect.getOutputStream());
    output.flush();

    //input = new ObjectInputStream(connect.getInputStream());
    System.out.println("Streams ready");
}

person Cj1m    schedule 17.08.2013    source источник
comment
Правильно ли работает приложение Sinatra при доступе к нему через браузер?   -  person Alyssa Ross    schedule 17.08.2013
comment
@RossPenman Да, отлично работает   -  person Cj1m    schedule 17.08.2013
comment
Что вы ожидаете от этого кода Java? Вы не делаете никаких HTTP-запросов. А почему вы используете ObjectOutputStream?   -  person matt    schedule 17.08.2013
comment
@RossPenman Я хочу отправить текст на сервер.   -  person Cj1m    schedule 17.08.2013
comment
Вы не можете просто открыть сокет и начать отправлять такие данные, вам нужно создать правильный HTTP-запрос. С помощью этого кода вы просто получаете ошибки сервера, связанные с недопустимыми запросами.   -  person matt    schedule 17.08.2013


Ответы (1)


Я предполагаю, что это происходит из-за ошибки theory в Rack в следующем коде в сочетании с ошибкой theory при вызове клиента Java сервера Ruby:

# Return the bytesize of String; uses String#size under Ruby 1.8 and
# String#bytesize under 1.9.
if ''.respond_to?(:bytesize)
  def bytesize(string)
    string.bytesize
  end
else
  def bytesize(string)
    string.size
  end
end
module_function :bytesize

Это находится в файле <rack>lib/rack/utils.rb ..., который использует Синатра, здесь:

headers["Content-Length"] = body.inject(0) { |l, p| l + Rack::Utils.bytesize(p) }.to_s

Это находится в файле <sinatra>lib/sinatra/base.rb в методе #finish, внутри проверки, которая проверяет calculate_content_length?

... в любом случае, в методе #bytesize нет проверки, является ли string Nil ... он просто проверяет, поддерживает ли сам движок Ruby #bytesize.

Другими словами, я предполагаю, что ваше тело Nil или несовместимый тип объекта, у которого нет метода #bytesize, поскольку Rack не тестирует, он просто предполагает, что данные, поступающие в этот метод, хороши, и передает метод вызвать этот объект, основываясь исключительно на базовом движке ... а не на user_agent. Это теоретическая ошибка Rack.

При дальнейшем устранении неполадок я предполагаю, что в вашем Java-коде есть что-то специфичное для user_agent, а не ваш Ruby-код. И даже не по-настоящему user_agent, потому что вы, кажется, не создаете экземпляр «браузера», а просто открываете соединение с сокетом. Я предполагаю, что вам действительно нужно вызывать сервер через HTTP-команды в формальном запросе, протоколе, совместимом с RFC, и т. Д., Поэтому вам нужно отправить синтаксически правильный заголовок и тело.

Я видел, как такое происходит со странными клиентами, такими как неясные сканеры, которые не отправляют правильные заголовки или отправляют не тело, а только заголовки. Далее я предполагаю, что открытия соединения Socket недостаточно. Вам нужно отправить на сервер заголовки и тело. Наконец, я бы предположил, что вы, вероятно, могли бы использовать библиотеку Java, которая похожа на curl или wget, а не просто манипулировать необработанным сокетом. Это сделает за вас правильную болтовню по протоколу и просто вернет вам то, что вы ищете, от конечных точек Ruby / Sinatra. Немного осмотревшись, я обнаружил:

эквивалент cURL в JAVA

person digitalextremist    schedule 17.08.2013
comment
Ага. Вернувшись к вашему вопросу, я могу лучше всего сформулировать его так: где называется конечная точка? Даже / - это конечная точка, которая явно вызывается в поле заголовка PATH_INFO. Sinatra и Rack внизу, которым нечего создавать для ответа. Технически это должно быть более элегантно, но все же решаемо с помощью реальной библиотеки текстового браузера, например, по добавленной мной ссылке. Я вижу, что Мэтт также упомянул об этом после более внимательного прочтения комментариев к вашему исходному вопросу. - person digitalextremist; 17.08.2013