【问题标题】:NoMethodError: undefined method `bytesize' SinatraNoMethodError:未定义的方法 `bytesize' Sinatra
【发布时间】:2013-08-17 11:44:00
【问题描述】:

当我尝试通过 java 连接到我的 ruby​​ sinatra 服务器时收到错误 NoMethodError: undefined method 'bytesize'

这是我的 ruby​​ 代码,我怀疑我需要某种方法,当客户端连接时运行,但我不确定:

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");
}

【问题讨论】:

  • 通过浏览器访问 Sinatra 应用程序是否正常工作?
  • @RossPenman 是的,工作得很好
  • 您希望该 Java 代码会发生什么?您不发出任何 HTTP 请求。你为什么使用ObjectOutputStream
  • @RossPenman 我想向服务器发送文本。
  • 你不能只打开一个套接字然后开始发送数据,你需要创建一个正确的 HTTP 请求。使用此代码,您只会得到与无效请求相关的服务器错误。

标签: java ruby sinatra nomethoderror


【解决方案1】:

我猜这是因为以下代码中 Rack 中的 theory 错误,以及您的 Java 客户端调用 Ruby 服务器中的 theory 错误:

# 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 ... Sinatra 使用的,在这里:

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。

换句话说,我猜你的body是Nil,或者不兼容的Object类型,它没有#bytesize方法,因为Rack没有测试,它只是假设数据进入那个方法很好,并且纯粹基于底层引擎将方法调用传递给该对象......而不是基于user_agent。那是Rack理论 错误。

进一步排除故障,我猜想在您的 Java 代码中存在特定于 user_agent 的东西,而不是您的 Ruby 代码。甚至不是真正的 user_agent,因为您似乎没有实例化“浏览器”,而只是打开了一个套接字连接。我猜你需要通过正式请求中的 HTTP 命令、符合 RFC 的协议等来实际调用服务器......所以你需要发送一个语法正确的标头和正文。

我见过这样的事情发生在奇怪的客户端上,例如不发送正确标题的模糊爬虫,或者不发送正文而只发送标题。我会进一步进一步猜测打开 Socket 连接是不够的。您需要将标头和正文发送到服务器。我最终猜想您可能会使用类似于curlwget 的Java 库,而不仅仅是操作原始套接字。这将为您提供适当的协议聊天,并从您的 Ruby/Sinatra 端点返回您正在寻找的内容。看了一圈,发现:

cURL equivalent in JAVA

【讨论】:

  • 是的。回到你的问题,我最好这样说:哪里有一个端点叫?甚至“/”也是在 PATH_INFO 标头字段中显式调用的端点。 SinatraRack 下面没有得到任何回应。从技术上讲,这应该更优雅地失败,但它仍然可以通过使用实际的文本浏览器库来解决,例如我添加的链接。我看到马特在更仔细地阅读了您原来的问题的 cmets 后也提到了这一点。
猜你喜欢
  • 2012-08-21
  • 1970-01-01
  • 2012-04-04
  • 2010-11-10
  • 2015-07-28
  • 2014-03-15
  • 2011-08-24
  • 1970-01-01
  • 2013-04-24
相关资源
最近更新 更多