Python. HTTP响应中缺少状态码。

huangapple go评论49阅读模式
英文:

Python. Status code missing in HTTP response

问题

I want to get audio streaming data from server using Python.

I try simple request to audio stream url using urllib:

req = urllib.request.Request(<url>)

but i get exception:

http.client.BadStatusLine: Uª¨Ì5¦`

It looks like server responses and send data without http header including Status code.

Is there any way to get and process response in this case?

Also it is worth to mention results i got to request this URL with clients:

  1. Curl:

curl "http://<server>:81/audiostream.cgi?user=<user>&pwd=<password>&streamid=0&filename=" curl: (1) Received HTTP/0.9 when not allowed

The workaround is use --http0.9 switch.

  1. Chrome/Chromium based browsers shows:

ERR_INVALID_HTTP_RESPONSE

  1. Mozilla Firefox can correctly fetch this data as binary

Screenshot

英文:

I want to get audio streaming data from server using Python.

I try simple request to audio stream url using urllib:

req = urllib.request.Request(<url>)

but i get exception:

http.client.BadStatusLine: Uª¨Ì5¦`

It looks like server responses and send data without http header including Status code.

Is there any way to get and process response in this case?

Also it is worth to mention results i got to request this URL with clients:

  1. Curl:

curl
"http://<server>:81/audiostream.cgi?user=<user>&pwd=<password>&streamid=0&filename="
curl: (1) Received HTTP/0.9 when not allowed

The workaround is use --http0.9 switch.

  1. Chrome/Chromium based browsers shows:

ERR_INVALID_HTTP_RESPONSE

  1. Mozilla Firefox can correctly fetch this data as binary

Screenshot

答案1

得分: 0

你试过在发送请求时包含 User-Agent 头部吗?有时这可能是由于网页抓取检测而引起的。

import urllib2

opener = urllib2.build_opener()

headers = {
  'User-Agent': 'Mozilla/5.0 (Windows NT 5.1; rv:10.0.1) Gecko/20100101 Firefox/10.0.1',
}

opener.addheaders = headers.items()
response = opener.open(<url>)
英文:

Have you tried including User-Agent header when doing this request? Sometimes this can be caused by a web-scraping detection.

import urllib2

opener = urllib2.build_opener()

headers = {
  &#39;User-Agent&#39;: &#39;Mozilla/5.0 (Windows NT 5.1; rv:10.0.1) Gecko/20100101 Firefox/10.0.1&#39;,
}

opener.addheaders = headers.items()
response = opener.open(&lt;url&gt;)

答案2

得分: 0

HTTP 0.9 是最简单的 HTTP 协议:

> 客户端发送一个由 ASCII 字符组成的一行文档请求,以 CR LF(回车,换行)对终止。
> 此请求由单词 "GET"、一个空格、文档地址组成,当它们是用来建立连接的坐标时,省略了 "http:"、主机和端口部分。
> 对于简单的 GET 请求,响应是一条超文本标记语言(HTML)消息。这是一系列 ASCII 字符的字节流。

来源

因此,您的服务器未发送有效的 HTTP 0.9 响应,因为它不是 HTML。Chrome(等等)有权拒绝它,尽管在实践中它可能甚至不支持 HTTP 0.9。

在这种情况下,摄像头显然(滥用)使用 HTTP 来启动一个流(因为假设它将继续在连接上发送数据,这也不是 HTTP 0.9,尽管没有明确禁止)。获取所需数据的最简单方法是手动执行以下操作:

  • 创建并打开与服务器的基本地址的套接字
  • 发送对 audiostream.cgi?user=<user>&amp;pwd=<password>&amp;streamid=0&amp;filename= 的 GET 请求(您真的需要最后一个参数吗?)
  • 在一个线程中以循环方式运行 socket.recv(max_bytes) 并传输到一个(线程安全的)缓冲区,在另一个线程中对该缓冲区执行所需操作。

或者,如果您熟悉异步编程,可以使用 asyncio 而不是线程。

显然,您需要自己处理文件流的解码。希望您能识别格式并将其传递给解码器;或者类似 ffmpeg 的工具可能能够猜测它。

英文:

HTTP 0.9 is about the simplest possible http protocol:

> The client sends a document request consisting of a line of ASCII characters terminated by a CR LF (carriage return, line feed) pair [...]
> This request consists of the word "GET", a space, the document address , omitting the "http:, host and port parts when they are the coordinates just used to make the connection.

> The response to a simple GET request is a message in hypertext mark-up language ( HTML ). This is a byte stream of ASCII characters.

source

Thus your server is not sending a valid HTTP 0.9 response, as it's not html. Chrome (etc) is quite within its rights to reject it, although in practice it may not even support http 0.9.

In this case the camera is apparently (ab)using http to start a stream (since presumably it will carry on sending data over the connection, which is also not http 0.9, although not explicitly forbidden). The simplest way to get the data you want is to do it manually:

  • Create and open a socket with the server's base address
  • send a GET request for audiostream.cgi?user=&lt;user&gt;&amp;pwd=&lt;password&gt;&amp;streamid=0&amp;filename= (do you really need that last param?)
  • run socket.recv(max_bytes) in a loop in a thread and transfer to a (thread-safe) buffer, do whatever you want to do with that buffer in another thread.

Alternatively if you're familiar with async programming, use asyncio rather than threads.

You will obviously need to handle decoding the file stream yourself. Hopefully you can identify the format and pass it to a decoder; alternatively something like ffmpeg might be able to guess it.

huangapple
  • 本文由 发表于 2023年2月16日 17:11:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/75469992.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定