Laravel Response Headers Setting

简介

上一章,我们了解了响应预处理的原理。

这里做一下总结:

响应预处理:即把我们控制器返回的各式各样的数据类型,统一转换成 Response 类对象,且根据控制器返回的数据,设置 Response 对象的内容体。内容体,即是我们浏览器看到的内容或者前端接收到的 json 字符串。

这一章呢,就是关于 Response 响应头数据设置。

响应头数据的初始化

还记的上一章 Response 构造函数里面有关于 响应头 数据的源码吗,我们来看一下

Symfony\Component\HttpFoundation\Response

public function __construct($content = '', int $status = 200, array $headers = array())
{
    // 实例化响应头数据对象
    $this->headers = new ResponseHeaderBag($headers);
    $this->setContent($content);
    $this->setStatusCode($status);
    $this->setProtocolVersion('1.0');
}

接下来我们看一下 响应头数据对象 实例化时都做了什么

Symfony\Component\HttpFoundation\ResponseHeaderBag

public function __construct(array $headers = array())
{
    // 首先将传进来的 $headers 加进当前响应头数据中,当前没有传 $headers,先不管。
    parent::__construct($headers);

    // 初始化 Cache-Control 响应头信息
    if (!isset($this->headers['cache-control'])) {
        $this->set('Cache-Control', '');
    }

    // 初始化 Date 头信息
    if (!isset($this->headers['date'])) {
        $this->initDate();
    }
}
  • Cache-Control

    通用消息头字段,被用于在 http 请求和响应中,通过指定指令来实现缓存机制。缓存指令是单向的, 这意味着在请求设置的指令,在响应中不一定包含相同的指令。

    服务器可以在响应中使用的标准 Cache-Control 指令。

    Cache-control: must-revalidate

    Cache-control: no-cache

    Cache-control: no-store

    Cache-control: no-transform

    Cache-control: public

    Cache-control: private

    Cache-control: proxy-revalidate

    Cache-control: max-age=<seconds>

    Cache-control: s-maxage=<seconds>

    更多详细的说明--->传送门

  • Date

    是一个通用首部,其中包含了报文创建的日期和时间。

    • 语法

    Date: <day-name>, <day> <month> <year> <hour>:<minute>:<second> GMT

    • 例如

    Date: Wed, 21 Oct 2015 07:28:00 GMT

    • GMT 是什么

    格林尼治标准时间。 在HTTP协议中,时间都是用格林尼治标准时间来表示的,而不是本地时间。

    更多详细的说明--->传送门

Respnse Prepare 方法

Prepare 方法:Respnse Headers Setting 正式方法。。。

Symfony\Component\HttpFoundation\Response

public function prepare(Request $request)
{
    // 获取上面初始化的 响应头数据对象
    $headers = $this->headers;

    if ($this->isInformational() || $this->isEmpty()) {
        /* 
         * 如果 HTTP 状态码是 100、101、204、304。。。
         * 则内容变成空,移除 Content-Type,Content-Length。
         */
        $this->setContent(null);
        $headers->remove('Content-Type');
        $headers->remove('Content-Length');
    } else {        
        /* 
         * 根据请求的 _format 获取对应 mimeType,并设置 Content-Type
         */
        if (!$headers->has('Content-Type')) {
            $format = $request->getRequestFormat();
            if (null !== $format && $mimeType = $request->getMimeType($format)) {
                $headers->set('Content-Type', $mimeType);
            }
        }

        /*
         * 在 Content-Type 后面追加 Charset。。
         */
        $charset = $this->charset ?: 'UTF-8';
        if (!$headers->has('Content-Type')) {
            $headers->set('Content-Type', 'text/html; charset='.$charset);
        } elseif (0 === stripos($headers->get('Content-Type'), 'text/') && false === stripos($headers->get('Content-Type'), 'charset')) {
            // add the charset
            $headers->set('Content-Type', $headers->get('Content-Type').'; charset='.$charset);
        }

        /*
         * 有我没他,有他没我。(Transfer-Encoding 与 Content-Length 不共戴天)
         */
        if ($headers->has('Transfer-Encoding')) {
            $headers->remove('Content-Length');
        }

        /*
         * 如果请求 HEAD 方法,移除内容,重新设定 Content-Length
         */
        if ($request->isMethod('HEAD')) {
            // cf. RFC2616 14.13
            $length = $headers->get('Content-Length');
            $this->setContent(null);
            if ($length) {
                $headers->set('Content-Length', $length);
            }
        }
    }

    /*
     * SERVER_PROTOCOL 不是 1.0 那就是 1.1
     */
    if ('HTTP/1.0' != $request->server->get('SERVER_PROTOCOL')) {
        $this->setProtocolVersion('1.1');
    }

    /*
     * 1.0 的 HTTP 协议,响应头 Cache-Control:no-cache; 需要 pragma 和 expires。
     */
    if ('1.0' == $this->getProtocolVersion() && false !== strpos($this->headers->get('Cache-Control'), 'no-cache')) {
        $this->headers->set('pragma', 'no-cache');
        $this->headers->set('expires', -1);
    }

    // 兼容 IE9 一下的响应头协议,谁用 < IE9,就掐死他。
    $this->ensureIEOverSSLCompatibility($request);

    return $this;
}
  • 这里重点说一下,HTTP 响应码 : 204

    204 No Content。

    成功状态响应码表示目前请求成功,但客户端不需要更新其现有页面。204 响应默认是可以被缓存的。在响应中需要包含头信息 ETag。

    使用惯例是,在 PUT 请求中进行资源更新,但是不需要改变当前展示给用户的页面,那么返回 204 No Content。如果新创建了资源,那么返回 201 Created 。如果页面需要更新以反映更新后的资源,那么需要返回 200 。

    这段的原文地址--->传送门

最后

关于 响应头 和 响应码 说一点:

我就是想说:如果想了解其它响应头设置,上面那些传送门的兄弟内容,大家尽管看。。

本篇如有错误、不当或者需补充的内容,请各位同僚多提宝贵意见。

本文章首发在 LearnKu.com 网站上。
上一篇 下一篇
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
讨论数量: 0
发起讨论 只看当前版本


暂无话题~