Laravel 5.5 - CORS GET 请求更改为 OPTIONS
Posted
技术标签:
【中文标题】Laravel 5.5 - CORS GET 请求更改为 OPTIONS【英文标题】:Laravel 5.5 - CORS GET request changed into OPTIONS 【发布时间】:2018-06-23 22:42:13 【问题描述】:我正在尝试在客户的网站上显示我的小部件。但我无法在 Laravel 5.5 中使用 CORS。这是我的代码:
public/js/cb.js 在客户网站上加载的 javascript 文件。
window.onload = do_request();
function do_request()
var url = "http://cb.dev.server-website.com/api/books/";
var book_id = 0;
var elementExists = document.getElementById("cb_script");
if (typeof elementExists != "undefined" && elementExists)
var book_id = elementExists.getAttribute('data-id');
if (typeof book_id != "undefined" && book_id)
var parts = book_id.split('_');
var loc = parts.pop();
url += loc;
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", url);
xmlhttp.setRequestHeader("Content-Type", "application/json; charset=UTF-8");
xmlhttp.setRequestHeader("Access-Control-Allow-Origin", "*");
xmlhttp.setRequestHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
xmlhttp.setRequestHeader("Access-Control-Allow-Headers", "Content-Type");
xmlhttp.setRequestHeader("Access-Control-Request-Headers", "X-Requested-With, accept, content-type");
xmlhttp.onreadystatechange = function()
if (xmlhttp.readyState == 4 && xmlhttp.status == 200)
var jsondata = JSON.parse(xmlhttp.responseText);
if (
typeof(jsondata) != "undefined" && jsondata != ""
&& typeof(jsondata['data']) != "undefined" && jsondata['data']
)
document.getElementById("stirbook_live").innerhtml = jsondata['data'].html;
do_modal('myModal');
;
xmlhttp.send();
routes/api.php Laravel API 路由文件
Route::resource('books', 'Api\BooksapiController')
->middleware('preflight');
app/Http/Middleware/PreflightResponse.php Laravel 中间件文件
namespace App\Http\Middleware;
use Closure;
class PreflightResponse
public function handle($request, Closure $next)
if ($request->getMethod() === "OPTIONS")
return response('');
return $next($request);
app/Http/Controllers/ApiBooksapiController.php Laravel 控制器文件
public function show($id)
$data = $book_array = array();
$output = '';
$book = DB::table('books')
->join('questions', 'books.id', '=', 'questions.book_id')
->select('books.user_id', 'books.website', 'questions.id AS question_id', 'questions.question')
->get()->toArray();
if (is_array($book) && count($book))
$questions_html = '';
for ($i = 0; $i < count($book); $i++)
$questions_html .= '<h5>Q: ' . $book[$i]->question . '</h5>';
$answers = DB::table('answers')
->where([
['question_id', $book[$i]->question_id],
['status', 1]
])
->select('answers.id', 'answers.answer', 'answers.o_quantity', 'answers.o_percentage', 'answers.o_schedule', 'answers.o_overunder', 'answers.o_overunder')
->get()->toArray();
if (is_array($answers) && count($answers))
$questions_html .= '<ul style="list-style-type: disc;">';
for ($j = 0; $j < count($answers); $j++)
$questions_html .= '<ol>
<input type="radio" name="question_' . $book[$i]->question_id . '" value="1" id="answer_' . $j . '_' . $book[$i]->question_id . '" class="radio-class" onclick="do_survey(' . $book[$i]->question_id . ', ' . $answers[$j]->id . ', ' . $answers[$j]->o_quantity . ')" />
<label for="answer_' . $j . '_' . $book[$i]->question_id . '">' . $answers[$j]->answer . '</label>
<input type="hidden" name="offer_' . $j . '_' . $book[$i]->question_id . '" value="' . $answers[$j]->o_quantity . '" />
</ol>';
$questions_html .= '</ul>';
$output .= '
<!-- Trigger/Open The Modal -->
<button id="myBtn" class="btn btn-primary">Opt-out</button>
<!-- The Modal -->
<div id="myModal" class="modal" style="display: none; position: fixed; z-index: 1; padding-top: 100px; left: 0; top: 0; width: 100%; height: 100%; overflow: auto; background-color: rgb(0,0,0); background-color: rgba(0,0,0,0.4);">
<!-- Modal content -->
<div class="modal-content" style="background-color: #fefefe; margin: auto; padding: 20px; border: 1px solid #888; width: 80%;">
<span class="close" style="color: #aaaaaa; float: right; font-size: 28px; font-weight: bold;">×</span>
<div id="book_form">
<h3>book</h3>
<form name="fbook" action="#" method="post">
' . $questions_html . '
</form>
</div>
<div id="offer_resp" style="display: none;">
<h3>Wait!!!</h3>
<div id="rm_body">
<p>Please don\'t go! How\'s this, we\'ll give you <span class="number-of-months"><numberofmonths></span> free month(s) for trying us out a little longer.</p>
</div>
<button id="yes_button" class="btn btn-primary" onclick="yes_response()" value="">Yes, give me <span class="number-of-months"><numberofmonths></span> month(s) free!</button>
<button id="no_button" class="btn btn-default" onclick="no_response()" value="">No thank you, I wish to cancel now!</button>
</div>
</div>
</div>
';
if (isset($output) && $output)
$data['html'] = $output;
return response()->json(['data' => $data], 200);
但它不起作用。当我在 Postman 中尝试它时,它工作正常。但是当我在任何其他网站上尝试它时,它会将请求从 GET 更改为 OPTIONS 并且什么也没提供。这可能是因为我的服务网站位于子子域中吗?我花了一整天的时间找出解决方案,并且我已经应用了互联网上几乎所有可用的解决方案。
【问题讨论】:
@nazim ,我得到了 OPTIONS 请求背后的逻辑,我尝试在中间件中处理它,但问题仍然存在。 将评论更改为答案。你需要参考 Laravel 文档来处理传入的 OPTIONS 请求。OPTIONS
请求是飞行前请求。客户端询问服务器是否允许 CORS。 服务器发送的特定响应在响应中没有allow-origin
标头,因此基本上不允许使用CORS。您似乎试图在客户端上设置标题,但它不是这样工作的。
@apokryfos ,我已经设法在响应头中添加了 Access-Control-Allow-Origin: * 但它仍然无法正常工作。
不工作太模糊,无法继续。是否有浏览器 CORS 错误?
【参考方案1】:
OPTIONS
调用由某些浏览器自己作为飞行前请求发出,以检查所请求的 URL 上可接受的请求类型(GET、POST、PUT...)。
Chrome 在尝试 CORS 请求时首先发送 OPTIONS 请求。
【讨论】:
【参考方案2】:好的,所以我找到了问题的解决方案。真正的问题在于我使用 GET 请求发送的标头。事实证明,在发送 GET 请求时,public/js/cb.js 中提到的任何标头都不是必需的。只需发送一个简单的 GET 请求。
这里是修改后的public/js/cb.js文件代码:
window.onload = do_request();
function do_request()
var url = "http://cb.dev.server-website.com/api/books/";
var book_id = 0;
var elementExists = document.getElementById("cb_script");
if (typeof elementExists != "undefined" && elementExists)
var book_id = elementExists.getAttribute('data-id');
if (typeof book_id != "undefined" && book_id)
var parts = book_id.split('_');
var loc = parts.pop();
url += loc;
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", url);
xmlhttp.onreadystatechange = function()
if (xmlhttp.readyState == 4 && xmlhttp.status == 200)
var jsondata = JSON.parse(xmlhttp.responseText);
if (
typeof(jsondata) != "undefined" && jsondata != ""
&& typeof(jsondata['data']) != "undefined" && jsondata['data']
)
document.getElementById("stirbook_live").innerHTML = jsondata['data'].html;
do_modal('myModal');
;
xmlhttp.send();
routes/api.php 文件不需要更改,但 app/Http/Middleware/PreflightResponse.php 文件需要稍作更改。
app/Http/Middleware/PreflightResponse.php文件的修改代码:
namespace App\Http\Middleware;
use Closure;
class PreflightResponse
public function handle($request, Closure $next)
if ($request->getMethod() === "OPTIONS")
return response('')
->header('Access-Control-Allow-Origin', '*')
->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
return $next($request)
->header('Access-Control-Allow-Origin', '*')
->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
现在一切就绪。 PreflightResponse 中间件会发送一个响应头...
Access-Control-Allow-Origin: *
到客户的网站。告诉它服务器接受对 API 的每个请求的 CORS 请求。
【讨论】:
以上是关于Laravel 5.5 - CORS GET 请求更改为 OPTIONS的主要内容,如果未能解决你的问题,请参考以下文章
来自 Vue.js 的 Laravel API 调用导致 GET 路由的 CORS
Axios CORS/Preflight 因 Laravel 5.4 API 调用而失败