2015-08-06 15 views
8

Tôi có một url mà tôi đang truy cập trên một trang web có thể được di chuyển và khi điểm cuối được di chuyển, tôi cần các tham số POST/GET được áp dụng lại . Tôi đang thiếu gì để đảm bảo trình xử lý này thực hiện điều này?Python 2.7 - Trình xử lý chuyển hướng không chuyển các tham số về trực tiếp

class RedirectHandler(urllib2.HTTPRedirectHandler): 


    def http_error_301(self, req, fp, code, msg, headers): 
     result = urllib2.HTTPRedirectHandler.http_error_301(
      self, req, fp, code, msg, headers) 
     result.status = code 
     return result 

    def http_error_302(self, req, fp, code, msg, headers): 
     result = urllib2.HTTPRedirectHandler.http_error_302(
      self, req, fp, code, msg, headers) 
     result.status = code 
     return result 

Khi tôi xem lưu lượng truy cập qua fiddler, tôi nhận thấy mã thông báo được sử dụng để xác thực bị xóa.

(xin lưu ý tôi không thể sử dụng các yêu cầu về giải pháp này, nó phải là thư viện tiêu chuẩn duy nhất)

Cảm ơn bạn

+0

Địa chỉ cookie của bạn ở đâu? (hoặc thông tin phiên của bạn) – dsgdfg

+0

@SDilmac để bạn cho rằng trình xử lý cookie sẽ giải quyết vấn đề này? –

+0

True! Tất cả các dịch vụ web sử dụng cookie cos không thể lưu tất cả các hành động của khách truy cập. – dsgdfg

Trả lời

2

Câu chuyện về HTTP 1.0 và 1.1 mã trạng thái 302, 303 và 307 là một ít phức tạp. Về cơ bản bạn thấy các mong đợi và documented hành vi (bạn cũng có thể nhìn vào this answer cho mô tả dài hơn):

Việc thực hiện mặc định của phương pháp này không đúng theo RFC 2616, mà nói rằng 301 và 302 phản ứng với POST yêu cầu phải không được tự động chuyển hướng mà không cần người dùng xác nhận. Trên thực tế, trình duyệt cho phép tự động chuyển hướng các phản hồi này, thay đổi POST thành GET và triển khai mặc định sẽ tái tạo hành vi này.

Và bạn đi đúng cách, nhưng ghi đè các phương pháp sai. Đây là nguồn của urllib2.HTTPRedirectHandler.redirect_request:

def redirect_request(self, req, fp, code, msg, headers, newurl): 
    """Return a Request or None in response to a redirect. 
    ... 
    Return None if you can't but another Handler might. 
    """ 
    m = req.get_method() 
    if (code in (301, 302, 303, 307) and m in ("GET", "HEAD") 
     or code in (301, 302, 303) and m == "POST"): 
     # ... 
     newurl = newurl.replace(' ', '%20') 
     newheaders = dict((k,v) for k,v in req.headers.items() 
          if k.lower() not in ("content-length", "content-type") 
         ) 
     return Request(newurl, 
         headers=newheaders, 
         origin_req_host=req.get_origin_req_host(), 
         unverifiable=True) 
    else: 
     raise HTTPError(req.get_full_url(), code, msg, headers, fp) 

Một số quan sát ở đây. Nó không vượt qua data, do đó yêu cầu mới là GET. Bộ lọc sẽ lọc ra các tiêu đề content-lengthcontent-type, được yêu cầu cho đúng POST. Nếu thực tế, trong ví dụ của tôi req.headers là một dict trống, vì vậy tôi đã sử dụng số req.header_items() (xem unredirected_hdrs). Hơn nữa, không xử lý các chuyển hướng POST và 307.

Dưới đây là cách thực hiện trình xử lý chuyển hướng chính xác cho chuyển hướng POST và 302. Đây cũng là mô phỏng CherryPy hoàn chỉnh (làm pip install cherrypy trước).

#!/usr/bin/env python 
# -*- coding: utf-8 -*- 


import urllib2 
from urllib2 import HTTPRedirectHandler, Request 

import cherrypy 


config = { 
    'global' : { 
    'server.socket_host' : '127.0.0.1', 
    'server.socket_port' : 8080, 
    'server.thread_pool' : 8 
    } 
} 


class RedirectHandler(HTTPRedirectHandler): 

    def redirect_request(self, req, fp, code, msg, headers, newurl): 
     if code == 302 and req.get_method() == 'POST': 
     return Request(newurl, headers=dict(req.header_items()), data=req.data, 
      origin_req_host=req.get_origin_req_host(), unverifiable=True) 
     else: 
     return HTTPRedirectHandler.redirect_request(self, req, fp, code, msg, 
      headers, newurl) 


class App: 

    @cherrypy.expose 
    def index(self): 
    opener = urllib2.build_opener(RedirectHandler()) 
    return opener.open('http://localhost:8080/redirect', data='foo=bar') 

    @cherrypy.expose 
    def redirect(self, **kwargs): 
    print('Before redirect {0}'.format(kwargs)) 
    raise cherrypy.HTTPRedirect('/target', 302) 

    @cherrypy.expose 
    def target(self, **kwargs): 
    return 'Target received {0} {1}'.format(cherrypy.request.method, kwargs) 


if __name__ == '__main__': 
    cherrypy.quickstart(App(), '/', config) 
+0

Cảm ơn bạn đã phản hồi, tôi sẽ kiểm tra điều này và liên hệ lại với bạn! –

Các vấn đề liên quan