Angular 6 + Laravel 5.6:httpClient.post

时间:2018-10-11 20:31:02

标签: angular post laravel-5 cors httpclient

使用Laravel 5.6创建了一个API,并且所有端点均可与Postman一起使用。当我开始开发Angular 6应用程序时,问题就开始了。由于我在本地工作,因此无论使用哪种http方法(httpClient),我都开始在Chrome中出现CORS错误。因此,我在Laravel中创建了一个中间件来处理CORS请求。一切开始按预期工作,所以我想...现在我面临其他问题。

我正在使用Laravel的默认控制器操作执行CRUD任务,因此我主要使用资源路由(Route :: resource)。对于自定义方法,我使用的是Route :: post()。

现在,奇怪的是我可以发送发布请求用于自定义方法(Route :: post),但不能发送到资源路由。

示例:

//post requests to custom routes work as expected
Route::post('users/block', 'API\UserController@toggleBlock');
Route::post('users/access', 'API\UserController@sendAccess');

//post requests to resource routes nothing happens
Route::resource('settings', 'API\SettingController');
Route::resource('products', 'API\ProductController');

如果我将路线更改为以下内容:

Route::get('settings', 'API\SettingController@index'); //works!
Route::post('settings', 'API\SettingController@store'); //nothing happens!!
Route::post('settings/bazinga', 'API\SettingController@store'); //works!!

因此,据我所知,即使http方法不同,我也无法使用相同的URI。

这是我的CORS中间件:

public function handle($request, Closure $next)
{
    //apply cors only to api routes
    if (Request::segment(1) == 'api') {
        header("Access-Control-Allow-Origin: *");

        // ALLOW OPTIONS METHOD
        $headers = [
            'Access-Control-Allow-Methods' => 'POST, GET, OPTIONS, PUT, DELETE',
            'Access-Control-Allow-Headers' => 'Content-Type, X-Auth-Token, Origin, Authorization, Accept, Cache-Control',
        ];
        if ($request->isMethod("OPTIONS")) {
            // The client-side application can set only headers allowed in Access-Control-Allow-Headers
            return Response::make('OK', 200, $headers);
        }

        $response = $next($request);
        foreach ($headers as $key => $value) {
            $response->header($key, $value);
        }
    } else {

        $response = $next($request);
    }
    return $response;
}

为什么会这样?这和CORS有关吗?既然一切都能按照Postman的要求进行,那么这可能与CORS有关,对吧?

更新:cURL输出

> curl 'https://api.project.localhost:34430/api/settings' -D -X OPTIONS -H 'pragma: no-cache' -H 'access-control-request-headers: authorization,' -H 'access-control-request-method: POST' -H 'origin: <http://localhost:4200>' -o output.txt
  

卷曲:(6)无法解析主机:选项

更新#2:角度代码

保存方法:

save(settings: Setting[]): Observable<any> {
    const path = 'settings';

    const headers = {
      'Cache-Control': 'no-cache'
    };

    const params = { settings: settings };

    return new Observable(observer => {
        this.api.post(path, params, headers).subscribe(
            data => {
              // observable execution
              observer.next('Save Settings');
              observer.complete();
        },
        error => console.log(error) // error path
      );
    });
}

发布方法:

post(path: string, params: Object, headers?: any): Observable<ApiResponse> {
    const request = this.createRequestObject(path, params, headers);

    return this.http.post<ApiResponse>(
        request.endPoint,
        request.params,
        request.httpOptions
    );
}

private createRequestObject(path: string, params?: Object, headers?: any): ApiRequest {
    if (headers) {
      Object.assign(this.headers, headers);
    }

    const request = new ApiRequest();
    request.endPoint = this.endPoint + path;
    request.httpOptions = { headers: this.headers };
    request.params = params;

    return request;
}

更新#3:Chrome开发者工具控制台

获取请求:

Get Request Console Log

Get Request Network Activity 1

Get Request Network Activity 2

发布请求:

Post Request Console Log

注意:当我执行发布请求时,“网络活动”中没有任何反应。

3 个答案:

答案 0 :(得分:0)

您可以通过curl或邮递员检查通过OPTION为此端点获得的输出是什么吗?

curl '<path to endpoint>' -X OPTIONS -H 'pragma: no-cache' -H 'access-control-request-headers: authorization,' -H 'access-control-request-method: POST' -H 'origin: <http://localhost:4200>'

类似上述要求?

答案 1 :(得分:0)

此问题是由于传递了和必需的标头。应该维护并从双方(客户端和服务器)传递。

Laravel:

您可以使用软件包https://github.com/barryvdh/laravel-cors并根据要求修改设置。

角度6:您必须阅读https://angular.io/api/common/http/HttpInterceptor。您可以创建拦截器,该拦截器将在客户端处理标头。我附上了样板,您可以在其中检查和使用拦截器。检查给定链接中的答案。 https://stackoverflow.com/a/53350123/3851720

答案 2 :(得分:0)

在角端,在我添加的服务文件中

const httpOptions = {
  headers: new HttpHeaders({ 
    'Access-Control-Allow-Origin':'*'
	})
};

在装饰之前。

然后在Laravel中以公用文件夹内的index.php结尾, 只需添加下面的标题

header('Access-Control-Allow-Origin: http://localhost:4200');
header('Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization');