【问题标题】:Which part sets `Content-Type` to `text/HTML` in response哪个部分将“Content-Type”设置为“text/HTML”作为响应
【发布时间】:2017-07-27 17:31:00
【问题描述】:

这里是一些 Laravel 的路线代码:

Route::get('a', function() {
    return 'hello';
});

调用此路由,Content-Type 标头值为text/HTML

这种默认行为从何而来?是否设置:

  • Nginx?
  • PHP?
  • Laravel?

【问题讨论】:

  • 你为什么在乎?你想解决什么问题?
  • Symphony 在 Symfony\Component\HttpFoundation\Response 这是 laravel 响应的基类。

标签: php laravel nginx laravel-5 laravel-5.4


【解决方案1】:

Laravel 扩展了 Symphony 的请求/响应,但仍然与它们的默认行为密切相关。此特定功能基于 Symphony 的 Response::prepare 函数。

public function prepare(Request $request)
{
    //does a lot of things, would not go into detail
        // Content-type based on the Request
        if (!$headers->has('Content-Type')) {
            $format = $request->getRequestFormat();
            if (null !== $format && $mimeType = $request->getMimeType($format)) {
                $headers->set('Content-Type', $mimeType);
            }
        }
 //Does a lot more things
}

这是基于$request->getMimeType($format)函数,$format来自$request->getRequestFormat()

public function getRequestFormat($default = 'html')
{
    if (null === $this->format) {
        $this->format = $this->attributes->get('_format');
    }
    return null === $this->format ? $default : $this->format;
}

请注意,当没有明确设置请求格式时,默认值是“html”。如果您还没有明确设置它,它也只会被设置。

mime 类型基于在 https://github.com/symfony/http-foundation/blob/master/Request.php#L1844 初始化的查找

该框架确实超越了这个级别,并提供了替代响应类型,例如JsonResponse(当你做 response()->json() 时 laravel 使用什么)并且这个响应使用不同的默认值。

【讨论】:

    【解决方案2】:

    使用路由时,laravel 会设置 header 值。这是symfony/http-foundation/Response.php的摘录

    public function __construct($content = '', $status = 200, $headers = array())
    {
        $this->headers = new ResponseHeaderBag($headers);
        $this->setContent($content);
        $this->setStatusCode($status);
        $this->setProtocolVersion('1.0');
    
        /* RFC2616 - 14.18 says all Responses need to have a Date */
        if (!$this->headers->has('Date')) {
            $this->setDate(\DateTime::createFromFormat('U', time()));
        }
    }
    

    希望这会有所帮助!

    【讨论】:

    • github.com/symfony/http-foundation/blob/master/… prepare 在准备响应时也会这样做
    • 谢谢!我在你的回答中看不到任何关于Content-Type的信息,我错过了什么吗?
    • @apokryfos 我认为您是对的,请随时发表您的评论作为答案。
    • $this->setContent($content);
    【解决方案3】:

    laravel 会自动将字符串转换成完整的 HTTP 响应。

    我在 symfony/http-foundation/response.php 中找到了这个方法。可能是此方法用于创建响应标头。

     public function prepare(Request $request)
     {
        $headers = $this->headers;
    
        if ($this->isInformational() || $this->isEmpty()) {
            $this->setContent(null);
            $headers->remove('Content-Type');
            $headers->remove('Content-Length');
        } else {
            // Content-type based on the Request
           if (!$headers->has('Content-Type')) {
                $format = $request->getRequestFormat();
                if (null !== $format && $mimeType = $request->getMimeType($format)) {
                    $headers->set('Content-Type', $mimeType);
                }
            }
    
            // Fix Content-Type
            $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);
            }
    
            // Fix Content-Length
            if ($headers->has('Transfer-Encoding')) {
                $headers->remove('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);
                }
            }
        }
    
        // Fix protocol
        if ('HTTP/1.0' != $request->server->get('SERVER_PROTOCOL')) {
            $this->setProtocolVersion('1.1');
        }
    
        // Check if we need to send extra expire info headers
        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);
        }
    
        $this->ensureIEOverSSLCompatibility($request);
    
        return $this;
    } 
    

    【讨论】:

    • 我不确定你的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-13
    • 2013-02-25
    • 1970-01-01
    • 2018-12-27
    • 2011-10-04
    • 1970-01-01
    相关资源
    最近更新 更多