Stephen Bannasch
2007-Jan-31 06:04 UTC
[Mongrel] GET request works via curl, crashes from Java
[That subject line is of course a severe truncation!] I''ve got a REST request that works fine from curl but causes a mongrel error when executed from a Java program. This all worked with fine with rails 1.1.6 and webrick. I''m trying to update the app to rails 1.2.1 (I need working around_filters). I''m running in development mode with mongrel 1.01 running on macosx 10.4.8 w/ruby 1.8.4, rails 1.2.1. When I do the following request with curl everything appears to work fine: curl -I -X GET -H ''Accept: application/xml'' http://localhost:3000/1/offering/84/bundle/168/0 HTTP/1.1 200 OK Connection: close Date: Wed, 31 Jan 2007 04:41:24 GMT Status: 200 OK Cache-Control: no-cache Server: Mongrel 1.0.1 Content-Type: text/xml; charset=utf-8 Content-Length: 2706 However when I try what is supposed to be the same request made from a Java jnlp application mongrel reports this error: You have a nil object when you didn''t expect it! You might have expected an instance of ActiveRecord::Base. The error occurred while evaluating nil.update /usr/local/lib/ruby/gems/1.8/gems/actionpack-1.13.1/lib/action_controller/request.rb:13:in `parameters'' /usr/local/lib/ruby/gems/1.8/gems/actionpack-1.13.1/lib/action_controller/request.rb:20:in `method'' /usr/local/lib/ruby/gems/1.8/gems/actionpack-1.13.1/lib/action_controller/routing.rb:1307:in `extract_request_environment'' /usr/local/lib/ruby/gems/1.8/gems/actionpack-1.13.1/lib/action_controller/routing.rb:1256:in `recognize'' /usr/local/lib/ruby/gems/1.8/gems/rails-1.2.1/lib/dispatcher.rb:40:in `dispatch'' /usr/local/lib/ruby/gems/1.8/gems/mongrel-1.0.1/lib/mongrel/rails.rb:78:in `process'' /usr/local/lib/ruby/gems/1.8/gems/mongrel-1.0.1/lib/mongrel/rails.rb:76:in `process'' /usr/local/lib/ruby/gems/1.8/gems/mongrel-1.0.1/lib/mongrel.rb:618:in `process_client'' /usr/local/lib/ruby/gems/1.8/gems/mongrel-1.0.1/lib/mongrel.rb:617:in `process_client'' /usr/local/lib/ruby/gems/1.8/gems/mongrel-1.0.1/lib/mongrel.rb:736:in `run'' /usr/local/lib/ruby/gems/1.8/gems/mongrel-1.0.1/lib/mongrel.rb:736:in `run'' /usr/local/lib/ruby/gems/1.8/gems/mongrel-1.0.1/lib/mongrel.rb:720:in `run'' /usr/local/lib/ruby/gems/1.8/gems/mongrel-1.0.1/lib/mongrel/configurator.rb:271:in `run'' /usr/local/lib/ruby/gems/1.8/gems/mongrel-1.0.1/lib/mongrel/configurator.rb:270:in `run'' /usr/local/lib/ruby/gems/1.8/gems/mongrel-1.0.1/bin/mongrel_rails:127:in `run'' /usr/local/lib/ruby/gems/1.8/gems/mongrel-1.0.1/lib/mongrel/command.rb:211:in `run'' /usr/local/lib/ruby/gems/1.8/gems/mongrel-1.0.1/bin/mongrel_rails:243 /usr/local/lib/ruby/gems/1.8/gems/activesupport-1.4.0/lib/active_support/dependencies.rb:489:in `load'' /usr/local/lib/ruby/gems/1.8/gems/activesupport-1.4.0/lib/active_support/dependencies.rb:343:in `new_constants_in'' /usr/local/lib/ruby/gems/1.8/gems/activesupport-1.4.0/lib/active_support/dependencies.rb:489:in `load'' /usr/local/lib/ruby/gems/1.8/gems/rails-1.2.1/lib/commands/servers/mongrel.rb:60 /usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `require'' /usr/local/lib/ruby/gems/1.8/gems/activesupport-1.4.0/lib/active_support/dependencies.rb:496:in `require'' /usr/local/lib/ruby/gems/1.8/gems/activesupport-1.4.0/lib/active_support/dependencies.rb:343:in `new_constants_in'' /usr/local/lib/ruby/gems/1.8/gems/activesupport-1.4.0/lib/active_support/dependencies.rb:496:in `require'' /usr/local/lib/ruby/gems/1.8/gems/rails-1.2.1/lib/commands/server.rb:39 /usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `require'' /usr/local/lib/ruby/gems/1.8/gems/activesupport-1.4.0/lib/active_support/dependencies.rb:496:in `require'' /usr/local/lib/ruby/gems/1.8/gems/activesupport-1.4.0/lib/active_support/dependencies.rb:343:in `new_constants_in'' /usr/local/lib/ruby/gems/1.8/gems/activesupport-1.4.0/lib/active_support/dependencies.rb:496:in `require'' script/server:3 Here''s the code in request.rb: # Returns both GET and POST parameters in a single hash. def parameters @parameters ||= request_parameters.update(query_parameters).update(path_parameters).with_indifferent_access end The Java program is expecting an xml file and obviously isn''t getting what it is supposed to: org.eclipse.emf.ecore.resource.Resource$IOWrappedException: Content is not allowed in prolog. I thought it was unlikely to be helpful but I turned $mongrel_debug_client: kill -USR1 900 This appeared in the mongrel_log but nothing else: ** USR1 received, toggling $mongrel_debug_client to true I''m not able to get the Java program to log any more info about just what request it made until I can get ion touch with the programmer. Somehow I''m stuck thinking there must be a difference in the actual http requests (though their shouldn''t be). The result from the Java request using webrick in 1.2.1 is also an error and is similar to a warning in he Mongrel FAQ page: The request from curl via webrick: 127.0.0.1 - - [31/Jan/2007:00:50:43 EST] "GET /1/offering/84/bundle/168/0 HTTP/1.1" 200 2706 The request from Java via webrick: 127.0.0.1 - - [31/Jan/2007:00:51:43 EST] "GET /1/offering/84/bundle/168/0 HTTP/1.1" 500 309 The error occurs in the same place in request.rb in Webrick so this isn''t mongrel specific. Is there a way I can get mongrel to log more about the http request so I can compare the two in more detail? I was able to set a breakpoint in the rails controller method and get detailed info from rails about the request that worked. But none of my breakpoints get touched with the request that causes the error. Thanks for any help or pointers. -- - Stephen Bannasch Concord Consortium, http://www.concord.org
You can tell mongrel to go into debug mode by passing in "-B" on the command line to "mongrel_rails start". It''ll start logging requests to the console like WEBrick, and it''ll log a ton of info to log/mongrel_debug. Although, in your case, I would recommend firing up some sort of HTTP traffic sniffer. It''ll give you way more information. Live HTTP Headers in Firefox may work in your case (but only if you want headers of the conversation, apropos to its name). Wireshark works well if you''re in Linux, and Fiddler''s a good tool for Windows users. I have no clue what a Mac OS X user would use, but there''s probably something out there. On 1/31/07, Stephen Bannasch <stephen at concord.org> wrote:> [That subject line is of course a severe truncation!] > > I''ve got a REST request that works fine from curl but causes a > mongrel error when executed from a Java program. This all worked with > fine with rails 1.1.6 and webrick. I''m trying to update the app to > rails 1.2.1 (I need working around_filters). > > I''m running in development mode with mongrel 1.01 running on macosx > 10.4.8 w/ruby 1.8.4, rails 1.2.1. > > When I do the following request with curl everything appears to work fine: > > curl -I -X GET -H ''Accept: application/xml'' > http://localhost:3000/1/offering/84/bundle/168/0 > > HTTP/1.1 200 OK > Connection: close > Date: Wed, 31 Jan 2007 04:41:24 GMT > Status: 200 OK > Cache-Control: no-cache > Server: Mongrel 1.0.1 > Content-Type: text/xml; charset=utf-8 > Content-Length: 2706 > > However when I try what is supposed to be the same request made from > a Java jnlp application mongrel reports this error: > > You have a nil object when you didn''t expect it! > You might have expected an instance of ActiveRecord::Base. > The error occurred while evaluating nil.update > > /usr/local/lib/ruby/gems/1.8/gems/actionpack-1.13.1/lib/action_controller/request.rb:13:in > `parameters'' > > /usr/local/lib/ruby/gems/1.8/gems/actionpack-1.13.1/lib/action_controller/request.rb:20:in > `method'' > > /usr/local/lib/ruby/gems/1.8/gems/actionpack-1.13.1/lib/action_controller/routing.rb:1307:in > `extract_request_environment'' > > /usr/local/lib/ruby/gems/1.8/gems/actionpack-1.13.1/lib/action_controller/routing.rb:1256:in > `recognize'' > > /usr/local/lib/ruby/gems/1.8/gems/rails-1.2.1/lib/dispatcher.rb:40:in > `dispatch'' > > /usr/local/lib/ruby/gems/1.8/gems/mongrel-1.0.1/lib/mongrel/rails.rb:78:in > `process'' > > /usr/local/lib/ruby/gems/1.8/gems/mongrel-1.0.1/lib/mongrel/rails.rb:76:in > `process'' > > /usr/local/lib/ruby/gems/1.8/gems/mongrel-1.0.1/lib/mongrel.rb:618:in > `process_client'' > > /usr/local/lib/ruby/gems/1.8/gems/mongrel-1.0.1/lib/mongrel.rb:617:in > `process_client'' > /usr/local/lib/ruby/gems/1.8/gems/mongrel-1.0.1/lib/mongrel.rb:736:in `run'' > /usr/local/lib/ruby/gems/1.8/gems/mongrel-1.0.1/lib/mongrel.rb:736:in `run'' > /usr/local/lib/ruby/gems/1.8/gems/mongrel-1.0.1/lib/mongrel.rb:720:in `run'' > > /usr/local/lib/ruby/gems/1.8/gems/mongrel-1.0.1/lib/mongrel/configurator.rb:271:in > `run'' > > /usr/local/lib/ruby/gems/1.8/gems/mongrel-1.0.1/lib/mongrel/configurator.rb:270:in > `run'' > > /usr/local/lib/ruby/gems/1.8/gems/mongrel-1.0.1/bin/mongrel_rails:127:in > `run'' > > /usr/local/lib/ruby/gems/1.8/gems/mongrel-1.0.1/lib/mongrel/command.rb:211:in > `run'' > /usr/local/lib/ruby/gems/1.8/gems/mongrel-1.0.1/bin/mongrel_rails:243 > > /usr/local/lib/ruby/gems/1.8/gems/activesupport-1.4.0/lib/active_support/dependencies.rb:489:in > `load'' > > /usr/local/lib/ruby/gems/1.8/gems/activesupport-1.4.0/lib/active_support/dependencies.rb:343:in > `new_constants_in'' > > /usr/local/lib/ruby/gems/1.8/gems/activesupport-1.4.0/lib/active_support/dependencies.rb:489:in > `load'' > > /usr/local/lib/ruby/gems/1.8/gems/rails-1.2.1/lib/commands/servers/mongrel.rb:60 > /usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `require'' > > /usr/local/lib/ruby/gems/1.8/gems/activesupport-1.4.0/lib/active_support/dependencies.rb:496:in > `require'' > > /usr/local/lib/ruby/gems/1.8/gems/activesupport-1.4.0/lib/active_support/dependencies.rb:343:in > `new_constants_in'' > > /usr/local/lib/ruby/gems/1.8/gems/activesupport-1.4.0/lib/active_support/dependencies.rb:496:in > `require'' > /usr/local/lib/ruby/gems/1.8/gems/rails-1.2.1/lib/commands/server.rb:39 > /usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `require'' > > /usr/local/lib/ruby/gems/1.8/gems/activesupport-1.4.0/lib/active_support/dependencies.rb:496:in > `require'' > > /usr/local/lib/ruby/gems/1.8/gems/activesupport-1.4.0/lib/active_support/dependencies.rb:343:in > `new_constants_in'' > > /usr/local/lib/ruby/gems/1.8/gems/activesupport-1.4.0/lib/active_support/dependencies.rb:496:in > `require'' > script/server:3 > > Here''s the code in request.rb: > > # Returns both GET and POST parameters in a single hash. > def parameters > @parameters ||> request_parameters.update(query_parameters).update(path_parameters).with_indifferent_access > end > > The Java program is expecting an xml file and obviously isn''t getting > what it is supposed to: > > org.eclipse.emf.ecore.resource.Resource$IOWrappedException: Content > is not allowed in prolog. > > I thought it was unlikely to be helpful but I turned $mongrel_debug_client: > > kill -USR1 900 > > This appeared in the mongrel_log but nothing else: > > ** USR1 received, toggling $mongrel_debug_client to true > > I''m not able to get the Java program to log any more info about just > what request it made until I can get ion touch with the programmer. > > Somehow I''m stuck thinking there must be a difference in the actual > http requests (though their shouldn''t be). > > The result from the Java request using webrick in 1.2.1 is also an > error and is similar to a warning in he Mongrel FAQ page: > > The request from curl via webrick: > > 127.0.0.1 - - [31/Jan/2007:00:50:43 EST] "GET > /1/offering/84/bundle/168/0 HTTP/1.1" 200 2706 > > The request from Java via webrick: > > 127.0.0.1 - - [31/Jan/2007:00:51:43 EST] "GET > /1/offering/84/bundle/168/0 HTTP/1.1" 500 309 > > The error occurs in the same place in request.rb in Webrick so this > isn''t mongrel specific. > > Is there a way I can get mongrel to log more about the http request > so I can compare the two in more detail? > > I was able to set a breakpoint in the rails controller method and get > detailed info from rails about the request that worked. But none of > my breakpoints get touched with the request that causes the error. > > Thanks for any help or pointers. > > -- > - Stephen Bannasch > Concord Consortium, http://www.concord.org > _______________________________________________ > Mongrel-users mailing list > Mongrel-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/mongrel-users >
Stephen Bannasch
2007-Jan-31 07:26 UTC
[Mongrel] GET request works via curl, crashes from Java
>On Wed, 31 Jan 2007 01:04:16 -0500 >Stephen Bannasch <stephen at concord.org> wrote: > >> [That subject line is of course a severe truncation!] > >Go get Wireshark and run it so you can grab two captures. One for curl one for the java stuff. Then use the Analyze -> Follow TCP Stream to see what''s the difference between the two.Thanks for the suggestion. I''m compiling it now with port. I assume it''ll run in xwindows. -- - Stephen Bannasch Concord Consortium, http://www.concord.org
Olle Jonsson
2007-Jan-31 08:23 UTC
[Mongrel] GET request works via curl, crashes from Java
Eden:> Although, in your case, I would recommend firing up some sort of HTTP > traffic sniffer. It''ll give you way more information.Yes, sniff that traffic! When debugging some Rails XML-RPC problems I had (had some junk with the same names installed in my site_ruby, so the problem was only at my end), I set up a tunnel, which worked great. You see all the headers, and the bodies of the requests and responses on your screen, just like with the other tools. TcpTunnelGui [1] for proxying data to and from webservices, an application that is bundled with Apache''s SOAP package. The soap.jar is in the lib folder. Fire up the TcpTunnelGui by running: java -cp soap.jar org.apache.soap.util.net.TcpTunnelGui 3001 123.123.123.123 8081 (3001 is the local port, and 8081 is the remote port, and 123.123.123.123 is your remote IP.) [1]: http://ws.apache.org/soap/ best regards, Olle Jonsson
On Wed, 31 Jan 2007 01:04:16 -0500 Stephen Bannasch <stephen at concord.org> wrote:> [That subject line is of course a severe truncation!]Go get Wireshark and run it so you can grab two captures. One for curl one for the java stuff. Then use the Analyze -> Follow TCP Stream to see what''s the difference between the two. It''s usually really obvious then. Feel free to send me the capture files off line and I''ll look at them (but you really should learn how to do this). -- Zed A. Shaw, MUDCRAP-CE Master Black Belt Sifu http://www.zedshaw.com/ http://www.awprofessional.com/title/0321483502 -- The Mongrel Book http://mongrel.rubyforge.org/ http://www.lingr.com/room/3yXhqKbfPy8 -- Come get help.
On Wed, 31 Jan 2007 02:26:44 -0500 Stephen Bannasch <stephen at concord.org> wrote:> >On Wed, 31 Jan 2007 01:04:16 -0500 > >Stephen Bannasch <stephen at concord.org> wrote: > > > >> [That subject line is of course a severe truncation!] > > > >Go get Wireshark and run it so you can grab two captures. One for curl one for the java stuff. Then use the Analyze -> Follow TCP Stream to see what''s the difference between the two. > > Thanks for the suggestion. I''m compiling it now with port. I assume it''ll run in xwindows.Yep, but there''s a command line tool called tshark or some such that will let you grab a capture. You can build that on a server if you need to find out what''s going on with a remote box. It''s better though to do it in a controlled environment. -- Zed A. Shaw, MUDCRAP-CE Master Black Belt Sifu http://www.zedshaw.com/ http://www.awprofessional.com/title/0321483502 -- The Mongrel Book http://mongrel.rubyforge.org/ http://www.lingr.com/room/3yXhqKbfPy8 -- Come get help.
Scott Brooks
2007-Jan-31 17:31 UTC
[Mongrel] GET request works via curl, crashes from Java
On Wednesday 31 January 2007 12:26 am, Stephen Bannasch wrote:> >On Wed, 31 Jan 2007 01:04:16 -0500 > > > >Stephen Bannasch <stephen at concord.org> wrote: > >> [That subject line is of course a severe truncation!] > > > >Go get Wireshark and run it so you can grab two captures. One for curl > > one for the java stuff. Then use the Analyze -> Follow TCP Stream to see > > what''s the difference between the two. > > Thanks for the suggestion. I''m compiling it now with port. I assume it''ll > run in xwindows.tcpdump would probably work for you as well, and it''s probably already installed(unless you are on windows) tcpdump -w output.dump -s 0 -i eth0 change -i eth0 to what ever interface you want. Then you can open up the dump with wireshark on any box with a GUI. Scott Brooks
Stephen Bannasch
2007-Jan-31 19:00 UTC
[Mongrel] GET request works via curl, crashes from Java
Thanks for all the suggestions. Wireshark and tcpdump work well together. I can reproduce the problem. When a client makes a GET request and intends for my application to return a REST resource in XML format it should look like this (or derivations thereof): curl -H ''Accept: application/xml'' http://localhost:3000/1/offering/84/bundle/168/0 About 6 months ago when I first wrote the app using rails 1.1.x I had instead specified this as the header to pass to indicate a REST xml response from the app was appropriate: curl -i -H ''Content-Type: application/xml'' http://localhost:3000/1/offering/84/bundle/168/0 That spec didn''t last long (because it didn''t actually make sense: a GET should describe what it accepts), I instead documented the first method as how to get the resource. The java program that uses these resources however still used the ''Content-Type'' header when making a GET request. That worked in rails 1.1.x for two reasons: the only controller methods it was calling in this manner *ONLY* provided REST xml responses and these methods didn''t use this rails idiom: respond_to do |wants| wants.html wants.xml end Instead they always returned an xml resource. In addition the interaction between webrick|lighttpd and rails 1.1.x didn''t generate an error with this kind of request. So the flaw went undiscovered. Here''s what seems to be a problem in the webserver/rails integration, making this kind of GET request: curl -i -H ''Content-Type: application/xml'' http://localhost:3000/1/offering/84/bundle/168/0 Produces this response (the returned headers indicate success and the returned body indicates a 500 error): HTTP/1.1 200 OK Connection: close Date: Wed, 31 Jan 2007 18:24:44 GMT Content-Type: text/html Content-Length: 371 Status: 500 Internal Server Error Content-Type: text/html <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <body> <h1>Application error</h1> <p>Change this error message for exceptions thrown outside of an action (like in Dispatcher setups or broken Ruby code) in public/500.html</p> </body> Shouldn''t 500 errors be reported in the first line of the HTTP headers? Is the wrong use of a header (and I would certainly agree that using ''Content-Type'' in a GET makes no sense) reason for disallowing the request. If the answer is yes then it probably makes sense to return an error in the headers also. So my question now is: Should this incorrect use be trapped as an error? If the answer is yes is the current handling of the error correct? If the answer is no any suggestion on where I can look in the code to fix the patch or fix the problem. My specific problem now is that while we can easily update the Java program now that I''ve found the problem the application is designed to support the creation of learner portfolios and to view portfolios created they may need to be matched to the earlier jar files and of course those earlier jar files will use the wrong heder when making the REST GET request ... sigh ... I rather not have to keep using 1.1.6 much longer. Thanks again for any comments/ideas. -- - Stephen Bannasch Concord Consortium, http://www.concord.org