博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
php runtime 中 headers already sent 问题解决方案
阅读量:6042 次
发布时间:2019-06-20

本文共 3666 字,大约阅读时间需要 12 分钟。

问题

  • 问题1:
    最近有不少用户反馈使用 php runtime的时候遇见如下报错

Cannot modify header information - headers already sent by (output started at ...

  • 问题2:
    如果更改php 的session 目录?

本文旨在梳理此类问题的原因,触发条件以及相应的解法, 在介绍原因之前,先过一遍php runtime http trigger 使用的两种方式。

php runtime http trigger的使用姿势

使用 php runtime http trigger 的时候中一般有两种使用方式:

不使用 fcPhpCgiProxy

使用方法,当不需要进行部署较大的php工程的使用方法, 比如:

"v1", "custom_header2" => ["v2", "v3"], "Set-Cookie" => urlencode("test php") . '=' . urlencode('test;more') ), "hello world" ); }

注意:强烈建议您所有返回的headers都放在构造Response对象的参数里面,如上面示例,不要单独使用能改变header的方法,比如 header 、 setcookie 等

使用 fcPhpCgiProxy

此时的函数入口相当传统Apache/Nginx 的 conf 中 location, 将对应的php 文件送给 php-fpm 去解析,然后将解析后的结果返回给用户

详解fcPhpCgiProxy

image.png

  • 函数计算的执行环境相当于传统 web 服务的 Apache/Nginx
  • 用户函数相当于实现 Apache/Nginx 的 conf 中 location
  • 用户将 Web 网站部署在 NAS,然后挂载 NAS 到函数的执行环境,

函数计算为用户提供了一个 $GLOBALS['fcPhpCgiProxy'] 对象用来和 php-fpm 进行交互,对

PHP 工程中的 php 文件进行解析,该对象提供了两个重要的接口:

requestPhpCgi($request, $docRoot, $phpFile = "index.php", $fastCgiParams = [], $options = [])
  • requestPhpCgi

    • $request: 跟 php http invoke 入口的参数一致
    • $docRoot: Web 工程的根目录
    • $phpFile: 用于拼接 cgi 参数中的 SCRIPT_FILENAME 的默认参数
    • $fastCgiParams: 函数计算内部尽量根据 $request 给您构造 default cgi params, 但是如果您不是想要的,可以使用$fastCgiParams覆盖一些参数 (reference: )
    • $options: array类型,可选参数, debug_show_cgi_params 设为 true ,会打印每次请求 php 解析时候的 cgi 参数, 默认为 false ;readWriteTimeout 设置解析的时间, 默认为 5 秒

原因

错误出现的原因简单描述就是当php 收到第一个 output (print, echo, )时,它会flush所有收集到的headers。然后它可以发送它想要的所有输出。但是这个时候再发送HTTP header是不允许的。详情可以参考:

通常来说就是用户第一种方式(不使用 fcPhpCgiProxy) 使用http trigger的时候,使用如下方法可能会出现以下问题:

  • /
  • /
  • /

解法

  • 不使用 fcPhpCgiProxy

    "v1", "custom_header2" => ["v2", "v3"], "Set-Cookie" => urlencode("test php") . '=' . urlencode('test;more') ), "hello world");}

不单独使用能改变header的方法,比如 header 、 setcookie 等,将您所有返回的headers都放在构造Response对象的参数里面

  • 使用fcPhpCgiProxy

    至少两个文件, 一个入口函数文件,一个待解析的文件, for example:

    getAttribute("requestURI"); // parse $requestURI $proxy = $GLOBALS['fcPhpCgiProxy']; return $proxy->requestPhpCgi($request, __DIR__ . '/www', "a.php", ['SERVER_NAME' => 'abc.com']);}
    " . "\n";echo "Simple Virtual HTML Document" . "\n";echo "" . $body . "\n";echo "REQUESTHEADERS: " . "\n";foreach ($_SERVER as $key => $value) { if (strpos($key, 'HTTP_') === 0) { echo $key . " : " . $value . PHP_EOL; }}echo "QUERYSTRING: " . $_SERVER['QUERY_STRING'] . PHP_EOL;echo "

    " . "Virtual HTML" . "

    " . "

    " . "\n";echo "Hey look. I just created a virtual (yep. virtual) HTML document!" . "\n";echo "" . "\n";?>

    建议: 如果只是使用http trigger 实现类似一个api的功能,尽量不要使用fcPhpCgiProxy, 即不要单独使用改变header的方法; 如果是类似一个web的工程的开发或者迁移,尽量使用fcPhpCgiProxy

session 目录更改的姿势

由于函数计算serverless的特性,我们会把公共的东西放在nas目录,比如web 工程, 临时tmp缓存; 在php runtime使用场景中, session目录肯定是想放在nas 公共目录中的.

参考

只要是在php ini 可以设置的,我们都可以通过上述的方法达到目标,并且我们鼓励使用这种方法来裁剪不需要的extension, 比如针对session 设置,我们可以使用如下自定义的ini:

extension=session.soextension=ftp.soextension=shmop.soextension=bcmath.soextension=gettext.soextension=pcntl.soextension=simplexml.soextension=xmlreader.soextension=bz2.soextension=gmp.soextension=pdo.soextension=soap.soextension=xmlrpc.soextension=calendar.soextension=iconv.soextension=pdo_mysql.soextension=sockets.soextension=xmlwriter.soextension=ctype.soextension=imagick.soextension=phar.soextension=sysvmsg.soextension=dom.soextension=json.soextension=posix.soextension=sysvsem.soextension=exif.soextension=mbstring.soextension=protobuf.soextension=sysvshm.soextension=fileinfo.soextension=mysqli.soextension=redis.soextension=zip.soextension=memcached.soextension=tokenizer.sosession.save_path=/mnt/wwwsession.auto_start=1

最后两句用于session的设置,设置到nas的 /mnt/www 目录 并且自动开启

转载地址:http://itghx.baihongyu.com/

你可能感兴趣的文章
2019-4-23 plan
查看>>
[编解码] 关于base64编码的原理及实现
查看>>
WinDbg配置和使用基础
查看>>
转:Object-Runtime的基本数据类型
查看>>
JMJS系统总结系列----Jquery分页扩展库(五)
查看>>
Excel技巧之——英文大小写转换(转)
查看>>
Google 翻译的妙用
查看>>
常用的集合
查看>>
Unity3D工程源码目录
查看>>
杀死进程命令
查看>>
cookie 和session 的区别详解
查看>>
Mongodb对集合(表)和数据的CRUD操作
查看>>
Target runtime Apache Tomcat is not defined.错误解决方法
查看>>
VC++ 监视文件(夹)
查看>>
【转】keyCode对照表及JS监听组合按键
查看>>
[Java开发之路](14)反射机制
查看>>
mac gentoo-prefix安装git svn
查看>>
浅尝异步IO
查看>>
C - Train Problem II——(HDU 1023 Catalan 数)
查看>>
Speak loudly
查看>>