发生了什么事?
{
"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->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)
我不知道这个问题是否仍然有效,但这是解决方案
您需要为每组路线添加带有选项路线的路线
示例(此示例来自文档):
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 () {});
});
我希望这有帮助:)