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