HTTP协议请求头详解
HTTP由两部分组成:请求和响应。当你在Web浏览器中输⼊⼀个URL时,浏览器将根据你的要求创建并发送请求,该请求包含所输⼊的URL以及⼀些与浏览器本⾝相关的信息。当服务器收到这个请求时将返回⼀个响应,该响应包括与该请求相关的信息以及位于指定URL(如果有的话)的数据。直到浏览器解析该响应并显⽰出⽹页(或其他资源)为⽌。
HTTP请求
HTTP请求的格式如下所⽰:
<request-line>
<headers>
<blank line>
[<request-body>]
在HTTP请求中,第⼀⾏必须是⼀个请求⾏(request line),⽤来说明请求类型、要访问的资源以及使
⽤的HTTP版本。紧接着是⼀个⾸部(header)⼩节,⽤来说明服务器要使⽤的附加信息。在⾸部之后是⼀个空⾏,再此之后可以添加任意的其他数据[称之为主体(body)]。
在HTTP中,定义了多种请求类型,通常我们关⼼的只有GET请求和POST请求。只要在Web浏览器上输⼊⼀个URL,浏览器就将基于该URL向服务器发送⼀个GET请求,以告诉服务器获取并返回什么资源。对于www.baidu的GET请求如下所⽰:
GET / HTTP/1.1
Host: www.baidu
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)
Gecko/20050225 Firefox/1.0.1
Connection: Keep-Alive
请求⾏的第⼀部分说明了该请求是GET请求。该⾏的第⼆部分是⼀个斜杠(/),⽤来说明请求的是该域名的根⽬录。该⾏的最后⼀部分说明使⽤的是HTTP 1.1版本(另⼀个可选项是1.0)。那么请求发到哪⾥去呢?这就是第⼆⾏的内容。
第2⾏是请求的第⼀个⾸部,HOST。⾸部HOST将指出请求的⽬的地。结合HOST和上⼀⾏中的斜杠(/),可以通知服务器请求的是www.baidu/(HTTP 1.1才需要使⽤⾸部HOST,⽽原来的1.0版本则不需要使⽤)。第三⾏中包含的是⾸部User-Agent,服务器端和客户端脚本都能够访问它,它是浏览器类型检测逻辑的重要基础。该信息由你使⽤的浏览器来定义(在本例中是Firefox 1.0.1),并且在每个请求中将⾃动发送。最后⼀⾏是⾸部Connection,通常将浏览器操作设置为Keep-Alive(当然也可以设置为其他值)。注意,在最后⼀个⾸部之后有⼀个空⾏。即使不存在请求主体,这个空⾏也是必需的。
要发送GET请求的参数,则必须将这些额外的信息附在URL本⾝的后⾯。其格式类似于:
URL ? name1=value1&name2=value2&..&nameN=valueN
该信息称之为查询字符串(query string),它将会复制在HTTP请求的请求⾏中,如下所⽰:
GET /books/?name=Professional%20Ajax HTTP/1.1
Host: www.baidu
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)
Gecko/20050225 Firefox/1.0.1
Connection: Keep-Alive
注意,为了将⽂本“Professional Ajax”作为URL的参数,需要编码处理其内容,将空格替换成%20,这称为URL编码(URL encoding),常⽤于HTTP的许多地⽅(JavaScript提供了内建的函数来处理URL编码和解码)。“名称—值”(name—value)对⽤ & 隔开。绝⼤部分的服务器端技术能够⾃动对请求主体进⾏解码,并为这些值的访问提供⼀些逻辑⽅式。当然,如何使⽤这些数据还是由服务器决定的。
另⼀⽅⾯,POST请求在请求主体中为服务器提供了⼀些附加的信息。通常,当填写⼀个在线表单并提交它时,这些填⼊的数据将以POST请求的⽅式发送给服务器。
以下就是⼀个典型的POST请求:在线url网址编码解码
POST / HTTP/1.1
Host: www.baidu
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)
Gecko/20050225 Firefox/1.0.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 40
Connection: Keep-Alive
name=Professional%20Ajax&publisher=Wiley
从上⾯可以发现, POST请求和GET请求之间有⼀些区别。⾸先,请求⾏开始处的GET改为了POST,以表⽰不同的请求类型。你会发现⾸部Host和User- Agent仍然存在,在后⾯有两个新⾏。其中⾸部Content-Type说明了请求主体的内容是如何编码的。浏览器始终以application/ x-www-form- urlencoded的格式编码来传送数据,这是针对简单URL编码的MIME类型。⾸部Content-Length说明了请求主体的字节数。在⾸部 Connection后是⼀个空⾏,再后⾯就是请求主体。与⼤多数浏览器的POST请求⼀样,这是以简单的“名称—值”对的形式给出的,其中name是 Professional Ajax,publisher是Wiley。你可以以同样的格式来组织URL的查询字符串参数。
下⾯是⼀些最常见的请求头:
Accept:浏览器可接受的MIME类型。
Accept - Charset:浏览器可接受的字符集。
Accept - Encoding:浏览器能够进⾏解码的数据编码⽅式,⽐如gzip。Servlet能够向⽀持gzip的浏览器返回经gzip编码的HTML页⾯。许多情形下这可以减少5到10倍的下载时间。
Accept - Language:浏览器所希望的语⾔种类,当服务器能够提供⼀种以上的语⾔版本时要⽤到。
Authorization:授权信息,通常出现在对服务器发送的WWW - Authenticate头的应答中。
Connection:表⽰是否需要持久连接。如果Servlet看到这⾥的值为“Keep - Alive”,或者看到请求使⽤的是HTTP 1.1(HTTP 1.1默认进⾏持久连接),它就可以利⽤持久连接的优点,当页⾯包含多个元素时(例如Applet,图⽚),显著地减少下载所需要的时间。要实现这⼀点,Servlet需要在应答中发送⼀个Content - Length头,最简单的实现⽅法是:先把内容写⼊ByteArrayOutputStream,然后在正式写出内容之前计算它的⼤⼩。
Content - Length:表⽰请求消息正⽂的长度。
Cookie:这是最重要的请求头信息之⼀,参见后⾯《Cookie处理》⼀章中的讨论。
From:请求发送者的email地址,由⼀些特殊的Web客户程序使⽤,浏览器不会⽤到它。
Host:初始URL中的主机和端⼝。
If - Modified - Since:只有当所请求的内容在指定的⽇期之后⼜经过修改才返回它,否则返回304“Not Modified”应答。
Pragma:指定“no - cache”值表⽰服务器必须返回⼀个刷新后的⽂档,即使它是代理服务器⽽且已经有了页⾯的本地拷贝。
Referer:包含⼀个URL,⽤户从该URL代表的页⾯出发访问当前请求的页⾯。
User - Agent:浏览器类型,如果Servlet返回的内容与浏览器类型有关则该值⾮常有⽤。
UA - Pixels,UA - Color,UA - OS,UA - CPU:由某些版本的IE浏览器所发送的⾮标准的请求头,表⽰屏幕⼤⼩、颜⾊深度、操作系统和CPU类型。
HTTP响应
如下所⽰,HTTP响应的格式与请求的格式⼗分类似:
<status-line>
<headers>
<blank line>
[<response-body>]
正如你所见,在响应中唯⼀真正的区别在于第⼀⾏中⽤状态信息代替了请求信息。状态⾏(status line)通过提供⼀个状态码来说明所请求的资源情况。以下就是⼀个HTTP响应的例⼦:
HTTP/1.1 200 OK
Date: Sat, 31 Dec 2005 23:59:59 GMT
Content-Type: text/html;charset=ISO-8859-1
Content-Length: 122
<html>
<head>
<title>Wrox Homepage</title>
</head>
<body>
<!-- body goes here -->
</body>
</html>
在本例中,状态⾏给出的HTTP状态代码是200,以及消息OK。状态⾏始终包含的是状态码和相应的简短消息,以避免混乱。最常⽤的状态码有:
◆200 (OK): 到了该资源,并且⼀切正常。
◆304 (NOT MODIFIED): 该资源在上次请求之后没有任何修改。这通常⽤于浏览器的缓存机制。
◆401 (UNAUTHORIZED): 客户端⽆权访问该资源。这通常会使得浏览器要求⽤户输⼊⽤户名和密码,以登录到服务器。
◆403 (FORBIDDEN): 客户端未能获得授权。这通常是在401之后输⼊了不正确的⽤户名或密码。
◆404 (NOT FOUND): 在指定的位置不存在所申请的资源。
在状态⾏之后是⼀些⾸部。通常,服务器会返回⼀个名为Data的⾸部,⽤来说明响应⽣成的⽇期和时间(服务器通常还会返回⼀些关于其⾃⾝的信息,尽管并⾮是必需的)。接下来的两个⾸部⼤家应该熟悉,就是与POST请求中⼀样的 Content-Type和Content-Length。在本例中,⾸部Content-Type指定了MIME类型HTML(text/html),其编码类型是ISO-8859-1(这是针对美国英语资源的编码标准)。响应主体所包含的就是所请求资源的HTML源⽂件(尽管还可能包含纯⽂本或其他资源类型的⼆进制数据)。浏览器将把这些数据显⽰给⽤户。
注意,这⾥并没有指明针对该响应的请求类型,不过这对于服务器并不重要。客户端知道每种类型的请求将返回什么类型的数据,并决定如何使⽤这些数据。
附录:使⽤Java套接字实现⼀个可以处理get和post请求的⼩HTTP服务器程序
/**
* SimpleHttpServer.java
*/
import java.io.*;
import java.*;
import java.util.StringTokenizer;
下⾯是不同状态码代表的意思:
http状态返回代码 1xx(临时响应)
表⽰临时响应并需要请求者继续执⾏操作的状态代码。
http状态返回代码代码说明
100 (继续)请求者应当继续提出请求。服务器返回此代码表⽰已收到请求的第⼀部分,正在等待其余部分。
101 (切换协议)请求者已要求服务器切换协议,服务器已确认并准备切换。
http状态返回代码 2xx (成功)
表⽰成功处理了请求的状态代码。
http状态返回代码代码说明
200 (成功)服务器已成功处理了请求。通常,这表⽰服务器提供了请求的⽹页。
201 (已创建)请求成功并且服务器创建了新的资源。
202 (已接受)服务器已接受请求,但尚未处理。
203 (⾮授权信息)服务器已成功处理了请求,但返回的信息可能来⾃另⼀来源。
204 (⽆内容)服务器成功处理了请求,但没有返回任何内容。
205 (重置内容)服务器成功处理了请求,但没有返回任何内容。
206 (部分内容)服务器成功处理了部分 GET 请求。
http状态返回代码 3xx (重定向)
表⽰要完成请求,需要进⼀步操作。通常,这些状态代码⽤来重定向。
http状态返回代码代码说明
300 (多种选择)针对请求,服务器可执⾏多种操作。服务器可根据请求者 (user agent) 选择⼀项操作,或提供操作列表供请求者选择。
301 (永久移动)请求的⽹页已永久移动到新位置。服务器返回此响应(对 GET 或 HEAD 请求的响应)时,会⾃动将请求者转到新位置。
302 (临时移动)服务器⽬前从不同位置的⽹页响应请求,但请求者应继续使⽤原有位置来进⾏以后的请求。
303 (查看其他位置)请求者应当对不同的位置使⽤单独的 GET 请求来检索响应时,服务器返回此代码。
304 (未修改)⾃从上次请求后,请求的⽹页未修改过。服务器返回此响应时,不会返回⽹页内容。
305 (使⽤代理)请求者只能使⽤代理访问请求的⽹页。如果服务器返回此响应,还表⽰请求者应使⽤代理。
307 (临时重定向)服务器⽬前从不同位置的⽹页响应请求,但请求者应继续使⽤原有位置来进⾏以后的请求。
http状态返回代码 4xx(请求错误)
这些状态代码表⽰请求可能出错,妨碍了服务器的处理。
http状态返回代码代码说明
400 (错误请求)服务器不理解请求的语法。
401 (未授权)请求要求⾝份验证。对于需要登录的⽹页,服务器可能返回此响应。
403 (禁⽌)服务器拒绝请求。
404 (未到)服务器不到请求的⽹页。
405 (⽅法禁⽤)禁⽤请求中指定的⽅法。
406 (不接受)⽆法使⽤请求的内容特性响应请求的⽹页。
407 (需要代理授权)此状态代码与 401(未授权)类似,但指定请求者应当授权使⽤代理。
408 (请求超时)服务器等候请求时发⽣超时。
409 (冲突)服务器在完成请求时发⽣冲突。服务器必须在响应中包含有关冲突的信息。
410 (已删除)如果请求的资源已永久删除,服务器就会返回此响应。
411 (需要有效长度)服务器不接受不含有效内容长度标头字段的请求。
412 (未满⾜前提条件)服务器未满⾜请求者在请求中设置的其中⼀个前提条件。
413 (请求实体过⼤)服务器⽆法处理请求,因为请求实体过⼤,超出服务器的处理能⼒。
414 (请求的 URI 过长)请求的 URI(通常为⽹址)过长,服务器⽆法处理。
415 (不⽀持的媒体类型)请求的格式不受请求页⾯的⽀持。
416 (请求范围不符合要求)如果页⾯⽆法提供请求的范围,则服务器会返回此状态代码。
417 (未满⾜期望值)服务器未满⾜”期望”请求标头字段的要求。
http状态返回代码 5xx(服务器错误)
这些状态代码表⽰服务器在尝试处理请求时发⽣内部错误。这些错误可能是服务器本⾝的错误,⽽不是请求出错。
http状态返回代码代码说明
500 (服务器内部错误)服务器遇到错误,⽆法完成请求。
501 (尚未实施)服务器不具备完成请求的功能。例如,服务器⽆法识别请求⽅法时可能会返回此代码。
502 (错误⽹关)服务器作为⽹关或代理,从上游服务器收到⽆效响应。
503 (服务不可⽤)服务器⽬前⽆法使⽤(由于超载或停机维护)。通常,这只是暂时状态。
504 (⽹关超时)服务器作为⽹关或代理,但是没有及时从上游服务器收到请求。
505 (HTTP 版本不受⽀持)服务器不⽀持请求中所⽤的 HTTP 协议版本。
⼀些常见的http状态返回代码为:
200 – 服务器成功返回⽹页
404 – 请求的⽹页不存在
503 – 服务不可⽤
*
* 在⽤Java语⾔实现HTTP服务器时,⾸先启动⼀个java.ServerSocket在提供服务的端⼝上监听连接.向客户返回⽂本时,可以⽤ PrintWriter,但是如果返回⼆进制数据,则必须使⽤OutputStream.write(byte[])⽅法,返回的应答消息字符串可以使⽤ Bytes()⽅法转换为字节数组返回,或者使⽤PrintStream的print()⽅法写⼊⽂本,⽤ write(byte[])⽅法写⼊⼆进制数据.
*
* </pre>
* @author 刘长炯
* @version 1.0 2007-07-24 Sunday
*/
public class SimpleHttpServer implements Runnable {
/**
*
*/
ServerSocket serverSocket;//服务器Socket
/**
* 服务器监听端⼝, 默认为 80.
*/
public static int PORT=80;//标准HTTP端⼝
/**
* 开始服务器 Socket 线程.
*/
public SimpleHttpServer() {
try {
serverSocket=new ServerSocket(PORT);
} catch(Exception e) {
System.out.println("⽆法启动HTTP服务器:"+e.getLocalizedMessage());
}
if(serverSocket==null) it(1);//⽆法开始服务器
new Thread(this).start();
System.out.println("HTTP服务器正在运⾏,端⼝:"+PORT);
}
/**
* 运⾏服务器主线程, 监听客户端请求并返回响应.
*/
public void run() {
while(true) {
try {
Socket client=null;//客户Socket
client=serverSocket.accept();//客户机(这⾥是 IE 等浏览器)已经连接到当前服务器
if(client!=null) {
System.out.println("连接到服务器的⽤户:"+client);
try {
// 第⼀阶段: 打开输⼊流
BufferedReader in=new BufferedReader(new InputStreamReader(
System.out.println("客户端发送的请求信息: ***************");
// 读取第⼀⾏, 请求地址
String adLine();
System.out.println(line);
String resource=line.substring(line.indexOf('/'),line.lastIndexOf('/')-5);
//获得请求的资源的地址
resource=URLDecoder.decode(resource, "UTF-8");//反编码 URL 地址
String method = new StringTokenizer(line).nextElement().toString();// 获取请求⽅法, GET 或者 POST
// 读取所有浏览器发送过来的请求参数头部信息
while( (line = in.readLine()) != null) {
System.out.println(line);
if(line.equals("")) break;
}
// 显⽰ POST 表单提交的内容, 这个内容位于请求的主体部分
if("POST".equalsIgnoreCase(method)) {
System.out.adLine());
}
System.out.println("请求信息结束 ***************");
System.out.println("⽤户请求的资源是:"+resource);
System.out.println("请求的类型是: " + method);
// GIF 图⽚就读取⼀个真实的图⽚数据并返回给客户端
dsWith(".gif")) {
fileService("images/test.gif", client);
closeSocket(client);
continue;
}
// 请求 JPG 格式就报错 404
dsWith(".jpg")) {
PrintWriter out=new OutputStream(),true);
out.println("HTTP/1.0 404 Not found");//返回应答消息,并结束应答
out.println();// 根据 HTTP 协议, 空⾏将结束头信息
out.close();
closeSocket(client);
continue;
} else {
// ⽤ writer 对客户端 socket 输出⼀段 HTML 代码
PrintWriter out=new OutputStream(),true);
out.println("HTTP/1.0 200 OK");//返回应答消息,并结束应答
out.println("Content-Type:text/html;charset=GBK");
out.println();// 根据 HTTP 协议, 空⾏将结束头信息
out.println("<h1> Hello Http Server</h1>");
out.println("你好, 这是⼀个 Java HTTP 服务器 demo 应⽤.<br>");
out.println("您请求的路径是: " + resource + "<br>");
out.println("这是⼀个⽀持虚拟路径的图⽚:<img src='abc.gif'><br>" +
"<a href='abc.gif'>点击打开abc.gif, 是个服务器虚拟路径的图⽚⽂件.</a>");
out.println("<br>这是个会反馈 404 错误的的图⽚:<img src='test.jpg'><br><a href='test.jpg'>点击打开test.jpg</a><br>");
out.println("<form method=post action='/'>POST 表单 <input name=username value='⽤户'> <input name=submit type=submit value=submit></form>"); out.close();
closeSocket(client);
}
} catch(Exception e) {
System.out.println("HTTP服务器错误:"+e.getLocalizedMessage());
}
}
//System.out.println(client+"连接到HTTP服务器");//如果加⼊这⼀句,服务器响应速度会很慢
} catch(Exception e) {
System.out.println("HTTP服务器错误:"+e.getLocalizedMessage());
}
}
}
/**
* 关闭客户端 socket 并打印⼀条调试信息.
* @param socket 客户端 socket.
*/
void closeSocket(Socket socket) {
try {
socket.close();
} catch (IOException ex) {
ex.printStackTrace();
}
System.out.println(socket + "离开了HTTP服务器");
}
/**
* 读取⼀个⽂件的内容并返回给浏览器端.
* @param fileName ⽂件名
* @param socket 客户端 socket.
*/
void fileService(String fileName, Socket socket)
{
try
{
PrintStream out = new OutputStream(), true);
File fileToSend = new File(fileName);
ists() && !fileToSend.isDirectory())
{
out.println("HTTP/1.0 200 OK");//返回应答消息,并结束应答
out.println("Content-Type:application/binary");
out.println("Content-Length:" + fileToSend.length());// 返回内容字节数
out.println();// 根据 HTTP 协议, 空⾏将结束头信息
FileInputStream fis = new FileInputStream(fileToSend);
byte data[] = new byte[fis.available()];
out.write(data);
out.close();
fis.close();
}
}
catch(Exception e)
{
System.out.println("传送⽂件时出错:" + e.getLocalizedMessage());
}
}
/**
* 打印⽤途说明.
*/
private static void usage() {
System.out.println("Usage: java HTTPServer <port> Default port is 80.");
}
/**
* 启动简易 HTTP 服务器
* @param args
*/
public static void main(String[] args) {
try {
if(args.length != 1) {
usage();
} else if(args.length == 1) {
PORT = Integer.parseInt(args[0]);
}
} catch (Exception ex) {
}
new SimpleHttpServer();
}
}
</HTML>
*
* 在⽤Java语⾔实现HTTP服务器时,⾸先启动⼀个java.ServerSocket在提供服务的端⼝上监听连接.向客户返回⽂本时,可以⽤PrintWriter,但是如果返回⼆进制数据,则必须使⽤OutputStream.write(byte[])⽅法,返回的应答消息字符串可以使⽤String.g *
* </pre>
* @author 刘长炯
* @version 1.0 2007-07-24 Sunday
*/
public class SimpleHttpServer implements Runnable {
/**
*
*/
ServerSocket serverSocket;//服务器Socket
/**
* 服务器监听端⼝, 默认为 80.
*/
public static int PORT=80;//标准HTTP端⼝
/**
* 开始服务器 Socket 线程.
*/
public SimpleHttpServer() {
try {
serverSocket=new ServerSocket(PORT);
} catch(Exception e) {
System.out.println("⽆法启动HTTP服务器:"+e.getLocalizedMessage());
}
if(serverSocket==null) it(1);//⽆法开始服务器
new Thread(this).start();
System.out.println("HTTP服务器正在运⾏,端⼝:"+PORT);
}
/**
* 运⾏服务器主线程, 监听客户端请求并返回响应.
*/
public void run() {
while(true) {
try {
Socket client=null;//客户Socket
client=serverSocket.accept();//客户机(这⾥是 IE 等浏览器)已经连接到当前服务器
if(client!=null) {
System.out.println("连接到服务器的⽤户:"+client);
try {
// 第⼀阶段: 打开输⼊流
BufferedReader in=new BufferedReader(new InputStreamReader(
System.out.println("客户端发送的请求信息: ***************");
// 读取第⼀⾏, 请求地址
String adLine();
System.out.println(line);
String resource=line.substring(line.indexOf('/'),line.lastIndexOf('/')-5);
//获得请求的资源的地址
resource=URLDecoder.decode(resource, "UTF-8");//反编码 URL 地址
String method = new StringTokenizer(line).nextElement().toString();// 获取请求⽅法, GET 或者 POST
// 读取所有浏览器发送过来的请求参数头部信息
while( (line = in.readLine()) != null) {
System.out.println(line);
if(line.equals("")) break;
}
// 显⽰ POST 表单提交的内容, 这个内容位于请求的主体部分
if("POST".equalsIgnoreCase(method)) {
System.out.adLine());
}
System.out.println("请求信息结束 ***************");
System.out.println("⽤户请求的资源是:"+resource);
System.out.println("请求的类型是: " + method);
// GIF 图⽚就读取⼀个真实的图⽚数据并返回给客户端
dsWith(".gif")) {
fileService("images/test.gif", client);
closeSocket(client);
continue;
}
// 请求 JPG 格式就报错 404
dsWith(".jpg")) {
PrintWriter out=new OutputStream(),true);
out.println("HTTP/1.0 404 Not found");//返回应答消息,并结束应答
out.println();// 根据 HTTP 协议, 空⾏将结束头信息
out.close();
closeSocket(client);
continue;
} else {
// ⽤ writer 对客户端 socket 输出⼀段 HTML 代码
PrintWriter out=new OutputStream(),true);
out.println("HTTP/1.0 200 OK");//返回应答消息,并结束应答
out.println("Content-Type:text/html;charset=GBK");
out.println();// 根据 HTTP 协议, 空⾏将结束头信息
out.println("<h1> Hello Http Server</h1>");
out.println("你好, 这是⼀个 Java HTTP 服务器 demo 应⽤.<br>");
out.println("您请求的路径是: " + resource + "<br>");
out.println("这是⼀个⽀持虚拟路径的图⽚:<img src="abc.gif" mce_src="abc.gif"><br>" +
"<a href="abc.gif" mce_href="abc.gif">点击打开abc.gif, 是个服务器虚拟路径的图⽚⽂件.</a>");
out.println("<br>这是个会反馈 404 错误的的图⽚:<img src="test.jpg" mce_src="test.jpg"><br><a href="test.jpg" mce_href="test.jpg">点击打开test.jpg</a><br>");
out.println("<form method=post action='/'>POST 表单 <input name=username value='⽤户'> <input name=submit type=submit value=submit></form>");
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论