如何在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\Router
和Illuminate\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 继承的 是的,创建初始请求会通过 SymfonyHttpFoundation
组件,但请求的调度是由路由器完成的。
你提到“原始对象”,你到底指的是什么?
比如说你的 API 返回一个用户信息。在 Web 上,您希望将其视为 JSON 响应,并且很可能希望隐藏一些列,例如密码。在内部,从长远来看,如果它返回原始对象(例如 Eloquent 模型)而不是返回 JSON 格式,对您来说会更好。这样,您仍然可以与对象本身进行交互,并且您仍然拥有所有列。
如果您需要更多想法和头脑风暴,请在 Freenode 上的#laravel 上进行讨论,通常会有人准备好聊天,我会稍作停留。干杯!以上是关于如何在Laravel Web程序里面调用自己的API的主要内容,如果未能解决你的问题,请参考以下文章
laravel 自己的 api 使用来自具有承载令牌的控制器
Laravel5.2默认会给路由增加Web中间件,怎么禁用掉
如何在自己的 laravel 包中添加助手? (调用未定义的函数)