Laravel 响应准备
public function prepareResponse($request, $response)
{
if ($response instanceof PsrResponseInterface) {
$response = (new HttpFoundationFactory)->createResponse($response);
}
// 若不是 \Symfony\Component\HttpFoundation\SymfonyResponse 的对象,则构造成此对象
elseif (! $response instanceof SymfonyResponse) {
$response = new Response($response);
}
return $response->prepare($request);
}
PsrResponseInterface 类型
public function createResponse(ResponseInterface $psrResponse)
{
$response = new Response(
$psrResponse->getBody()->__toString(),
$psrResponse->getStatusCode(),
$psrResponse->getHeaders()
);
$response->setProtocolVersion($psrResponse->getProtocolVersion());
foreach ($psrResponse->getHeader('Set-Cookie') as $cookie) {
$response->headers->setCookie($this->createCookie($cookie));
}
return $response;
}
本质就是用的 Response 类
Response 构建
public function __construct($content = '', $status = 200, $headers = array())
{
$this->headers = new ResponseHeaderBag($headers);
$this->setContent($content);
$this->setStatusCode($status);
$this->setProtocolVersion('1.0');
// Deprecations
$class = get_class($this);
if ($this instanceof \PHPUnit_Framework_MockObject_MockObject || $this instanceof \Prophecy\Doubler\DoubleInterface) {
$class = get_parent_class($class);
}
if (isset(self::$deprecationsTriggered[$class])) {
return;
}
self::$deprecationsTriggered[$class] = true;
foreach (self::$deprecatedMethods as $method) {
$r = new \ReflectionMethod($class, $method);
if (__CLASS__ !== $r->getDeclaringClass()->getName()) {
@trigger_error(sprintf('Extending %s::%s() in %s is deprecated since version 3.2 and won\'t be supported anymore in 4.0 as it will be final.', __CLASS__, $method, $class), E_USER_DEPRECATED);
}
}
}
public function setContent($content)
{
if (null !== $content && !is_string($content) && !is_numeric($content) && !is_callable(array($content, '__toString'))) {
throw new \UnexpectedValueException(sprintf('The Response content must be a string or object implementing __toString(), "%s" given.', gettype($content)));
}
$this->content = (string) $content;
return $this;
}
public function setStatusCode($code, $text = null)
{
$this->statusCode = $code = (int) $code;
if ($this->isInvalid()) {
throw new \InvalidArgumentException(sprintf('The HTTP status code "%s" is not valid.', $code));
}
if (null === $text) {
$this->statusText = isset(self::$statusTexts[$code]) ? self::$statusTexts[$code] : 'unknown status';
return $this;
}
if (false === $text) {
$this->statusText = '';
return $this;
}
$this->statusText = $text;
return $this;
}
public function isInvalid()
{
return $this->statusCode < 100 || $this->statusCode >= 600;
}
public function setProtocolVersion($version)
{
$this->version = $version;
return $this;
}
响应准备
主要是设置响应头
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 {
if (!$headers->has('Content-Type')) {
$format = $request->getRequestFormat();
# static::$formats = array(
# 'html' => array('text/html', 'application/xhtml+xml'),
# 'txt' => array('text/plain'),
# 'js' => array('application/javascript', 'application/x-javascript', 'text/javascript'),
# 'css' => array('text/css'),
# 'json' => array('application/json', 'application/x-json'),
# 'xml' => array('text/xml', 'application/xml', 'application/x-xml'),
# 'rdf' => array('application/rdf+xml'),
# 'atom' => array('application/atom+xml'),
# 'rss' => array('application/rss+xml'),
# 'form' => array('application/x-www-form-urlencoded'),
# );
if (null !== $format && $mimeType = $request->getMimeType($format)) {
$headers->set('Content-Type', $mimeType);
}
}
// 设置编码格式
$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')) {
$headers->set('Content-Type', $headers->get('Content-Type').'; charset='.$charset);
}
// 若传输时用分块编码,则移除 Content-Length, 因为采用分块编码时可以知道传输何时完成
if ($headers->has('Transfer-Encoding')) {
$headers->remove('Content-Length');
}
if ($request->isMethod('HEAD')) {
$length = $headers->get('Content-Length');
$this->setContent(null);
if ($length) {
$headers->set('Content-Length', $length);
}
}
}
if ('HTTP/1.0' != $request->server->get('SERVER_PROTOCOL')) {
$this->setProtocolVersion('1.1');
}
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;
}
public function isInformational()
{
return $this->statusCode >= 100 && $this->statusCode < 200;
}
protected function ensureIEOverSSLCompatibility(Request $request)
{
if (false !== stripos($this->headers->get('Content-Disposition'), 'attachment') && preg_match('/MSIE (.*?);/i', $request->server->get('HTTP_USER_AGENT'), $match) == 1 && true === $request->isSecure()) {
if ((int) preg_replace('/(MSIE )(.*?);/', '$2', $match[0]) < 9) {
$this->headers->remove('Cache-Control');
}
}
}