2016-02-27 126 views
1

我正在嘗試構建一個反向代理以與某些API(如Twitter,Github,Instagram)進行對話,然後我可以使用反向代理與任何API進行通信(客戶端)應用程序(將其想像爲API管理器)。Python-Twisted:反向代理到HTTPS API:無法連接

此外,我正在使用LXC容器來做到這一點。

例如,這裏是最簡單的,我從在被扭曲文檔的例子砍死代碼:

from twisted.internet import reactor 
from twisted.web import proxy, server 
from twisted.python.log import startLogging 
from sys import stdout 
startLogging(stdout) 

site = server.Site(proxy.ReverseProxyResource('https://api.github.com/users/defunkt', 443, b'')) 
reactor.listenTCP(8080, site) 
reactor.run() 

當我做容器內捲曲,我得到一個有效的請求(這意味着我得到適當的JSON響應)。

這是我如何使用curl命令:

curl https://api.github.com/users/defunkt 

,這裏是輸出我得到:

{ 
    "login": "defunkt", 
    "id": 2, 
    "avatar_url": "https://avatars.githubusercontent.com/u/2?v=3", 
    "gravatar_id": "", 
    "url": "https://api.github.com/users/defunkt", 
    "html_url": "https://github.com/defunkt", 
    "followers_url": "https://api.github.com/users/defunkt/followers", 
    "following_url": "https://api.github.com/users/defunkt/following{/other_user}", 
    "gists_url": "https://api.github.com/users/defunkt/gists{/gist_id}", 
    "starred_url": "https://api.github.com/users/defunkt/starred{/owner}{/repo}", 
    "subscriptions_url": "https://api.github.com/users/defunkt/subscriptions", 
    "organizations_url": "https://api.github.com/users/defunkt/orgs", 
    "repos_url": "https://api.github.com/users/defunkt/repos", 
    "events_url": "https://api.github.com/users/defunkt/events{/privacy}", 
    "received_events_url": "https://api.github.com/users/defunkt/received_events", 
    "type": "User", 
    "site_admin": true, 
    "name": "Chris Wanstrath", 
    "company": "GitHub", 
    "blog": "http://chriswanstrath.com/", 
    "location": "San Francisco", 
    "email": "[email protected]", 
    "hireable": true, 
    "bio": null, 
    "public_repos": 107, 
    "public_gists": 280, 
    "followers": 15153, 
    "following": 208, 
    "created_at": "2007-10-20T05:24:19Z", 
    "updated_at": "2016-02-26T22:34:27Z" 
} 

然而,當我嘗試通過Firefox中使用獲取代理:

http://10.5.5.225:8080/

我得到:「無法連接」

這是我扭日誌是什麼樣子:

2016-02-27 [-] Log opened.

2016-02-27 [-] Site starting on 8080

2016-02-27 [-] Starting factory

2016-02-27 [-] Starting factory

2016-02-27 [-] "10.5.5.225" - - [27/Feb/2016: +0000] "GET/HTTP/1.1" 501 26 "-" "Mozilla/5.0 (X11; Debian; Linux x86_64; rv:44.0) Gecko/20100101 Firefox/44.0"

2016-02-27 [-] Stopping factory

如何使用Twisted來進行API調用(大多數API是HTTPS現在反正),並得到所需要的反應(基本上,什麼是「200」響應/ JSON應該是)?

我試圖尋找這個問題:Convert HTTP Proxy to HTTPS Proxy in Twisted

但它並沒有從編碼點的視圖多大意義(或提及關於反向代理的任何東西)。

**編輯:我也嘗試過使用切換了HTTPS API調用一個普通HTTP調用:

curl http[colon][slash][slash]openlibrary[dot]org[slash]authors[slash]OL1A.json

(URL上面已被格式化,以避免鏈路衝突的問題)

然而,我的瀏覽器仍然出現同樣的錯誤(如上所述)。

** EDIT2:我已經嘗試運行你的代碼,但我得到這個錯誤:

Error-screenshot

如果你看一下圖片,你會看到錯誤的(當運行代碼時):

builtins.AttributeError: 'str' object has no attribute 'decode'

+0

當我運行這個例子時,'curl'和Firefox都會說「無法連接」,所以我不知道你在做什麼來獲得正確的JSON響應。你是否按照書面形式運行代碼示例? – Glyph

+0

哇,你是Twisted的創始人,很高興認識你,先生!我正在運行代碼:'python3 file.py'。就輸出而言,我正在編輯我的問題,以便說明如何使用捲曲和輸出。這可能是因爲你被github API限制了速度(沒有API密鑰的公共調用有一些限制),但是我成功設法獲得了JSON響應。 – coolpy

+0

也很高興見到你。感謝您使用Twisted :)。現在你已經明確了你如何運行你的命令,我可以回答它... – Glyph

回答

3

如果你讀了API documentation for ReverseProxyResource,你會看到的__init__的簽名是:

def __init__(self, host, port, path, reactor=reactor): 

和「host」被記錄爲「要代理的Web服務器的主機」。

所以你傳遞一個URI,Twisted需要一個主機。

更糟糕的是,ReverseProxyResource是專爲在Web服務器上本地使用,並且不相當支持https://網址開箱。

確實有一個(非常有限)可擴展性掛鉤,但 - proxyClientFactoryClass - 和ReverseProxyResource沒有你需要開箱的事道歉,我會告訴你如何用它來擴展ReverseProxyResource添加https://支持所以你可以使用GitHub API :)。

from twisted.web import proxy, server 
from twisted.logger import globalLogBeginner, textFileLogObserver 
from twisted.protocols.tls import TLSMemoryBIOFactory 
from twisted.internet import ssl, defer, task, endpoints 
from sys import stdout 
globalLogBeginner.beginLoggingTo([textFileLogObserver(stdout)]) 

class HTTPSReverseProxyResource(proxy.ReverseProxyResource, object): 
    def proxyClientFactoryClass(self, *args, **kwargs): 
     """ 
     Make all connections using HTTPS. 
     """ 
     return TLSMemoryBIOFactory(
      ssl.optionsForClientTLS(self.host.decode("ascii")), True, 
      super(HTTPSReverseProxyResource, self) 
      .proxyClientFactoryClass(*args, **kwargs)) 
    def getChild(self, path, request): 
     """ 
     Ensure that implementation of C{proxyClientFactoryClass} is honored 
     down the resource chain. 
     """ 
     child = super(HTTPSReverseProxyResource, self).getChild(path, request) 
     return HTTPSReverseProxyResource(child.host, child.port, child.path, 
             child.reactor) 

@task.react 
def main(reactor): 
    import sys 
    forever = defer.Deferred() 
    myProxy = HTTPSReverseProxyResource('api.github.com', 443, 
             b'/users/defunkt') 
    myProxy.putChild("", myProxy) 
    site = server.Site(myProxy) 
    endpoint = endpoints.serverFromString(
     reactor, 
     dict(enumerate(sys.argv)).get(1, "tcp:8080:interface=127.0.0.1") 
    ) 
    endpoint.listen(site) 
    return forever 

如果你運行這個,curl http://localhost:8080/應該做你的期望。

我冒昧地將你的Twisted代碼現代化了一些; endpoints而不是listenTCP,logger而不是twisted.python.logreact,而不是自己啓動反應器。

怪異的小putChild片末出現,因爲當我們通過b"https://stackoverflow.com/users/defunkt"的路徑,這意味着對於/的請求會導致客戶端請求/users/defunkt/(注意尾隨斜線),這是一個404 GitHub的API 。如果我們明確地將空子段路徑代理爲好像它沒有尾部段,我相信它會做你期望的。

請注意:從純文本HTTP代理到加密的HTTPS可以極其危險,所以我添加了一個默認這裏只有本地主機,監聽接口。如果您的字節通過實際網絡傳輸,則應確保使用TLS正確加密它們。

+0

謝謝你的詳細解答先生。我首先想說的是,沒有必要爲軟件不能開箱就道歉,但沒有解決我的明確使用案例不是任何人的錯誤:)我成功地能夠運行代碼,但是我得到一個錯誤,我將在上面的輸入中作爲編輯/圖像粘貼。我試圖解決它,因爲我認爲這是python3的一個字節/字符串問題,但目前爲止沒有運氣。 – coolpy

+0

由於我的分數低,我不能滿足您的答案,但我將其標記爲選定的答案。 – coolpy