1

代码仓库:https://github.com/jczzq/cool...

HTTP 知识提要

HTTP(超文本传输协议)是一个客户端(浏览器)和服务端(服务器)用于请求响应的标准。记录http请求和响应信息的代码称为报文

HTTP动作

HTTP/1.1协议中共定义了八种方法来操作指定的资源:GET、HEAD、 POST、 PUT、 DELETE、 TRACE、 OPTIONS、 CONNECT

HTTP报文

HTTP报文由4个部分组成:

  • 请求(响应)行(第一行,以下将称为起始行
  • 头字段(第一行之后,明文字符串,以冒号分隔的键名与键值对,以回车(CR)加换行(LF)符号序列结尾。)
  • 空行
  • 请求体(可选的HTTP报文主体数据)

HTTP头字段

HTTP头字段(HTTP header fields)是指在HTTP的请求和响应消息中的消息头部分。它们定义了一个超文本传输协议事务中的操作参数。HTTP头字段根据实际用途被分为以下 4 种类型:

  • 通用头字段(General Header Fields):同时适用于请求和响应消息,但与最终消息主体中传输的数据无关的消息头。
  • 请求头字段(Request Header Fields):包含更多有关要获取的资源或客户端本身信息的消息头。
  • 响应头字段(Response Header Fields):包含有关响应的补充信息,如其位置或服务器本身(名称和版本等)的消息头。
  • 实体头字段(Entity Header Fields):包含有关实体主体的更多信息,比如主体长(Content-Length)度或其MIME类型。

请求方的头结构:通用报头 | 请求报头 | 实体报头
响应方的头结构:通用报头 | 响应报头 | 实体报头

需要注意的是请求头并不是按照我们理解的语义化分类,而是按照RFC文件标准已经归类。Accept属于请求头, Content-Type属于实体头。HTTP头部字段可以自己根据需要定义,因此可能在 Web 服务器和浏览器上发现非标准的头字段。,按照惯例,非标准的协议头字段是在字段名称前加上X-前缀来标识。但这一惯例已在2012年6月被废弃,因为按照这种惯例,非标准字段变成标准字段时会引起很多不方便之处。

准备工作

这是我的测试表单:

<form :action="form.action"
    :method="form.method"
    :enctype="form.enctype">
    <fieldset>
        <legend>
            {{ form.name }} | action="{{ form.action }}" | method="{{ form.method }}" | enctype="{{ form.enctype }}"
        </legend>
        <p>
            <label for="name"> action: </label>
            <input type="text" name="action" v-model="form.action" placeholder="aciton">
        </p>
        <p>
            <label for="name"> name: </label>
            <input type="text" name="name" v-model="form.name" placeholder="name">
        </p>
        <p>
            <label for="method"> method: </label>
            <select name="method" v-model="form.method">
                <option v-for="item in METHODS" :key="item" :value="item">{{item}}</option>
            </select>
        </p>
        <p>
            <label for="enctype"> enctype: </label>
            <select name="enctype" v-model="form.enctype">
                <option v-for="item in ENCTYPES" :key="item" :value="item">{{item}}</option>
            </select>
        </p>
        <p>
            <label for="avatar"> 头像: </label>
            <input type="file" name="avatar" placeholder="头像">
        </p>
    </fieldset>
    <p class="p-4 p-r-0 text-right">
        <input type="submit" value="提交">
    </p>
</form>

服务端脚本:

const path = require('path');
const express = require('express');
var app = express();

// 设置静态文件目录
app.use(express.static(path.resolve('./static')));
console.info('静态文件目录:', path.resolve('./static'));

// 首页
app.get('/', function(req, res) {
    res.sendFile(path.join(__dirname, './index.html'));
});

app.use('/user', (req, res, next) => {
    // return res.json({
    //     query: req.query,
    //     params: req.params,
    //     body: req.body
    // });
    return res.sendStatus(200);
});

app.listen(3000, '0.0.0.0', () => {
    console.log('启动服务器: http://localhost:3000');
});

1. 表单提交时表单内的数据将会被如何处理?

表单提交有三个关键的属性:action,method,enctype。这三个参数分别指定了http请求消息的路径、动作、消息实体如何编码。前两者不做赘述,下面仔细说enctype属性。HTML5 Form的enctype有三个枚举值:

  • application/x-www-form-urlencoded
    Form表单默认编码方式,method="GET"时表单值内会自动处理成(?name1=value1&name2=value2...)结构的参数并追加到action指定的url之后。
  • multipart/form-data
    表单内有文件提交必选的编码格式。
  • text/plain
    表单数据以纯文本形式进行编码。

application/x-www-form-urlencoded

clipboard.png
clipboard.png

可以看到表单GET提交的数据默认采取了application/x-www-form-urlencoded编码。被追加到url后面。服务端默认响应的Content-Type是text/plain纯文本。

clipboard.png
clipboard.png

再来看看表单POST提交的报文,请求报文头字段Content-Type明文显示application/x-www-form-urlencoded,响应报文头字段Content-Type依然是默认的text/plain纯文本。

multipart/form-data

接下来看看第二个multipart/form-data,并且上传一个图片23333.jpg
clipboard.png

clipboard.png

观察请求报文,头字段Content-Type是我们设定的multipart/form-data,并且制定了一个特定的值boundary,请求实体被编码变成了一整条消息,里面的数据由分隔符boundary分割成了多个部分,每一个部分的描述不尽相同,其中我们上传的文件23333.jpg已经处理成了乱码。

text/plain

接下来看看第三个text/plain,依然上传一个图片23333.jpg
clipboard.png
clipboard.png

头字段Content-Type是我们设定的text/plain纯文本,服务端响应的也是纯文本。

参考链接

HTTP头字段 - Wikipedia
HTTP Headers - MDN
关于HTTP Content-Type说明

如有不足,欢迎指正。


jczzq
33 声望1 粉丝

死宅程序员