如何在 google 应用引擎 (python) 上获得流式传输 url 的响应
How to get a response for a streaming url on google app engine (python)
我正在尝试验证在线广播 url 是否正在传送音乐以及 url 是否被重定向(如果出于某种原因请求 url 错误,则会发生这种情况或不活跃)。我在这里 Fetching url in python with google app engine 找到了一些建议。但是,对于提供 Content-Type:audio/mpeg 的 url,它似乎不起作用。
在我的本地机器上使用 python 2.7.6 urllib2.urlopen 一切正常:
try:
print "begin urlopen"
url = urllib2.urlopen("http://streaming.radionomy.com/jamaican-roots-radio")
print "end urlopen"
except Exception, e:
print e
给予
begin urlopen
end urlopen
我可以从 returned object(这是一个 socket._fileobject)中读取 N 个字节并使用方法 geturl( ) 以获取流来自的实际 url(如果没有重定向,则请求 url 和检索到的资源 url 相同)
将 dev_appserver.py 用于 google appengine 时会出现问题(我还没有部署)。调用从不 returns:
begin urlopen
WARNING 2015-06-12 14:31:43,599 urlfetch_stub.py:504] Stripped prohibited headers from URLFetch request: ['Host']
和 "end urlopen" 永远不会打印。
我理解警告错误,所以我切换(按照上面 link 中的建议)到 urlfetch:
try:
print "begin fetch"
url = urlfetch.fetch("http://streaming.radionomy.com/jamaican-roots-radio")
print "end fetch"
except Exception, e:
print e
给予
begin
警告消失了,但调用也没有 return。
对于一个普通的网页url,一切都符合预期。我猜问题出在从未完成的响应 object 上。同时使用
urlfetch.set_default_fetch_deadline(5)
没有改变这种情况,可能是因为数据是从服务器连续流式传输的(因此没有调用超时??)。
我也尝试了低级别 httplib.HTTPConnection,但是在发出请求后 getresponse() 函数永远不会 returns。
就我的目的而言,回复 header 就足够了。但是在服务器上(不在我的控制之下)HEAD 方法没有实现(尽管在 Access-Control-Allow-Methods 中列出,因为它可以从浏览器中看到)
curl -X HEAD -i http://streaming.radionomy.com/jamaican-roots-radio
HTTP/1.0 501 Not Implemented
我没有在 Whosebug 上找到任何关于流 url 的问题,除了这个
。不幸的是,建议的回复对我不是很有帮助 ("Using Twitter's 'standard' API")。
我能解决这个问题吗?
更新
在 google appengine 上(不是在上面的 dev_appserver.py 上)问题是相似的:
- 最后期限为 5 秒
Deadline exceeded while waiting for HTTP response from URL...
- 截止时间为 60 秒
Traceback (most recent call last):
File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/runtime/wsgi.py", line 267, in Handle result = handler(dict(self._environ), self._StartResponse)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.3/webapp2.py", line 1505, in call
rv = self.router.dispatch(request, response)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.3/webapp2.py", line 1253, in default_dispatcher
return route.handler_adapter(request, response)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.3/webapp2.py", line 1077, in call
return handler.dispatch()
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.3/webapp2.py", line 545, in dispatch
return method(*args, **kwargs)
File "/base/data/home/apps/s~radiosnoozers/3.384985169499124712/controllers/checkurl.py", line 80, in get
print e
File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/runtime/request_environment.py", line 94, in write
self._request.errors.write(data)
File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/api/logservice/logservice.py", line 287, in write
self._write(line)
File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/api/logservice/logservice.py", line 307, in _write
if self._request != logsutil.RequestID():
DeadlineExceededError
遵守超时,使用 allow_truncated=True 没有区别。无论如何,无法访问响应...
我真的不知道发生了什么,但感谢您的建议。
如果 URL 是基于 HTTP 的流端点,则可能是使用 http 范围请求完成的。这意味着,如果您只想获取流的特定字节范围(比如前几个字节),则需要告诉 urlfetch 这样做。您可以通过指定 request headers for urlfetch 并指定字节范围(例如 headers={'Range': 'bytes=0-299'})
UrlFetch 用于从 URL 中获取有限资源,并且通常不能很好地处理流。它正在等待请求终止。我相信端点一般不能很好地处理 Range
请求。当我的浏览器点击该流时,请查看 headers(顺便说一句,很棒的流):
GET http://streaming.radionomy.com/jamaican-roots-radio HTTP/1.1
Host: streaming.radionomy.com
Proxy-Connection: keep-alive
Accept-Encoding: identity;q=1, *;q=0
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.124 Safari/537.36
Accept: */*
Referer: http://streaming.radionomy.com/jamaican-roots-radio
Accept-Language: en-US,en;q=0.8
Cookie: gsScrollPos=
Range: bytes=0-
现在看看回复:
HTTP/1.1 200 OK
Accept-Ranges: none
icy-br: 128
ice-audio-info: bitrate=128;samplerate=44100;channels=2
icy-br: 128
icy-description: Radio Online producida en Colombia. Al aire: Ska Reggae Rocksteady jamaiquino las 24 horas los 7 días a la semana. http://www.jamaicanroots.com.co/
icy-genre: Jamaican
icy-name: JamaicanRootsRadio
icy-pub: 1
icy-url: http://www.jamaicanroots.com.co
Server: Icecast 2.3.3-kh8
Cache-Control: no-cache, no-store
Pragma: no-cache
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Origin, Accept, X-Requested-With, Content-Type
Access-Control-Allow-Methods: GET, OPTIONS, HEAD
Expires: Mon, 26 Jul 1997 05:00:00 GMT
Transfer-Encoding: chunked
Content-Type: audio/mpeg
Date: Wed, 17 Jun 2015 19:35:42 GMT
Via: **[my proxy here]**
Connection: keep-alive
Proxy-Connection: keep-alive
事实上,正如我上面所暗示的,我认为流本身不能很好地与 HTTP 兼容。如果您尝试 运行 通过 CURL 的等效请求并指定 Range: bytes=0-100
,您会注意到范围请求 header 未得到遵守,它会流式传输永远。
因此,您似乎需要使用 Managed VM or Compute Engine 实例来手动打开和关闭连接。
我正在尝试验证在线广播 url 是否正在传送音乐以及 url 是否被重定向(如果出于某种原因请求 url 错误,则会发生这种情况或不活跃)。我在这里 Fetching url in python with google app engine 找到了一些建议。但是,对于提供 Content-Type:audio/mpeg 的 url,它似乎不起作用。
在我的本地机器上使用 python 2.7.6 urllib2.urlopen 一切正常:
try:
print "begin urlopen"
url = urllib2.urlopen("http://streaming.radionomy.com/jamaican-roots-radio")
print "end urlopen"
except Exception, e:
print e
给予
begin urlopen
end urlopen
我可以从 returned object(这是一个 socket._fileobject)中读取 N 个字节并使用方法 geturl( ) 以获取流来自的实际 url(如果没有重定向,则请求 url 和检索到的资源 url 相同)
将 dev_appserver.py 用于 google appengine 时会出现问题(我还没有部署)。调用从不 returns:
begin urlopen
WARNING 2015-06-12 14:31:43,599 urlfetch_stub.py:504] Stripped prohibited headers from URLFetch request: ['Host']
和 "end urlopen" 永远不会打印。
我理解警告错误,所以我切换(按照上面 link 中的建议)到 urlfetch:
try:
print "begin fetch"
url = urlfetch.fetch("http://streaming.radionomy.com/jamaican-roots-radio")
print "end fetch"
except Exception, e:
print e
给予
begin
警告消失了,但调用也没有 return。
对于一个普通的网页url,一切都符合预期。我猜问题出在从未完成的响应 object 上。同时使用
urlfetch.set_default_fetch_deadline(5)
没有改变这种情况,可能是因为数据是从服务器连续流式传输的(因此没有调用超时??)。 我也尝试了低级别 httplib.HTTPConnection,但是在发出请求后 getresponse() 函数永远不会 returns。
就我的目的而言,回复 header 就足够了。但是在服务器上(不在我的控制之下)HEAD 方法没有实现(尽管在 Access-Control-Allow-Methods 中列出,因为它可以从浏览器中看到)
curl -X HEAD -i http://streaming.radionomy.com/jamaican-roots-radio
HTTP/1.0 501 Not Implemented
我没有在 Whosebug 上找到任何关于流 url 的问题,除了这个 。不幸的是,建议的回复对我不是很有帮助 ("Using Twitter's 'standard' API")。
我能解决这个问题吗?
更新
在 google appengine 上(不是在上面的 dev_appserver.py 上)问题是相似的:
- 最后期限为 5 秒
Deadline exceeded while waiting for HTTP response from URL...
- 截止时间为 60 秒
Traceback (most recent call last):
File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/runtime/wsgi.py", line 267, in Handle result = handler(dict(self._environ), self._StartResponse)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.3/webapp2.py", line 1505, in call rv = self.router.dispatch(request, response)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.3/webapp2.py", line 1253, in default_dispatcher return route.handler_adapter(request, response)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.3/webapp2.py", line 1077, in call return handler.dispatch()
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.3/webapp2.py", line 545, in dispatch return method(*args, **kwargs)
File "/base/data/home/apps/s~radiosnoozers/3.384985169499124712/controllers/checkurl.py", line 80, in get print e
File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/runtime/request_environment.py", line 94, in write self._request.errors.write(data)
File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/api/logservice/logservice.py", line 287, in write self._write(line)
File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/api/logservice/logservice.py", line 307, in _write if self._request != logsutil.RequestID():
DeadlineExceededError
遵守超时,使用 allow_truncated=True 没有区别。无论如何,无法访问响应...
我真的不知道发生了什么,但感谢您的建议。
如果 URL 是基于 HTTP 的流端点,则可能是使用 http 范围请求完成的。这意味着,如果您只想获取流的特定字节范围(比如前几个字节),则需要告诉 urlfetch 这样做。您可以通过指定 request headers for urlfetch 并指定字节范围(例如 headers={'Range': 'bytes=0-299'})
UrlFetch 用于从 URL 中获取有限资源,并且通常不能很好地处理流。它正在等待请求终止。我相信端点一般不能很好地处理 Range
请求。当我的浏览器点击该流时,请查看 headers(顺便说一句,很棒的流):
GET http://streaming.radionomy.com/jamaican-roots-radio HTTP/1.1
Host: streaming.radionomy.com
Proxy-Connection: keep-alive
Accept-Encoding: identity;q=1, *;q=0
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.124 Safari/537.36
Accept: */*
Referer: http://streaming.radionomy.com/jamaican-roots-radio
Accept-Language: en-US,en;q=0.8
Cookie: gsScrollPos=
Range: bytes=0-
现在看看回复:
HTTP/1.1 200 OK
Accept-Ranges: none
icy-br: 128
ice-audio-info: bitrate=128;samplerate=44100;channels=2
icy-br: 128
icy-description: Radio Online producida en Colombia. Al aire: Ska Reggae Rocksteady jamaiquino las 24 horas los 7 días a la semana. http://www.jamaicanroots.com.co/
icy-genre: Jamaican
icy-name: JamaicanRootsRadio
icy-pub: 1
icy-url: http://www.jamaicanroots.com.co
Server: Icecast 2.3.3-kh8
Cache-Control: no-cache, no-store
Pragma: no-cache
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Origin, Accept, X-Requested-With, Content-Type
Access-Control-Allow-Methods: GET, OPTIONS, HEAD
Expires: Mon, 26 Jul 1997 05:00:00 GMT
Transfer-Encoding: chunked
Content-Type: audio/mpeg
Date: Wed, 17 Jun 2015 19:35:42 GMT
Via: **[my proxy here]**
Connection: keep-alive
Proxy-Connection: keep-alive
事实上,正如我上面所暗示的,我认为流本身不能很好地与 HTTP 兼容。如果您尝试 运行 通过 CURL 的等效请求并指定 Range: bytes=0-100
,您会注意到范围请求 header 未得到遵守,它会流式传输永远。
因此,您似乎需要使用 Managed VM or Compute Engine 实例来手动打开和关闭连接。