如何在Laravel Web程序里面调用自己的API

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在Laravel Web程序里面调用自己的API相关的知识,希望对你有一定的参考价值。

根据你的描述明显应该是放在 web.php 中。
因为你只是普通的 web 项目,web.php 中的路由使用了 web middleware group 。
protected $middlewareGroups = [
\'web\' => [
\\App\\Http\\Middleware\\EncryptCookies::class,
\\Illuminate\\Cookie\\Middleware\\AddQueuedCookiesToResponse::class,
\\Illuminate\\Session\\Middleware\\StartSession::class,
\\Illuminate\\View\\Middleware\\ShareErrorsFromSession::class,
\\App\\Http\\Middleware\\VerifyCsrfToken::class,
\\Illuminate\\Routing\\Middleware\\SubstituteBindings::class,
],
\'api\' => [
\'throttle:60,1\',
\'bindings\',
],
];
如果你把 ajax 的路由放在 api.php 中,没有csrf 保护,很容易造成程序上的漏洞,公共资源请求除外。
api.php 配合Laravel passport 来使用提供 API 服务。
参考技术A 这COM技术的一种,可以做成GUI EXE, 象Word, Excel;也可以做成Service. 从CoRegisterClassObject(...)看起吧, COM是Windows的一大支柱,但弄明白了它, 你也就可以当老大了.

使用我自己的 Laravel API 时如何遵循不要重复自己的原则?

【中文标题】使用我自己的 Laravel API 时如何遵循不要重复自己的原则?【英文标题】:How Follow the Don't Repeat Yourself Principle When Consuming My Own Laravel API? 【发布时间】:2013-05-07 09:45:32 【问题描述】:

我正在开发一个 Laravel 4 应用程序,它将通过 JSON REST API 和 Web UI 对我的数据集进行相同的 CRUD 操作。似乎为了防止违反 DRY 原则,我的 UI 应该通过将所有请求从 UI 路由回 API 来使用我自己的 API。虽然我不确定完成这项工作的最佳方法。大概我会有单独的 UI 和 API 控制器,并以某种方式路由请求。还是我应该考虑完全不同的方法?

【问题讨论】:

【参考方案1】:

如果您正在寻找内部使用护照登录api,那么您需要将参数添加到原始请求中:

    protected function manualLogin(Request $request)
    
        $email = $request->input('email');
        $password = $request->input('password');

        $request->request->add([
        'username' => $email,
        'password' => $password,
        'grant_type' => 'password',
        'client_id' => $clientID,
        'client_secret' => $clientSecret,
        'scope' => '*']);

    $newRequest = Request::create('/oauth/token', 'post');

    return Route::dispatch($newRequest)->getContent();

【讨论】:

【参考方案2】:

如果您使用自己的 API,请使用 app()->handle() 而不是 Derek MacDonald 建议的 Route::dispatch()

app()->handle() 创建一个新请求,而Route::dispatch() 在堆栈中运行路由,有效地忽略了作为您正在发送的请求的一部分的参数。

编辑:提醒一下。泰勒奥特威尔advises against using sub-requests to make internal API calls, as they mess the current route。您可以使用像 Guzzle 这样的 HTTP API 客户端来进行 API 调用。

【讨论】:

【参考方案3】:

您可以使用Optimus API consumer,API 简洁明了,例如发出内部请求:

$response = app()->make('apiconsumer')->post('/oauth/token', $data);

在它的核心中,它使用Illuminate\Routing\RouterIlluminate\Http\Request 进行调用

// create the request
$this->request->create($uri, $method, $data, [], [], $server, $content);

// get the response
$response = $this->router->prepareResponse($request, $this->app->handle($request));

【讨论】:

【参考方案4】:

Taylor Otwell suggested 使用 app()->handle() 而不是 Route::dispatch() 来实现干净的请求。

对于Route::dispatch($request),我注意到您的非 GET 请求的端点(HTTP 请求正文上的参数)是否使用注入的依赖项 \Illuminate\Http\Request\Illuminate\Foundation\Http\FormRequest 扩展实例、参数状态、cookie、文件等. 来自原始 HTTP 请求。即,用于您的应用程序的控制器操作方法。

如果您的应用控制器和 API 控制器的参数名称和发布方法类型相同,您将不会注意到差异,因为原始参数值已传递。但是当你手动组装Request::create()的第三个参数时,Route::dispatch()会导致它被忽略。

app()->handle() 修复了 Laravel 请求生命周期中的上下文问题。

警告: app()->handle() 影响 Illuminate\Support\Facades\Request,用这个新的请求实例刷新它。作为连锁效应,在app()->handle() 之后调用Request::isXmlHttpRequest()redirect()->back() 之类的调用将导致不可预知的行为。我建议您跟踪原始请求的上下文,而改用redirect()->to(route('...')),这样您就可以严格控制应用的流程和状态。

考虑到所有这些极端情况,最好只使用Guzzle HTTP client 进行手动卷曲。

【讨论】:

Guzzle HTTP 出于某种原因在执行 php artisan serve 时挂起应用程序(使用我的 IIS 就可以了)。这个 app()->handle() 拯救了一天。 @GTHell 已经一年了,所以也许你已经弄清楚了,但是对于可能碰巧遇到这个的其他人来说,原因是因为 php 的内置服务器(工匠服务使用)只能处理单连接。 也可能是 Guzzle 及其与 80 以外的端口有关的问题:***.com/questions/29017526/…【参考方案5】:

注意:正如 vcardillo 在下面指出的,这些方法不会调用路由过滤器。

我目前正在做同样的事情,Jason 的回答让我朝着一个伟大的方向前进。查看Symfony\Component\HttpFoundation\Request 文档,我知道了如何发布,以及我需要做的所有其他事情。假设您使用的是表单,这里有一些可以帮助您的代码:

获取:

$request = Request::create('/api/users/1', 'GET');

$response = Route::dispatch($request);

发布:

$request = Request::create('/api/users/1', 'POST', Input::get());

$response = Route::dispatch($request);

带有 cookie 的 POST

$request = Request::create('/api/users/1', 'POST', Input::get(), Cookie::get('name'));

$response = Route::dispatch($request);

POST 带文件

$request = Request::create('/api/users/1', 'POST', Input::get(), null, Input::file('file'));

$response = Route::dispatch($request);

我希望这对其他人有所帮助。如果你没有使用表单,或者你没有使用 Laravel 的 Input / Cookie 门面,请将 Input / Cookie 门面替换为你自己的内容。

【讨论】:

我在所有这些中看到的唯一问题是没有调用路由过滤器。 链接已损坏,正在更新:api.symfony.com/master/Symfony/Component/HttpFoundation/… 这会导致同一个 api 服务器上的请求超时 :(【参考方案6】:

我实际上正在修改相同的想法,它非常简洁。使用 Laravel,你确实可以发出内部请求(有些人可能将其称为 HMVC,但我不会)。这是内部请求的基础知识。

$request = Request::create('/api/users/1', 'GET');

$response = Route::dispatch($request);

$response 现在将包含 API 返回的响应。通常这将返回一个 JSON 编码的字符串,这对客户端来说非常有用,但对于内部 API 请求来说不是那么好。您必须在这里扩展一些东西,但基本上想法是通过内部调用返回实际对象,而外部请求返回格式化的 JSON 响应。您可以在这里使用$response->getOriginalContent() 之类的东西来处理这种事情。

您应该考虑构建某种内部Dispatcher,它允许您分派API 请求并返回原始对象。调度程序还应处理格式错误的请求或错误响应并抛出异常以匹配。

这个想法本身是可靠的。但是规划 API 是一项艰巨的工作。我建议您编写一份所有预期端点的好列表,并起草几个 API 版本,然后选择最好的一个。

【讨论】:

有趣的是,我一直在寻找这方面的文档,但最初找不到。意识到这实际上是从 Symfony 继承的 是的,创建初始请求会通过 Symfony HttpFoundation 组件,但请求的调度是由路由器完成的。 你提到“原始对象”,你到底指的是什么? 比如说你的 API 返回一个用户信息。在 Web 上,您希望将其视为 JSON 响应,并且很可能希望隐藏一些列,例如密码。在内部,从长远来看,如果它返回原始对象(例如 Eloquent 模型)而不是返回 JSON 格式,对您来说会更好。这样,您仍然可以与对象本身进行交互,并且您仍然拥有所有列。 如果您需要更多想法和头脑风暴,请在 Freenode 上的#laravel 上进行讨论,通常会有人准备好聊天,我会稍作停留。干杯!

以上是关于如何在Laravel Web程序里面调用自己的API的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Laravel 中实现自己的 Faker 提供程序

laravel 自己的 api 使用来自具有承载令牌的控制器

Laravel5.2默认会给路由增加Web中间件,怎么禁用掉

如何在自己的 laravel 包中添加助手? (调用未定义的函数)

sh 该程序自动为基于Laravel框架的应用程序的公开发布创建一个干净的存档。为了安全起见,您需要ap

如何在 laravel 中进行会话?