Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bad header with HTTPFound() method #212

Closed
pppierre opened this issue Jun 18, 2011 · 16 comments
Closed

Bad header with HTTPFound() method #212

pppierre opened this issue Jun 18, 2011 · 16 comments
Labels

Comments

@pppierre
Copy link

Hi,

I use the last version of Pyramid and I validate my pages with WDG. Here is an extract of my development.ini file:

[pipeline:main]
pipeline =
egg:WebError#evalerror
egg:Paste#wdg_validate
TestAgent

Now, when I use a HTTPFound() method, wdg_validate crashes. The reason seems simple: HTTPFound() no longer sets page length (Content-Length) in the header.

I think it's very easy to fix.

Patrick PIERRE

@mcdonc
Copy link
Member

mcdonc commented Jun 18, 2011

On Fri, 2011-06-17 at 23:08 -0700, pppierre wrote:

Hi,

I use the last version of Pyramid and I validate my pages with WDG. Here is an extract of my development.ini file:

[pipeline:main]
pipeline =
egg:WebError#evalerror
egg:Paste#wdg_validate
TestAgent

Now, when I use a HTTPFound() method, wdg_validate crashes. The reason seems simple: HTTPFound() no longer sets page length (Content-Length) in the header.

Without getting into details, I suspect the problem that is exposed here
will be fixed in Pyramid 1.1.

  • C

I think it's very easy to fix.

Patrick PIERRE

@pppierre
Copy link
Author

Great!

Thanks.

@pppierre pppierre reopened this Jul 23, 2011
@pppierre
Copy link
Author

I am testing Pyramid 1.1. I note the bug about HTTPFound() page length has not been fixed.

@mcdonc
Copy link
Member

mcdonc commented Sep 4, 2011

I don't know how to repeat this issue. The below script is an application, which, when visited on "/" uses HTTPFound to redirect to '/foo'. It has the WDGValidator middleware in its pipeline. When I run it, it redirects without telling me anything is particularly wrong with the intermediate redirect page. Can you help me change it to replicate the issue?

from pyramid.view import view_config
from pyramid.config import Configurator
from pyramid.response import Response
from pyramid.httpexceptions import HTTPFound
from paste.httpserver import serve
from paste.debug.wdg_validate import WDGValidateMiddleware

@view_config(route_name='redirect')
def test_page(request):
    return HTTPFound('/foo')

@view_config(route_name='foo')
def foo_page(request):
    return Response('<!DOCTYPE html><html><head></head><body>foo</body></html>')

if __name__ == '__main__':
    config = Configurator()
    config.add_route('redirect', '/')
    config.add_route('foo', '/foo')
    config.scan('__main__')
    app = config.make_wsgi_app()
    app = WDGValidateMiddleware(app)
    serve(app)

@cd34
Copy link

cd34 commented Nov 24, 2011

Ran into this tonight when working with Velruse's Twitter redirect.

It is specific to Mac (Lion - 10.7.2), Chrome (15.0.874.121), Chrome Canary (17.0.948.0 canary), Safari (5.1.1 (7534.51.22)) and Opera (11.52) are affected, Firefox 9.0 Beta and Firefox 8.0 work.

The sample code above does not trigger it, and, Velruse's Facebook redirect which is functionally equivalent doesn't have a problem. Both bound methods appear to be identical. Moving the fb_url to the Twitter code still breaks, moving the Twitter url to the Facebook Code allows it to work.

I believe this issue is still a problem internal to webob as even passing return HTTPFound(location='http://www.google.com/') breaks. Something in Velruse or Paste (since Velruse is a composite app) is sending something through to the WSGI exception handler that is causing an issue.

This is the header sent:

HTTP/1.1 302 Found
Content-Length: 265
Date: Thu, 24 Nov 2011 08:37:49 GMT
Server: PasteWSGIServer/0.5 Python/2.6.6
Location: https://api.twitter.com/oauth/authenticate?oauth_token=111111IjDFJMX94h486QfZWdMV2FgWtFMal6O2qHBk
Set-Cookie: session="111111f73eead816a4648629deb31937b3d37d94gAJKXQLOTkdB07OAl2Gtin1xAVUFdG9rZW5xAliTAAAAb2F1dGhfdG9rZW49TEFYa3dsSWpERkpNWDk0aDQ4NlFmWldkTVYyRmdXdEZNYWw2TzJxSEJrJm9hdXRoX3Rva2VuX3NlY3JldD1oVWxMamZ1ZllQTk41Y1BQSWpsRExBSnAyc3BxbkdsRDhKWXFxcXlZbU1nJm9hdXRoX2NhbGxiYWNrX2NvbmZpcm1lZD10cnVlcQNzh3EELg\075\075"; Path=/
Content-Type: text/html; charset=UTF-8
Connection: keep-alive

I need to check the RFC, but, I believe Content-Length is wrong.

@cd34
Copy link

cd34 commented Nov 24, 2011

This appears to be related to WebOb.

On Chrome/Chrome Canary/Safari/Opera, a snippet of the response looks like:

00000520 31 4d 54 67 32 4d 54 68 6c 4f 54 45 31 59 6d 4d |1MTg2MThlOTE1YmM|
00000530 77 4d 6a 42 6b 4e 44 55 77 4d 44 41 31 4d 44 49 |wMjBkNDUwMDA1MDI|
00000540 31 63 51 4e 7a 68 33 45 45 4c 67 5c 30 37 35 5c |1cQNzh3EELg\075|
00000550 30 37 35 22 0d 0a 0d 0a f4 79 ce 4e 6a 56 05 00 |075"....?y?NjV..|
00000560 42 00 00 00 42 00 00 00 00 12 1e 2f b7 f0 00 30 |B...B....../??.0|
00000570 48 76 77 b0 08 00 45 00 00 34 d4 b6 40 00 40 06 |Hvw?..E..4Զ@.@.|
00000580 00 fd 42 f4 92 e8 b8 20 d7 13 1f 90 d3 02 29 9e |.?B?.? ?...?.).|
00000590 12 09 e7 51 c0 9a 80 10 00 21 65 37 00 00 01 01 |..?Q?....!e7....|
000005a0 08 0a 90 ca c6 c3 d5 45 eb c4 f4 79 ce 4e b6 72 |...????E???y?N?r|
000005b0 05 00 7c 01 00 00 7c 01 00 00 00 30 48 76 77 b0 |..|...|....0Hvw?|
000005c0 00 12 1e 2f b7 f0 08 00 45 00 01 6e 84 30 40 00 |.../??..E..n.0@.|
000005d0 33 06 5d 49 b8 20 d7 13 42 f4 92 e8 d3 02 1f 90 |3.]I? ?.B?.??...|
000005e0 e7 51 c0 9a 29 9e 12 09 80 18 ff ff fc b2 00 00 |?Q?.).....????..|
000005f0 01 01 08 0a d5 45 eb c4 90 ca c6 bb 65 6e 64 5f |....?E??.?ƻend_|
00000600 70 6f 69 6e 74 3d 68 74 74 70 25 33 41 25 32 46 |point=http%3A%2F|

On Firefox 8/Firefox 9 beta, the same snippet looks like:

00000400 4d 77 4f 47 46 69 5a 57 59 77 4d 57 4d 34 4e 32 |MwOGFiZWYwMWM4N2|
00000410 56 69 4d 57 4e 6b 5a 6a 46 6b 4d 6d 49 79 63 51 |ViMWNkZjFkMmIycQ|
00000420 4e 7a 68 33 45 45 4c 67 5c 30 37 35 5c 30 37 35 |Nzh3EELg\075\075|
00000430 22 3b 20 5f 5f 75 74 6d 62 3d 35 34 35 32 30 31 |"; __utmb=545201|
00000440 30 35 2e 31 2e 31 30 2e 31 33 32 32 31 35 34 35 |05.1.10.13221545|
00000450 34 39 3b 20 5f 5f 75 74 6d 63 3d 35 34 35 32 30 |49; __utmc=54520|
00000460 31 30 35 0d 0a 43 6f 6e 74 65 6e 74 2d 54 79 70 |105..Content-Typ|
00000470 65 3a 20 61 70 70 6c 69 63 61 74 69 6f 6e 2f 78 |e: application/x|
00000480 2d 77 77 77 2d 66 6f 72 6d 2d 75 72 6c 65 6e 63 |-www-form-urlenc|
00000490 6f 64 65 64 0d 0a 43 6f 6e 74 65 6e 74 2d 4c 65 |oded..Content-Le|
000004a0 6e 67 74 68 3a 20 33 31 34 0d 0a 0d 0a 65 6e 64 |ngth: 314....end|
000004b0 5f 70 6f 69 6e 74 3d 68 74 74 70 25 33 41 25 32 |_point=http%3A%2|

some of the high order characters in the first response appear to be triggering it, particularly the 90 ca c6 bb prior to endpoint which should be \r\n.

@cd34
Copy link

cd34 commented Nov 24, 2011

In Velruse, providers/twitter.py

r = requests.get(REQUEST_URL, headers=oauth_request.to_header())

appears to munge the existing request.

Wrapping the request with:

save_request = copy.copy(request)
r = requests.get(REQUEST_URL, headers=oauth_request.to_header())
request = copy.copy(save_request)

Allows it to work. I suspect this isn't an issue with Pyramid/WebOb that I am running into, but, a leak in requests that is modifying request.

@cd34
Copy link

cd34 commented Nov 24, 2011

It appears to be related to HTTP 401 Authorization on the url being requested which appears to do something to the connection pool.

@cd34
Copy link

cd34 commented Nov 24, 2011

Now it gets odd:

r = requests.get(REQUEST_URL, headers=oauth_request.to_header())
print request

Merely printing request makes it work. Without that line, the connection is closed.

@mcdonc
Copy link
Member

mcdonc commented Nov 24, 2011

OK, well, if that's the case, we should continue discussion on it in the velruse issue tracker (as its not really related to Pyramid, but only to Velruse and its use of "requests"): bbangert/velruse#30

@mcdonc
Copy link
Member

mcdonc commented Nov 24, 2011

I misread the code above when I entered the last comment; "request" is still a webob request. Closing the issue above; this is still the appropriate place I guess.

@cd34
Copy link

cd34 commented Nov 25, 2011

Removed the print statement to further debug:

With:

pyramid.includes = pyramid_tm

or

[filter:tm]
use = egg:repoze.tm2#tm
commit_veto = repoze.tm:default_commit_veto

[pipeline:psflh]
pipeline = exc tm sflh

[composite:main]
use = egg:Paste#urlmap
/ = psflh
/velruse = velruse

Either configuration, when tm is called I get the reset and corrupted request object. Removing tm (on either my small test site) or the site I was developing allows the page to function as it should.

in development.ini

@cd34
Copy link

cd34 commented Nov 25, 2011

Scratch that, worked for 15 or so requests after clearing cache each time, issue recurs somewhat randomly, though, less frequent.

@cd34
Copy link

cd34 commented Nov 28, 2011

Further debugging:

blaflamme tested URL with Mac OS/X Lion + Webkit browser, page worked as expected

Executing through proxy server works. Executing same script through mod_wsgi works.

Modifying the exception handlers to print a message over 540 bytes (to avoid smart error messages) did not allow Webkit to work. Removing egg:WebError#evalerror from the pipeline (which is the only change to the .ini to make it run under mod_wsgi) makes no difference.

Webkit string of payload:

0Hvw
0Hvw
RF.P
0Hvw
0Hvw
0Hvw
0Hvw
POST /hosting/usertype HTTP/1.1
Host: pch1.mia.domain.com:8080
Connection: keep-alive
Content-Length: 32
Cache-Control: max-age=0
Origin: http://pch1.mia.domain.com:8080
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/535.10 (KHTML, like Gecko) Chrome/17.0.949.0 Safari/535.10
Content-Type: application/x-www-form-urlencoded
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
Referer: http://pch1.mia.domain.com:8080/hosting/users
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Cookie: refer=1; session="6a317289edecf03a4883078ca411b6d96d5ff8d6gAJKf7vRTkdB07RsvUcsH31xAVUHX2NzcmZ0X3ECVShkYmQzNzcxM2FkM2VkNmU0MjAwNzdhZmU0MDY0OTgxZDY2YjViMjRjcQNzh3EELg\075\075"; __utma=54520105.1650010611.1322149780.1322364299.1322367870.17; __utmc=54520105; __utmz=54520105.1322149780.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); auth_tkt="c828ddaaa030c9e4f07b1d3de7f9c50b4ed1e4ca1!userid_type:int"; auth_tkt="c828ddaaa030c9e4f07b1d3de7f9c50b4ed1e4ca1!userid_type:int"
0Hvw
0Hvw
TBh@
user_id=791&type=S&submit=Update
0Hvw
0Hvw
HTTP/1.0 404 Not Found
0Hvw
0Hvw
0Hvw

Firefox response for same request:

0Hvw
0Hvw
0Hvw
0Hvw

V-@
POST /hosting/usertype HTTP/1.1
Host: pch1.mia.domain.com:8080
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:9.0) Gecko/20100101 Firefox/9.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Referer: http://pch1.mia.domain.com:8080/hosting/users
Cookie: __utma=54520105.2073281535.1322120136.1322149004.1322154549.4; __utmz=54520105.1322120136.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); auth_tkt="9f16479ff7f100950dc16c0c06b4fc6a4ed1e4981!userid_type:int"; auth_tkt="9f16479ff7f100950dc16c0c06b4fc6a4ed1e4981!userid_type:int"
Content-Type: application/x-www-form-urlencoded
Content-Length: 32
user_id=791&type=S&submit=Update
0Hvw
4O*@
0Hvw
LO+@
kHTTP/1.0 404 Not Found
0Hvw
[O,@
kServer: PasteWSGIServer/0.5 Python/2.7.2+
Date: Sun, 27 Nov 2011 16:05:36 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 152

<title>404 Not Found</title>

404 Not Found

The resource could not be found.

0Hvw 49\@ 0Hvw 0Hvw 0Hvw

Only occurs when using paster serve --reload development.ini - using uwsgi or mod_wsgi appear to work consistently (less than 15 tests on uwsgi, over 50 tests on mod_wsgi)

This currently happens consistently for me on a Python 2.6 environment with Velruse and the /velruse/twitter/login url. In a Python 2.7 environment with Velruse, the /velruse/twitter/login works, however, if the link is embedded in a page or form submission button, the redirect created by Velruse won't work.

It consistently happens on a view created by Deform that has a form action that 404s both on 2.6 and 2.7.

Does not occur in any scenario if a proxy server is used.

Happens on multiple machines on my network and I do believe it is the same issue experienced by the original poster since the response packet does appear to be missing Content-length on webkit browsers, but, only because the response is munged.

Does not happen with installations on same OS served on the local net, so, I'm assuming this is probably a Paster or Webob induced problem triggered through Pyramid. I doubt Pyramid is creating the problem, merely the catalyst.

I believe the issue deals with the way Webkit handles form submissions by sending an RST to ensure the keepalive session is still active. Paster appears to corrupt the request rather than properly restarting. I think this might be insulated by some firewalls which will (improperly) drop the RST without EST set.

@cd34
Copy link

cd34 commented Nov 28, 2011

Replacing paste.http with cherrypy (as per mcdonc's suggestion in IRC works). Requires PasteScript>=1.7.5

[server:main]
#use = egg:Paste#http
use = egg:PasteScript#cherrypy
host = 0.0.0.0
port = 8080

@mcdonc
Copy link
Member

mcdonc commented Jan 3, 2012

I'm closing this issue, as I think it has lost all focus on one actual problem. If anyone still has bugs, please re-report them in a different place.

@mcdonc mcdonc closed this as completed Jan 3, 2012
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants