route () 函数将 https 渲染成了 http

部署到 Heroku 上后发现 route() 函数将 https 渲染成了 http
file
没找到问题所有,请知道的同学如果有时间帮忙解答下.
谢谢.

《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
讨论数量: 5

追了一下源码,渲染成 http:// 的原因可能如下:
route 函数的定义在 /vendor/laravel/framework/src/Illuminate/Routing/Redirector.php 中:

/**
 * Create a new redirect response to a named route.
 *
 */
public function route($route, $parameters = [], $status = 302, $headers = [])
{
    return $this->to($this->generator->route($route, $parameters), $status, $headers);
}

注意其中的 to 方法:

/**
 * Create a new redirect response to the given path.
 *
 */
public function to($path, $status = 302, $headers = [], $secure = null)
{
    return $this->createRedirect($this->generator->to($path, [], $secure), $status, $headers);
}

传递了一个 $secure 参数给到 generatorto 方法,且默认值为 null ,找到 /vendor/laravel/framework/src/Illuminate/Routing/UrlGenerator.php 中的定义:

/**
 * Generate an absolute URL to the given path.
 */
public function to($path, $extra = [], $secure = null)
{
    ……
    $root = $this->formatRoot($this->formatScheme($secure));
}

$secure 参数传递到了 formatScheme 方法,找到定义:

/**
 * Get the default scheme for a raw URL.
 */
public function formatScheme($secure)
{
    if (! is_null($secure)) {
        return $secure ? 'https://' : 'http://';
    }

    if (is_null($this->cachedSchema)) {
        $this->cachedSchema = $this->forceScheme ?: $this->request->getScheme().'://';
    }
    return $this->cachedSchema;
}

可以看到,当 $secure 不为空时,会根据 $secure 的值来选择 https 还是 http;如果 $secure 为空,则会去检查 $cachedSchema 的值并返回,如果 $cachedSchema 的值为空,则会根据 $forceScheme 的值来进行设定,如果 $forceScheme 的值为空,则会调用 getScheme 方法来进行相关的设置,找到 /vendor/symfony/http-foundation/Request.php 中的定义:

/**
 * Gets the request's scheme.
 */
public function getScheme()
{
    return $this->isSecure() ? 'https' : 'http';
}

此处会通过 isSecure 方法来检查安全性配置:

/**
 * Checks whether the request is secure or not.
 *
 * This method can read the client protocol from the "X-Forwarded-Proto" header
 * when trusted proxies were set via "setTrustedProxies()".
 *
 * The "X-Forwarded-Proto" header must contain the protocol: "https" or "http".
 *
 * If your reverse proxy uses a different header name than "X-Forwarded-Proto"
 * ("SSL_HTTPS" for instance), configure it via the $trustedHeaderSet
 * argument of the Request::setTrustedProxies() method instead.
 *
 * @return bool
 */
public function isSecure()
{
    …… 重点看注释
}

如果使用了教程中的默认设置,最终返回的链接是否启用 https:// 是由服务器的相关配置决定的。 herokuapp.com 这个域名是有 SSL 证书的,如果要渲染出 https:// 链接,方法有两个:1.修改 heroku 上的相关配置;2.设定 $forceScheme 的值,强制启用 HTTPS

5年前 评论
堂堂糖唐

最简单的处理方式,修改nginx代理fpm配置:

server {
    listen      80;
    server_name www.a.com;
    root        /www/code;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        fastcgi_pass    127.0.0.1:9000;
        fastcgi_param   HTTPS on;
        fastcgi_param   SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include         fastcgi_params;
    }
}

注意fastcgi_param HTTPS on;

3年前 评论
Echos

应该是跟你的服务器配置有关系,具体原因百度你应该可以得到你想要的答案

5年前 评论
Shuyi

.env文件里面, APP_URLHTTP:// 改成 HTTPS:// 试试?

5年前 评论

追了一下源码,渲染成 http:// 的原因可能如下:
route 函数的定义在 /vendor/laravel/framework/src/Illuminate/Routing/Redirector.php 中:

/**
 * Create a new redirect response to a named route.
 *
 */
public function route($route, $parameters = [], $status = 302, $headers = [])
{
    return $this->to($this->generator->route($route, $parameters), $status, $headers);
}

注意其中的 to 方法:

/**
 * Create a new redirect response to the given path.
 *
 */
public function to($path, $status = 302, $headers = [], $secure = null)
{
    return $this->createRedirect($this->generator->to($path, [], $secure), $status, $headers);
}

传递了一个 $secure 参数给到 generatorto 方法,且默认值为 null ,找到 /vendor/laravel/framework/src/Illuminate/Routing/UrlGenerator.php 中的定义:

/**
 * Generate an absolute URL to the given path.
 */
public function to($path, $extra = [], $secure = null)
{
    ……
    $root = $this->formatRoot($this->formatScheme($secure));
}

$secure 参数传递到了 formatScheme 方法,找到定义:

/**
 * Get the default scheme for a raw URL.
 */
public function formatScheme($secure)
{
    if (! is_null($secure)) {
        return $secure ? 'https://' : 'http://';
    }

    if (is_null($this->cachedSchema)) {
        $this->cachedSchema = $this->forceScheme ?: $this->request->getScheme().'://';
    }
    return $this->cachedSchema;
}

可以看到,当 $secure 不为空时,会根据 $secure 的值来选择 https 还是 http;如果 $secure 为空,则会去检查 $cachedSchema 的值并返回,如果 $cachedSchema 的值为空,则会根据 $forceScheme 的值来进行设定,如果 $forceScheme 的值为空,则会调用 getScheme 方法来进行相关的设置,找到 /vendor/symfony/http-foundation/Request.php 中的定义:

/**
 * Gets the request's scheme.
 */
public function getScheme()
{
    return $this->isSecure() ? 'https' : 'http';
}

此处会通过 isSecure 方法来检查安全性配置:

/**
 * Checks whether the request is secure or not.
 *
 * This method can read the client protocol from the "X-Forwarded-Proto" header
 * when trusted proxies were set via "setTrustedProxies()".
 *
 * The "X-Forwarded-Proto" header must contain the protocol: "https" or "http".
 *
 * If your reverse proxy uses a different header name than "X-Forwarded-Proto"
 * ("SSL_HTTPS" for instance), configure it via the $trustedHeaderSet
 * argument of the Request::setTrustedProxies() method instead.
 *
 * @return bool
 */
public function isSecure()
{
    …… 重点看注释
}

如果使用了教程中的默认设置,最终返回的链接是否启用 https:// 是由服务器的相关配置决定的。 herokuapp.com 这个域名是有 SSL 证书的,如果要渲染出 https:// 链接,方法有两个:1.修改 heroku 上的相关配置;2.设定 $forceScheme 的值,强制启用 HTTPS

5年前 评论

这个问题困扰了我几天,解决方案记录一下:

如果你前端用了 SLB 的话,后端默认是 80 端口,需要在 SLB 中设置 X-Forwarded-Proto,同时修改 TrustProxies.php 这个 Middleware 加入相关的前端代理服务器 IP,官网文档参见

https://learnku.com/docs/laravel/6.x/requests#conf...

4年前 评论
堂堂糖唐

最简单的处理方式,修改nginx代理fpm配置:

server {
    listen      80;
    server_name www.a.com;
    root        /www/code;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        fastcgi_pass    127.0.0.1:9000;
        fastcgi_param   HTTPS on;
        fastcgi_param   SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include         fastcgi_params;
    }
}

注意fastcgi_param HTTPS on;

3年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!