HTTP响应设置及PHP模拟HTTP请求

Posted eyes++

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HTTP响应设置及PHP模拟HTTP请求相关的知识,希望对你有一定的参考价值。

一:HTTP详解

1). HTTP相关了解

HTTP协议概念
HTTP协议,即超文本传输协议(Hypertext transfer protocol)。是一种详细规定了浏览器和万维网(WWW = World Wide Web)服务器之间互相通信的规则,通过因特网传送万维网文档的数据传送协议。
HTTP协议是用于从WWW服务器传输超文本到本地浏览器的传送协议。它可以使浏览器更加高效,使网络传输减少。它不仅保证计算机正确快速地传输超文本文档,还确定传输文档中的哪一部分,以及哪部分内容首先显示(如文本先于图形)等。

HTTP协议特点

  • 客户/服务器模式:客户端(浏览器)/服务端
  • 简单快速:客户向服务器请求服务时,只需传送请求方法和路径。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。
  • 灵活:HTTP允许传输任意类型的数据对象(MIME类型)
  • 无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
  • 无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。

HTTP协议分类
http请求协议:浏览器向服务器发起请求的时候需要遵循的协议
http响应协议:服务器向浏览器发起响应的时候需要遵循的协议

2). HTTP请求

一个完整的http请求应该包括请求行,请求头以及请求体。

请求行
1)形式:请求方式 资源路径 协议版本号
2)GET https://www.baidu.com/ HTTP/1.1
请求行独占第一行

请求头
请求头就是各项协议内容:具体的协议内容不会每次都使用全部
常见请求头内容:
1)Host:请求的主机地址(必须)
2)Accept:当前请求能够接收服务器返回的类型(MIME类型)
3)Accept-Language:接收的语言
4)User-Agent:客户浏览器所在点的一些信息
5)Accept-Encoding:可接受的数据压缩格式

请求头不固定数量,每个请求协议也是独占一行,最后会有一行空行(用来区分请求头和请求体)

请求体
请求数据:POST请求会有请求体而GET请求没有。因为GET请求所有的数据都是跟在URL之后,会在请求行中的资源路径上体现。

下面是我使用fiddler对百度进行抓包得到的数据,因为现在的主流浏览器都会对http请求做处理,因此我只能使用fiddler获取原始的http请求。

GET https://www.baidu.com/ HTTP/1.1
Host: www.baidu.com
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/92.0.4515.107 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
sec-ch-ua: "Chromium";v="92", " Not A;Brand";v="99", "Google Chrome";v="92"
sec-ch-ua-mobile: ?0
Accept-Encoding: gzip, deflate, br
Accept-Language: en,zh-CN;q=0.9,zh;q=0.8

3). HTTP响应

与HTTP请求类似,一个完整的http响应也包括三部分:响应行,响应头以及响应体。

响应行
1)形式:协议版本号 状态码 状态消息(独占一行)
HTTP/1.1 200 ok
2)200 ok: 成功
3)403 Forbidden: 没权限访问
4)404 Not Found: 未找到页面
5)500 Server Internal Error: 服务器内部错误

响应头
响应头一个占一行,并且为了区分响应头和响应体,响应头后面应该先空一行再是响应体。
常见协议内容:
1)http协议版本、状态码:HTTP/1.1 200 OK
2)连接状态:Connection: keep-alive
3)响应数据压缩格式:Content-Encoding: gzip
4)内容类型(告诉浏览器对应的数据格式):Content-Type: text/html;charset=utf-8
5)响应时间:Date: Thu, 29 Jul 2021 13:21:31 GMT
6)服务器信息:Server: BWS/1.1
7)设置的cookie信息:Set-Cookie

响应体
实际服务器响应给浏览器的内容

以下是我用fiddle对百度抓包的响应体数据:

HTTP/1.1 200 OK
Bdpagetype: 1
Bdqid: 0xf5445c5400006514
Cache-Control: private
Connection: keep-alive
Content-Encoding: gzip
Content-Type: text/html;charset=utf-8
Date: Thu, 29 Jul 2021 13:21:31 GMT
Expires: Thu, 29 Jul 2021 13:20:35 GMT
P3p: CP=" OTI DSP COR IVA OUR IND COM "
P3p: CP=" OTI DSP COR IVA OUR IND COM "
Server: BWS/1.1
Set-Cookie: BAIDUID=7FB5161F958DA8DA11245312F6CA57B0:FG=1; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
Set-Cookie: BIDUPSID=7FB5161F958DA8DA11245312F6CA57B0; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
Set-Cookie: PSTM=1627564891; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
Set-Cookie: BAIDUID=7FB5161F958DA8DACC6F37A89191F334:FG=1; max-age=31536000; expires=Fri, 29-Jul-22 13:21:31 GMT; domain=.baidu.com; path=/; version=1; comment=bd
Set-Cookie: BDSVRTM=0; path=/
Set-Cookie: BD_HOME=1; path=/
Set-Cookie: H_PS_PSSID=34299_33802_34335_34278_34004_34092_34107_34094_26350_34242; path=/; domain=.baidu.com
Set-Cookie: BAIDUID_BFESS=7FB5161F958DA8DA11245312F6CA57B0:FG=1; Path=/; Domain=baidu.com; Expires=Thu, 31 Dec 2037 23:55:55 GMT; Max-Age=2147483647; Secure; SameSite=None
Strict-Transport-Security: max-age=172800
Traceid: 1627564891097109965817673352353555703060
X-Frame-Options: sameorigin
X-Ua-Compatible: IE=Edge,chrome=1
Transfer-Encoding: chunked

...
...
(此处省略响应体)

二:HTTP相应设置

php中针对HTTP协议(响应)进行了底层设计,可以通过函数header来实现修改HTTP响应(响应头)

注意事项:
1、 Header函数可以设计HTTP响应,因为HTTP协议特点是:响应行,响应头(空行结尾),响应体。认为通过header函数设计响应头的时候,不应该有任何内容输出,因为一旦产生内容输出(哪怕一个空格),系统都会认为响应头已经结束而响应体开始了,所以如果先输出内容后设置响应头(header使用),理论设置无效;
2、 在PHP5以后,增加程序缓存内容:允许服务器脚本在输出内容的时候,不直接返回浏览器而是现在服务器端使用程序缓存保留(php.ini中使用output_buffering),有了该内容之后,在程序缓存内会自动调整响应头和响应体(允许响应头在已经输出的内容之后再设置),但是此时会报错(警告)。
总结:header设置响应体之前不要有任何输出

Location:重定向,立即跳转(响应体不用解析)
浏览器在解析服务器响应的时候:先判定响应行,继续响应头,最后响应体:location是在响应头中,所以浏览器一旦见到该协议项,不再向下解析。

<?php
echo 'hello';
sleep(5); // 休眠5s后再执行后面代码
echo 'world';

呃…似乎使用该方法会被浏览器拦截

Refresh:重定向,定时跳转(响应体会解析)
延时重定向:浏览器会根据具体时间延迟后在访问指定跳转链接:浏览器在准备跳转访问之前,会继续解析HTTP协议(响应头和响应体),设置的延时单位为秒。

<?php
echo 'hello!';
header('Refresh:3;url=https://www.csdn.com');
echo 'world';

似乎使用这种方式也会被浏览器定义为不安全。

Content-type:内容类型,MIME类型
通过内容告知(MIME类型),浏览器正确解析内容

<?php
header('Content-type:text/html;charset:utf-8');
echo '你好';

Content-disposition:内容类型,MIME类型扩展,激活浏览器文件下载对话框
是 MIME 协议的扩展,MIME 协议指示 MIME 用户代理如何显示附加的文件。Content-disposition其实可以控制用户请求所得的内容存为一个文件的时候提供一个默认的文件名,文件直接在浏览器上显示或者在访问时弹出文件下载对话框。

<?php
// Content-disposition:attachment 是指以附件的形式下载
header('Content-disposition:attachment;filename=php.txt');

echo 'hello php';

三:PHP模拟HTTP请求

前提条件:HTTP协议的客户端/服务端模式,HTTP协议不局限于一定要浏览器访问。

PHP可以通过模拟HTTP协议发起HTTP请求
CURL是一个非常强大的开源库,支持很多协议,包括HTTP、FTP、TELNET等,我们使用它来发送HTTP请求。它给我们带来的好处是可以通过灵活的选项设置不同的HTTP协议参数,并且支持HTTPS。CURL可以根据URL前缀是“HTTP” 还是“HTTPS”自动选择是否加密发送内容。

开启curl库

curl库是php的一个标准库,因此可直接在php.ini中开启拓展。

实现curl

1). 建立连接(激活一个curl连接功能):curl_init()

2). 设置请求选项: curl_setOpt()
语法格式为:

curl_setopt( resource $ch, int $option, mixed $value) : bool

ch :由 curl_init() 返回的 cURL 句柄。option:需要设置的CURLOPT_XXX选项。 value:将设置在option选项上的值。

option常用可选参数:
CURLOPT_URL:连接对象
CURLOPT_RETURNTRANSFER:将服务器执行的结果(响应)以文件流的形式返回给请求界面(PHP脚本)
CURLOPT_POST:是否才有POST方式发起请求(默认请求是GET)
CURLOPT_POSTFIELDS:用来传递POST提交的数据,分为两种方式:字符串(name=abc&password=123)以及数组形式(array(‘name’=>’abc’,…))
CURLOPT_HEADER:是否得到响应的header信息(响应头),默认不获取

3). 执行请求(得到服务器返回内容): curl_exec()

4). 关闭连接: curl_close()

<?php
header('Content-type:text/html;charset:utf-8');

// 开启会话
$ch = curl_init();
//var_dump($ch);

// 设置连接选项
curl_setopt($ch, CURLOPT_URL, './sim_obj.php');  // 连接选项
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);  // 文件流形式返回数据(不直接显示)
curl_setopt($ch, CURLOPT_HEADER, 0);  // 是否获取响应头信息

// 如果要使用post
curl_setopt($ch, CURLOPT_POST, TURE);
curl_setopt($ch, CURLOPT_POSTFIELDS, array());

// 执行
$content = curl_exec($ch);
echo $content;

// 关闭资源
curl_close($ch);

四:HTTP状态码

1xx:信息
消息
描述
100 Continue
服务器仅接收到部分请求,但是一旦服务器并没有拒绝该请求,客户端应该继续发送其余的请求。
101 Switching Protocols
服务器转换协议:服务器将遵从客户的请求转换到另外一种协议。
2xx:成功
消息
描述
200 OK
请求成功(其后是对GET和POST请求的应答文档。)
201 Created
请求被创建完成,同时新的资源被创建。
202 Accepted
供处理的请求已被接受,但是处理未完成。
203 Non-authoritative Information
文档已经正常地返回,但一些应答头可能不正确,因为使用的是文档的拷贝。
204 No Content
没有新文档。浏览器应该继续显示原来的文档。如果用户定期地刷新页面,而Servlet可以确定用户文档足够新,这个状态代码是很有用的。
205 Reset Content
没有新文档。但浏览器应该重置它所显示的内容。用来强制浏览器清除表单输入内容。
206 Partial Content
客户发送了一个带有Range头的GET请求,服务器完成了它。
3xx:重定向
消息
描述
300 Multiple Choices
多重选择。链接列表。用户可以选择某链接到达目的地。最多允许五个地址。
301 Moved Permanently
所请求的页面已经转移至新的url。
302 Found
所请求的页面已经临时转移至新的url。
303 See Other
所请求的页面可在别的url下被找到。
304 Not Modified
未按预期修改文档。客户端有缓冲的文档并发出了一个条件性的请求(一般是提供If-Modified-Since头表示客户只想比指定日期更新的文档)。服务器告诉客户,原来缓冲的文档还可以继续使用。
305 Use Proxy
客户请求的文档应该通过Location头所指明的代理服务器提取。
306 Unused
此代码被用于前一版本。目前已不再使用,但是代码依然被保留。
307 Temporary Redirect
被请求的页面已经临时移至新的url。
4xx:客户端错误
消息
描述
400 Bad Request
服务器未能理解请求。
401 Unauthorized
被请求的页面需要用户名和密码。
401.1
登录失败。
401.2
服务器配置导致登录失败。
401.3
由于ACL对资源的限制而未获得授权。
401.4
筛选器授权失败。
401.5
ISAPI/CGI应用程序授权失败。
401.7
访问被Web服务器上的URL授权策略拒绝。这个错误代码为IIS 6.0所专用。
402 Payment Required
此代码尚无法使用。
403 Forbidden
对被请求页面的访问被禁止。
403.1
执行访问被禁止。
403.2
读访问被禁止。
403.3
写访问被禁止。
403.4
要求SSL。
403.5
要求SSL 128。
403.6
IP地址被拒绝。
403.7
要求客户端证书。
403.8
站点访问被拒绝。
403.9
用户数过多。
403.10
配置无效。
403.11
密码更改。
403.12
拒绝访问映射表。
403.13
客户端证书被吊销。
403.14
拒绝目录列表。
403.15
超出客户端访问许可。
403.16
客户端证书不受信任或无效。
403.17
客户端证书已过期或尚未生效。
403.18
在当前的应用程序池中不能执行所请求的URL。这个错误代码为IIS 6.0所专用。
403.19
不能为这个应用程序池中的客户端执行CGI。这个错误代码为IIS 6.0所专用。
403.20
Passport登录失败。这个错误代码为IIS 6.0所专用。
404 Not Found
服务器无法找到被请求的页面。
404.0
(无)–没有找到文件或目录。
404.1
无法在所请求的端口上访问Web站点。
404.2
Web服务扩展锁定策略阻止本请求。
404.3
MIME映射策略阻止本请求。
405 Method Not Allowed
请求中指定的方法不被允许。
406 Not Acceptable
服务器生成的响应无法被客户端所接受。
407 Proxy Authentication Required
用户必须首先使用代理服务器进行验证,这样请求才会被处理。
408 Request Timeout
请求超出了服务器的等待时间。
409 Conflict
由于冲突,请求无法被完成。
410 Gone
被请求的页面不可用。
411 Length Required
"Content-Length"未被定义。如果无此内容,服务器不会接受请求。
412 Precondition Failed
请求中的前提条件被服务器评估为失败。
413 Request Entity Too Large
由于所请求的实体的太大,服务器不会接受请求。
414 Request-url Too Long
由于url太长,服务器不会接受请求。当post请求被转换为带有很长的查询信息的get请求时,就会发生这种情况。
415 Unsupported Media Type
由于媒介类型不被支持,服务器不会接受请求。
416 Requested Range Not Satisfiable
服务器不能满足客户在请求中指定的Range头。
417 Expectation Failed
执行失败。
423
锁定的错误。
5xx:服务器错误
消息
描述
500 Internal Server Error
请求未完成。服务器遇到不可预知的情况。
500.12
应用程序正忙于在Web服务器上重新启动。
500.13
Web服务器太忙。
500.15
不允许直接请求Global.asa。
500.16
UNC授权凭据不正确。这个错误代码为IIS 6.0所专用。
500.18
URL授权存储不能打开。这个错误代码为IIS 6.0所专用。
500.100
内部ASP错误。
501 Not Implemented
请求未完成。服务器不支持所请求的功能。
502 Bad Gateway
请求未完成。服务器从上游服务器收到一个无效的响应。
502.1
CGI应用程序超时。
502.2
CGI应用程序出错。
503 Service Unavailable
请求未完成。服务器临时过载或宕机。
504 Gateway Timeout
网关超时。
505 HTTP Version Not Supported
服务器不支持请求中指明的HTTP版本。

以上是关于HTTP响应设置及PHP模拟HTTP请求的主要内容,如果未能解决你的问题,请参考以下文章

Charles——Charles环境搭建,使用Charles抓取 Http 和 Https 的请求和响应进行接口测试,模拟慢速网络进行弱网测试,设置请求时间和请求数量进行负载测试

http模拟登陆及发请求

如何用 Charles 模拟 HTTP 错误响应?

http常见的状态码,400,401,403状态码 , http响应 ,php设置http响应

Fiddler常用功能-总结

fiddler 设置断点修改请求,响应数据及模拟响应