GuzzleHTTP 在现有页面上返回 404

GuzzleHTTP returns 404 on existing page

提问人: 提问时间:4/20/2019 更新时间:11/18/2023 访问量:8947

问:

我对 https://api.scarif.dev/auth 的 Guzzle POST 请求返回了 404,而该页面通过 Postman、浏览器或 javascript 存在。它应该返回带有 401 消息的 200,但 Guzzle 返回 404。在 POST 和 GET 模式下都是如此。

我尝试了多种客户端设置,包括不同的标头和禁用 SSL 验证,但没有成功。现在我已经复制了使其在 postman 中工作的完全相同的标题,但仍然没有成功。

我一直在搜索谷歌和stackoverflow,但找不到解决我问题的答案。

PHP中的请求:

<?php
$client = new Client([
    'header' => [
        'Accept' => 'application/json',
        'Content-Type' => 'application/x-www-form-urlencoded'
    ],
    'verify' => false
]);

$response = $client->request('POST', 'https://api.scarif.dev/auth', [
    'form_params' => []
]);

echo $response->getBody()->getContents();
?>

预期结果:

{
    "detail": "https://login.scarif.dev",
    "status": 401,
    "title": "Unauthorized",
    "type": "http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html"
}

实际结果:

致命错误:未捕获的 GuzzleHttp\Exception\ClientException:客户端 错误:导致响应: 404 未找到POST https://api.scarif.dev/auth404 Not Found

未找到 (截断...) 在 /home/admin/domains/login.scarif.dev/framework/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php:113 堆栈跟踪:#0 /home/admin/domains/login.scarif.dev/framework/vendor/guzzlehttp/guzzle/src/Middleware.php(66): GuzzleHttp\Exception\RequestException::create(Object(GuzzleHttp\Psr7\Request), 对象 (GuzzleHttp\Psr7\Response)) #1 /home/admin/domains/login.scarif.dev/framework/vendor/guzzlehttp/promises/src/Promise.php(203): GuzzleHttp\Middleware::GuzzleHttp{closure}(Object(GuzzleHttp\Psr7\Response)) 2 /home/admin/domains/login.scarif.dev/framework/vendor/guzzlehttp/promises/src/Promise.php(156):

GuzzleHttp\Promise\Promise::callHandler(1, 对象 (GuzzleHttp\Psr7\Response), 数组) #3 /home/admin/domains/login.scarif.dev/framework/ven 中 /home/admin/domains/login.scarif.dev/framework/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php 上线 113

API 端点控制器:

<?php

namespace Controller;

use Core\Config;
use Core\Request;
use Core\Response;
use Model\Token;
use Model\User;
use MongoDB\BSON\UTCDateTime;

class AuthController extends Controller
{
    public function view(User $user, Token $token)
    {
        extract(Request::getPostData());

        if (isset($access_token) && !empty($access_token)) {
            $_token = $token->getTokenByToken($access_token);

            if (
                $_token['type'] !== Token::TYPE_ACCESS_TOKEN ||
                $_token['expires_on'] <= new UTCDateTime()
            ) {
                return $this->view->display('json', [
                    'payload' => Response::apiResponse(
                        $this->config->get('url.login'), 401
                    )
                ]);
            }

            $token->delete($_token['_id']);

            $newToken = $token->create(Token::TYPE_ACCESS_TOKEN, $_token['user_id']);

            return $this->view->display('json', [
                'payload' => Response::apiResponse($newToken['token'])
            ]);
        }

        if (!isset($email) || !isset($password) || empty($email) || empty($password)) {
            return $this->view->display('json', [
                'payload' => Response::apiResponse(
                    $this->config->get('url.login'), 401
                )
            ]);
        }

        if (!$user->checkCredentials($email, $password)) {
            return $this->view->display('json', [
                'payload' => Response::apiResponse(
                    "The email address or password you've entered is invalid. Please check your entry and try again.",
                    422
                )
            ]);
        }

        $user = $user->getUserByEmail($email);
        $token = $token->create(Token::TYPE_ACCESS_TOKEN, $user['_id']);

        return $this->view->display('json', [
            'payload' => Response::apiResponse($token['token'])
        ]);
    }
}
php http-status-code-404 口大口

评论


答:

0赞 PtrTon 4/20/2019 #1

问题似乎来自您正在使用的 API。当将代码与不同的 url 一起使用时,它工作得很好:

$client = new Client([
    'header' => [
        'Accept' => 'application/json',
        'Content-Type' => 'application/x-www-form-urlencoded'
    ],
    'verify' => false
]);

$response = $client->request('POST', 'https://jsonplaceholder.typicode.com/posts', [
    'form_params' => []
]);

echo $response->getBody()->getContents();

您能展示 API 端点的代码吗?

评论

0赞 PtrTon 4/20/2019
据我所知,您的 API 在任何情况下都不会返回 404,这意味着您的请求甚至可能没有到达控制器。您是否尝试过返回一个简单的响应来查看是否调用了控制器操作?
0赞 4/20/2019
好吧,这很奇怪,我认为这是我的服务器设置。如果我指向 api.scarif.dev,它应该返回一个字符串,上面写着“欢迎来到 Scarif API”,但它返回“Apache 运行正常”。
0赞 4/20/2019
一切似乎都很好。Guzzle 的行为怎么可能与我正在使用的任何其他客户端不同?有没有办法检查 guzzle 最终得到的实际 url 是什么?查看是否有任何重定向处于活动状态或曾经发生过什么?我的代码中没有任何。
0赞 PtrTon 4/20/2019
考虑记录 Guzzle 的确切操作。像这样的事情应该有助于解决这个问题。
0赞 4/20/2019
嗯,看起来我的SSL通配符无法正常工作。它已通过 DirectAdmin 在 scarif.dev 上设置,但我已将 api.scarif.dev 和 login.scarif.dev 添加为单独的域,在它们上安装了相同的证书,但它们以自签名证书的形式返回,而我的浏览器显示不同。有趣:/
0赞 Ismail 2/16/2022 #2

我遇到了同样的问题,一直在寻找解决方案,直到我来到这里。虽然没有在网上得到任何帮助,其他人的解决方案对我不起作用,但后来我通过广泛的调试解决了自己,我正在分享解决方案,希望将来可以帮助其他人。

场景:在我的例子中,我有一个 API 网关,客户端(在我的情况下是 Postman)正在向 API 网关发出请求,网关又在 Laravel 8 中使用 Guzzle 7 向微服务发出请求。我曾经将我从客户端收到的所有标头按原样传递到微服务,这导致了 404 错误。当我更改它并仅将请求中我自己的标头传递给微服务时,出现了光,404 消失了。

这些是 Postman 的默认标头,我按原样传递请求:

{
    "authorization": [
        "Bearer eyJ0eXAiOiJKV1 .."
    ],
    "user-agent": [
        "PostmanRuntime/7.29.0"
    ],
    "accept": [
        "*/*"
    ],
    "postman-token": [
        "ca180f3a-ec65-4212-bd9f-dc294846dc65"
    ],
    "host": [
        "sagateway.com"
    ],
    "accept-encoding": [
        "gzip, deflate, br"
    ],
    "connection": [
        "keep-alive"
    ]
}

我删除了所有这些内容,只在标题中传递了一件事:

['Authorization' => "<Key Here>"]

然后它工作正常,经过几天的连续谷歌搜索,我松了一口气。