2017-05-09 225 views
1

我对模块请求返回的HTTP标头有问题。请求HTTP标头

我用下面的代码:

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

response = requests.get("http://www.google.co.il",proxies={'http': '','https':''}) 

data = response.text 
# response.text returns the appropriate html code 
# (<!doctype html><html dir="rtl" itemscope=""....) 

if response.status_code == requests.codes.ok: 
    # How do I send those headers to the conn (browser) 
    print "HEADERS: " + str(response.headers) 
    conn.send(data) 

我试图发送一个GET请求到www.google.co.il,并传送到浏览器的响应(在我打电话的例子它“conn”)。问题在于浏览器不会显示收到的HTML代码,而是收到ERR_EMPTY_RESPONSE。 在响应标头是:

HEADERS: {'Content-Length': '5451', 'X-XSS-Protection': '1; mode=block', 'Content-Encoding': 'gzip', 'Set-Cookie': 'NID=103=RJzu4RTCNxkh-75dvKBHx-_jen9M8iPes_AdOIQqzBVZ0VPTz1PlQaAVLpwYOmxZlTKmcogiDb1VoY__Es0HqSNwlkmHl3SuBZC8_8XUfqh1PzdWTjrXRnB4S738M1lm; expires=Wed, 08-Nov-2017 10:05:46 GMT; path=/; domain=.google.co.il; HttpOnly', 'Expires': '-1', 'Server': 'gws', 'Cache-Control': 'private, max-age=0', 'Date': 'Tue, 09 May 2017 10:05:46 GMT', 'P3P': 'CP="This is not a P3P policy! See https://www.google.com/support/accounts/answer/151657?hl=en for more info."', 'Content-Type': 'text/html; charset=windows-1255', 'X-Frame-Options': 'SAMEORIGIN'} 

有人告诉我,问题是,我不发送任何头到浏览器。这真的是问题吗?还有其他建议吗?如果这是问题,我该如何将适当的标题发送给浏览器?

编辑:我忘了提及通过代理服务器的连接是 。

任何帮助将是伟大的!

非常感谢Yahli。

+1

什么是'conn'?套接字? –

+0

是的,'conn'是一个插座。 –

+1

有点像拦截代理权吗?您必须向浏览器发送完整的HTTP响应,而不仅仅是正文。如果您使用套接字,则可以跳过“请求”并使用“套接字”发送HTTP请求。如果你坚持使用'requests',你必须从'response'对象构造头部。 –

回答

2

我找不到任何关于歌厅在requests文档的原始HTTP响应(不response.raw)任何东西,所以我写了一个函数:

def http_response(response): 
    return 'HTTP/1.1 {} {}\r\n{}\r\n\r\n{}'.format(
     response.status_code, response.reason , 
     '\r\n'.join(k + ': ' + v for k, v in response.headers.items()), 
     response.content 
    ) 

我通过Firefox的HTTP代理服务器设置为localhost测试它:端口(带一个端口监听套接字),它工作正常。

或者,您可以从conn.recv获取主机,向该主机打开一个新套接字并发送数据。示例:

data = conn.recv(1024) 
host = [ l.split(':')[1].strip() for l in data.splitlines() if l.startswith('Host:') ] 
if len(host) : 
    cli = socket.socket() 
    cli.connect((host[0], 80)) 
    cli.send(data) 
    response = '' 
    while True : 
     data = cli.recv(1024) 
     if not data.strip() : 
      break 
     response += data 
    conn.send(response) 
    cli.close() 

其中conn是连接到Web浏览器。这只是一个简单的例子,假设你只有HTTP请求(端口80)。有很多优化的空间

+0

不幸的是,当我试图连接到'www.google.com'时,我在浏览器中收到此错误:ERR_TUNNEL_CONNECTION_FAILED(与其他任何HTTP/s相同),并且不显示正确的网站。我确实收到了正确的html转储文件。任何想法为什么发生这种情况? (我只会在5小时内赞成你,我已经超过了我的最大投票数lol) –

+1

我不能确定,除非我看到你的代码,但如果你正在构建一个intecepting代理,这是一个ssl问题。谷歌只使用HTTPS,你应该sslwrap你的套接字(创建一个证书,将其添加到信任的权威等)。尝试连接到端口80上的stackoverflow,并让我知道会发生什么 –

+0

这是我的完整代码:[pastebin](https://pastebin.com/TtmaDLAs)。如果你能帮我解决这个特定的问题,我会很棒!代码从_https函数中的类Server中获取。关于你说的话,我认为模块请求已经处理过了,我应该创建一个请求会话吗? –