有没有办法配置 php 始终设置 $_SERVER['CONTENT_LENGTH']?

发布于 2024-12-07 16:19:57 字数 2179 浏览 3 评论 0原文

我正在研究carddav 客户端。作为服务器,我使用 davical v. 0.9.9.6。我不明白为什么当 http 标头包含正确的值时我会收到无效的内容类型错误。我查看源代码并发现了这种情况:

if ( isset($_SERVER['CONTENT_LENGTH']) && $_SERVER['CONTENT_LENGTH'] > 7) {...

经过一番研究,我发现 php set $_SERVER['CONTENT_LENGTH'] 仅使用 POST 方法和上传文件。有没有办法配置 php 始终设置 $_SERVER['CONTENT_LENGTH']? 我问的是一般情况,不仅仅是这种情况......

//编辑 我正在向 davical 服务器发出 HTTP PUT 请求(使用 php curl)。

PUT /caldav.php/testuser/contacts/newc.vcf HTTP/1.1
Host: davical  
Content-Type: text/vcard;

BEGIN:VCARD
VERSION:3.0
FN:ME
...

在 davical 方面是未设置的条件测试 CONTENT_LENGTH。那么这是一个戴维的错误吗?

//编辑2

我终于明白了! 带有回调 readfunc 的 PUT 请求需要通过curl_setopt(...) 设置 INFILE_SIZE 没有自动值,手动将 Content-Length 字段放入标头也是错误的。 示例(不正确):

// PUT REQUEST
curl_setopt($ch,CURLOPT_HTTPHEADER,"Content-Length: $length");  //mistake
curl_setopt($ch,CURLOPT_PUT,true);
curl_setopt($ch,CURLOPT_READFUNCTION,array($this,'readfunc'));
....
--------------------------------------------------------------
// WIRESHARK TCP STREAM DUMP
PUT /caldav.php/testuser/contacts/novy.vcf HTTP/1.1
Authorization: Basic xxxxxxxxxxxxxxx
Host: davical
Accept: */*
Content-Type: text/vcard
Content-Length: xxx
Expect: 100-continue

HTTP/1.1 100 Continue

155
BEGIN:VCARD
VERSION:3.0
...
END:VCARD

0

HTTP/1.1 200 OK
----------------------------------------------------------------
// On server side
isset($_SERVER['CONTENT_LENGTH'])==false

第二个(正确)示例

// PUT REQUEST
curl_setopt($ch,CURLOPT_INFILESIZE,$length);
curl_setopt($ch,CURLOPT_PUT,true);
curl_setopt($ch,CURLOPT_READFUNCTION,array($this,'readfunc'));
....
--------------------------------------------------------------
// WIRESHARK TCP STREAM DUMP
PUT /caldav.php/testuser/contacts/novy.vcf HTTP/1.1
Authorization: Basic xxxxxxxxxxxxxxx
Host: davical
Accept: */*
Content-Type: text/vcard
Content-Length: xxx
Expect: 100-continue

HTTP/1.1 100 Continue

BEGIN:VCARD
VERSION:3.0
...
END:VCARD
HTTP/1.1 200 OK
----------------------------------------------------------------
// On server side
isset($_SERVER['CONTENT_LENGTH'])==true

I'm working on carddav client. As server i use davical v. 0.9.9.6. I don't understand why i'm getting invalid content-type error when http headers contains correct value. I look into source code and found this condition:

if ( isset($_SERVER['CONTENT_LENGTH']) && $_SERVER['CONTENT_LENGTH'] > 7) {...

After little research I found php set $_SERVER['CONTENT_LENGTH'] only with POST method and uploading file. Is there any way to configure php to always set $_SERVER['CONTENT_LENGTH']?
I'm asking generally, not only for this case...

//EDIT
I'm doing HTTP PUT request to davical server (using php curl).

PUT /caldav.php/testuser/contacts/newc.vcf HTTP/1.1
Host: davical  
Content-Type: text/vcard;

BEGIN:VCARD
VERSION:3.0
FN:ME
...

On davical side is condition testing CONTENT_LENGTH which is not set. So it's a davical bug?

//EDIT 2

Finally I figure it out!
PUT request with calback readfunc requires set INFILE_SIZE via curl_setopt(...)
There is none auto value and put Content-Length field manualy into header is also wrong.
Example (incorrect):

// PUT REQUEST
curl_setopt($ch,CURLOPT_HTTPHEADER,"Content-Length: $length");  //mistake
curl_setopt($ch,CURLOPT_PUT,true);
curl_setopt($ch,CURLOPT_READFUNCTION,array($this,'readfunc'));
....
--------------------------------------------------------------
// WIRESHARK TCP STREAM DUMP
PUT /caldav.php/testuser/contacts/novy.vcf HTTP/1.1
Authorization: Basic xxxxxxxxxxxxxxx
Host: davical
Accept: */*
Content-Type: text/vcard
Content-Length: xxx
Expect: 100-continue

HTTP/1.1 100 Continue

155
BEGIN:VCARD
VERSION:3.0
...
END:VCARD

0

HTTP/1.1 200 OK
----------------------------------------------------------------
// On server side
isset($_SERVER['CONTENT_LENGTH'])==false

Second (correct) example

// PUT REQUEST
curl_setopt($ch,CURLOPT_INFILESIZE,$length);
curl_setopt($ch,CURLOPT_PUT,true);
curl_setopt($ch,CURLOPT_READFUNCTION,array($this,'readfunc'));
....
--------------------------------------------------------------
// WIRESHARK TCP STREAM DUMP
PUT /caldav.php/testuser/contacts/novy.vcf HTTP/1.1
Authorization: Basic xxxxxxxxxxxxxxx
Host: davical
Accept: */*
Content-Type: text/vcard
Content-Length: xxx
Expect: 100-continue

HTTP/1.1 100 Continue

BEGIN:VCARD
VERSION:3.0
...
END:VCARD
HTTP/1.1 200 OK
----------------------------------------------------------------
// On server side
isset($_SERVER['CONTENT_LENGTH'])==true

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

信愁 2024-12-14 16:19:57

尽管我从未使用过 CONTENT_LENGHT,但我可以告诉您为什么可能会发生这种情况:

在请求中,您不必设置 Content-Lenght 标头...这不是强制性的。特殊情况除外。如果您发布的内容的类型为“multipart/form-data”,则有必要为每个部分使用内容长度,因为每个部分都由边界分隔,并且每个部分都有自己的标题...

例如:

Content-Type: MultiPart/Form-Data
Boundary: @FGJ4823024562DGGRT3455

MyData=1&Username=Blabla&Password=Blue


@FGJ4823024562DGGRT3455==
Content-Type: image/jpef:base64
Content-Lenght: 256

HNSIFRTGNOHVDFNSIAH$5346twSADVni56hntgsIGHFNR$Iasdf==

所以这里是是多部分请求工作原理的一个粗略示例,您会看到第二部分具有内容长度。这就是为什么有时设置内容长度有时不设置的原因,因为在找到另一个边界并提取正确的数据之前需要读取 X 字节。

这并不意味着您的服务器在其他情况下永远不会发送它,但我的 2 美分是现在的情况。这是因为你不是处于POST,而是处于其他一些模式。

Although i have never used CONTENT_LENGHT i can tell you why this is probably happening:

In a request, you don't have to set the Content-Lenght header... IT IS NOT MANDATORY. Except for specific situations. If your POSTed content is of type "multipart/form-data" it becomes necessary to use content-lenght for each part because each part is seperated by a boundary and each part will have its own headers...

For example:

Content-Type: MultiPart/Form-Data
Boundary: @FGJ4823024562DGGRT3455

MyData=1&Username=Blabla&Password=Blue


@FGJ4823024562DGGRT3455==
Content-Type: image/jpef:base64
Content-Lenght: 256

HNSIFRTGNOHVDFNSIAH$5346twSADVni56hntgsIGHFNR$Iasdf==

So here this is a crude example of what a multi part request works, you see that the second part has a content-lenght. This is why sometimes the content-lenght is set and sometimes not, because you need to read X bytes before finding another boundary and extract the correct data.

It doesn't mean your server will never send it in in other cases, but my 2 cents are this is the case right now. Its because you are not in POST, but in some other modes.

口干舌燥 2024-12-14 16:19:57

只有具有请求正文的请求才具有内容长度请求标头(或者至少只有这样才有意义),因此会设置 $_SERVER 变量。

如果您需要始终设置它(我认为这是假的),您可以在脚本的一开始就自己执行此操作:

isset($_SERVER['CONTENT_LENGTH']) && $_SERVER['CONTENT_LENGTH'] = 0;

假设如果未设置它,则它的长度为零。另请参阅改进了 PHP 中 HTTP 请求的处理

Only requests that have a request body have a content length request header (or at least only then it makes sense) and so therefore the $_SERVER variable is set.

If you need it to be always set (which I think is bogus), you can do this yourself on the very beginning of your script:

isset($_SERVER['CONTENT_LENGTH']) && $_SERVER['CONTENT_LENGTH'] = 0;

Assuming that if it is not set, it's of zero length. See as well Improved handling of HTTP requests in PHP.

街道布景 2024-12-14 16:19:57

您也许可以自己设置它们。为什么需要设置这个值?他们应该设置什么?

也许您缺少有关 $_SERVER['CONTENT_TYPE'] 的信息或
$_SERVER['CONTENT_LENGTH'] 就像我一样。在 POST 请求中,这些是
除了上面列出的之外,还可以使用。

-> http://www.php.net/manual/en/reserved .variables.server.php#86495

You could probably set them by yourself. Why do you need that this values are set? And what should they set to?

Maybe you're missing information on $_SERVER['CONTENT_TYPE'] or
$_SERVER['CONTENT_LENGTH'] as I did. On POST-requests these are
available in addition to those listed above.

-> http://www.php.net/manual/en/reserved.variables.server.php#86495

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文