角度选项飞行前请求被 codeigniter 4 解释为路线

问题描述 投票:0回答:2

发生了什么事?

  • 当我以角度提交表单时,会调用 codeigniter 4 后端。出现以下错误:
{
    "title": "CodeIgniter\\Exceptions\\PageNotFoundException",
    "type": "CodeIgniter\\Exceptions\\PageNotFoundException",
    "code": 404,
    "message": "Can't find a route for 'options: codeSnippets'.",
    "file": "/app/myapp/system/CodeIgniter.php",
    "line": 957,
    "trace": [
        {
            "file": "/app/myapp/system/CodeIgniter.php",
            "line": 957,
            "function": "forPageNotFound",
            "class": "CodeIgniter\\Exceptions\\PageNotFoundException",
            "type": "::"
        },
        {
            "file": "/app/myapp/system/CodeIgniter.php",
            "line": 354,
            "function": "display404errors",
            "class": "CodeIgniter\\CodeIgniter",
            "type": "->"
        },
        {
            "file": "/app/myapp/public/index.php",
            "line": 67,
            "function": "run",
            "class": "CodeIgniter\\CodeIgniter",
            "type": "->"
        }
    ]
}

这发生在请求的预检阶段。我通过在邮递员中创建选项请求发现了这一点。

我想要什么:我希望表单将其值提交给资源控制器并将它们存储在数据库中。 这是相关的角度代码:

import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Component, OnInit } from '@angular/core';
import { FormControl } from '@angular/forms';


@Component({
  selector: 'app-create-code-snippet',
  templateUrl: './create-code-snippet.component.html',
  styleUrls: ['./create-code-snippet.component.scss']
})
export class CreateCodeSnippetComponent implements OnInit {
  
  title = new FormControl('');
  content = new FormControl('')
  
  constructor(private http: HttpClient) { }
  
  public  httpOptions = {
    headers: new HttpHeaders({
      'Content-Type':  'application/json',
      'X-Requested-With': 'XMLHttpRequest',
      //Authorization: 'my-auth-token'
    })
  };
  ngOnInit(): void {
  }

  create() {
    return this.http.post<any>('http://localhost:8000/codeSnippets',JSON.stringify({ title: this.title, content: this.content}),this.httpOptions)
  }

  send() {
    console.log('test')
    this.create().subscribe((data)=> console.log(data));
  }

}

还有 codeigniter 控制器:

<?php

namespace App\Controllers;

use CodeIgniter\RESTful\ResourceController;
use App\Models\CodeSnippet as CodeSnippetModel;
use CodeIgniter\API\ResponseTrait;

class CodeSnippets extends ResourceController
{
    use ResponseTrait;

    protected $modelName = 'App\Models\CodeSnippet';
    protected $format    = 'json';

    public function index()
    {
        return $this->respond($this->model->findAll());
    }

    public function create()
    {
       
        $CodeSnippetModel = new CodeSnippetModel();
        $data = [
            'title' => $this->request->getVar('title'),
            'content'  => $this->request->getVar('content'),
        ];
        $CodeSnippetModel->insert($data);
        //return $this->response->setStatusCode(200);
        return $this->response->setStatusCode(200)->setJSON( ['message' => 'testing'] );
        //return $this->respondCreated();
    }
}

我尝试在过滤器中拦截选项请求,但不知何故它没有到达那里。我可以在路由配置文件中拦截它:

$request = \Config\Services::request();
if ($request->getMethod('options')) {
    var_dump('test');
}

我知道我必须以某种方式返回 200 OK 响应并设置这些标头,我认为:

 header("Access-Control-Allow-Origin: *");
 header("Access-Control-Allow-Methods: GET,HEAD,OPTIONS,POST,PUT");
 header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization");

一些相关信息是我正在运行一个 Angular 13 开发服务器,并将其连接到一个暴露端口为 8000 的 docker Codeigniter 容器。正如所说,我可以使用邮递员毫无问题地访问它,并且数据存储在数据库中,问题发生在以下情况:从 Angular 提交表单以及从邮递员提交选项请求时。

更新:

设置后:

$routes->setAutoRoute(true);

在config/routes.php中

并将这段代码放入我制作的corsfilter中:

<?php

namespace App\Filters;

use CodeIgniter\Filters\FilterInterface;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;

class CorsFilter implements FilterInterface
{
    /**
     * Do whatever processing this filter needs to do.
     * By default it should not return anything during
     * normal execution. However, when an abnormal state
     * is found, it should return an instance of
     * CodeIgniter\HTTP\Response. If it does, script
     * execution will end and that Response will be
     * sent back to the client, allowing for error pages,
     * redirects, etc.
     *
     * @param RequestInterface $request
     * @param array|null       $arguments
     *
     * @return mixed
     */
    public function before(RequestInterface $request, $arguments = null)
    {
        if (array_key_exists('HTTP_ORIGIN', $_SERVER)) {
            $origin = $_SERVER['HTTP_ORIGIN'];
            } else if (array_key_exists('HTTP_REFERER', $_SERVER)) {
            $origin = $_SERVER['HTTP_REFERER'];
            } else {
            $origin = $_SERVER['REMOTE_ADDR'];
            }
            $allowed_domains = array(
                'http://localhost:4200'            
            );
            
            
            if (in_array($origin, $allowed_domains)) {
                header('Access-Control-Allow-Origin: ' . $origin);
            }
            
            header("Access-Control-Allow-Headers: Origin, X-API-KEY, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method, Access-Control-Allow-Headers, Authorization, observe, enctype, Content-Length, X-Csrf-Token");
            header("Access-Control-Allow-Methods: GET, PUT, POST, DELETE, PATCH, OPTIONS");
            header("Access-Control-Allow-Credentials: true");
            header("Access-Control-Max-Age: 3600");
            header('content-type: application/json; charset=utf-8');
            
        if ($request->getMethod('options') === "OPTIONS") {
            header("Access-Control-Allow-Origin: {$origin}");
            header("Access-Control-Allow-Methods: OPTIONS");
            header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization");
            header("HTTP/1.1 200 OK CORS");
            die();
        }
    }    

    /**
     * Allows After filters to inspect and modify the response
     * object as needed. This method does not allow any way
     * to stop execution of other after filters, short of
     * throwing an Exception or Error.
     *
     * @param RequestInterface  $request
     * @param ResponseInterface $response
     * @param array|null        $arguments
     *
     * @return mixed
     */
    public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
    {
        //
    }
}

我在预检检查中不再出现错误。

routes codeigniter-4 angular13 preflight
2个回答
0
投票

解决方案是设置:

$routes->setAutoRoute(true);

在 Config/Routes.php 中

结合提供正确的标头和“200 Cors OK”响应,如下所示:

if ($request->getMethod('options') === "OPTIONS") {
            header("Access-Control-Allow-Origin: {$origin}");
            header("Access-Control-Allow-Methods: OPTIONS");
            header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization");
            header("HTTP/1.1 200 OK CORS");
            die();
        }

在 CorsFilter 中实现,如原始帖子所示。(OP)


0
投票

我不知道这个问题是否仍然有效,但这是解决方案

使用 codeigniter 4 的实际文档

您需要为每组路线添加带有选项路线的路线

示例(此示例来自文档):


use CodeIgniter\Router\RouteCollection;

$routes->group('', ['filter' => 'cors'], static function (RouteCollection $routes): void {
    $routes->resource('product');

    $routes->options('product', static function () {
        // Implement processing for normal non-preflight OPTIONS requests,
        // if necessary.
        $response = response();
        $response->setStatusCode(204);
        $response->setHeader('Allow:', 'OPTIONS, GET, POST, PUT, PATCH, DELETE');

        return $response;
    });
    $routes->options('product/(:any)', static function () {});
});

我希望这有帮助:)

© www.soinside.com 2019 - 2024. All rights reserved.