有没有办法从 PHP 脚本中达到 API 端点但保留原始请求方法?

Posted

技术标签:

【中文标题】有没有办法从 PHP 脚本中达到 API 端点但保留原始请求方法?【英文标题】:is there a way to hit an API end point from a PHP script but retain the original request method? 【发布时间】:2020-01-12 19:44:12 【问题描述】:

根据这个answer,

...header("Location: ...") 设置一个状态码,显式导致浏览器使用 GET 请求,而不是它使用的任何方法。

这正是我正在编写的应用程序所看到的行为,该应用程序试图通过 API 将数据添加到数据库中。

我希望旁边有红线的那一行也说 POST。

这是调用 makeAPIcalls.php 文件中 API 端点的逻辑:

# read raw data from request body and stuff it into $_POST
$_POST = json_decode(file_get_contents('php://input'), true);

# set variables using data that was passed in
$id = getParameterValue('id');
// there are others that aren't shown here

# make API call depending on request method
$method = $_SERVER['REQUEST_METHOD'];
$url = 'http://localhost:8080/miscellaneous/APIexamples/CRUD/';
if ($method == 'GET')    $url .= 'mobile/list';
if ($method == 'POST')   $url .= 'mobile/add';
if ($method == 'PUT')    $url .= 'mobile/edit/' . $id;
if ($method == 'DELETE') $url .= 'mobile/remove/' . $id;
header('Location: ' . $url);

是否有替代 header('Location: '... 的方法来访问保留原始请求方法的 API 端点?

编辑: 这是表格和JS:

                    <form action="" method="post" id="add">
                        <legend>Add Mobile</legend>
                        <ol>
                            <li>
                            <label for="add_name">name</label>
                                <input type="text" name="name" id="add_name"></input>
                            </li>
                            <li>
                                <label for="add_model">model</label>
                                <input type="text" name="model" id="add_model"></input>
                            </li>
                            <li>
                                <label for="add_color">color</label>
                                <input type="text" name="color" id="add_color"></input>
                            </li>                               
                        </ol>
                        <button type="button" onclick="addMobile()">Submit</button>
                        <button type="reset">Cancel</button>
                    </form>
function addMobile() 
    // get the form data
    var formData = 
        name: $('#add input[name="name"]').val(),
        model: $('#add input[name="model"]').val(),
        color: $('#add input[name="color"]').val()
    

    // process form
    $.ajax(
        method:"POST",
        url:"js/makeAPIcalls.php",
        contentType: 'application/json',
        data: JSON.stringify(formData),
        async: true,
        cache: false
    )
    .done(function(data)
        // log data to console for visibility
        // console.log(data);

        // clear out form fields
        $('#add input[name="name"]').val('');
        $('#add input[name="model"]').val('');
        $('#add input[name="color"]').val('');

    )
    .fail(function(data)
        console.log(data);
        console.log('AJAX call failed');
    )  

【问题讨论】:

如果您需要 client(浏览器)来发起 POST 请求,那么您不能为此使用重定向。页面上带有method="POST" 的表单可以解决问题,如果需要,您可以通过 javascript 自动提交。 我正在使用 AJAX 添加数据以避免在用户单击提交时重新加载页面。 客户端 AJAX 跟随重定向,仍然作为另一个 AJAX 请求?在这种情况下,不用重定向响应,而是用数据响应,并让 AJAX 响应处理程序向 API 提交 AJAX POST。 @David - 太棒了!我将删除 makeAPIcalls.php 脚本并将所有 URL 直接放在 AJAX 中。 【参考方案1】:

如果这不是为了简洁起见而简化的示例,并且这确实是makeAPIcalls.php 中的所有服务器端代码,那么首先甚至不需要这种交互。客户端已经知道进行 API 调用所需的一切:

$.ajax(
    method:"POST",
    url:"http://localhost:8080/miscellaneous/APIexamples/CRUD",
    /.../
)
.done(function(data)
    $('#add input[name="name"]').val('');
    $('#add input[name="model"]').val('');
    $('#add input[name="color"]').val('');
)

不需要与服务器的来回、重定向等。

【讨论】:

它可以完全删除makeAPIcalls.php 脚本并替换.ajax 中对它的引用,如下所示:url: 'http://localhost:8080/miscellaneous/APIexamples/CRUD/mobile/add' @knot22: 哦,如果整个事件序列根本不需要任何服务器端交互(在调用makeAPIcalls.php 之前,客户端已经知道一切)那肯定会更好.我会更新答案。 @David 重定向并不总是 GET 请求。另见:***.com/a/42138726/362536【参考方案2】:

返回307308 状态码是告诉客户他们应该在新位置重复整个请求的正确方法。

307 用于临时重定向,308 用于永久重定向。

【讨论】:

所有主流浏览器都支持,很开心。 caniuse.com/#search=307caniuse.com/#search=308

以上是关于有没有办法从 PHP 脚本中达到 API 端点但保留原始请求方法?的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法让 Swashbuckle 将 OData 参数添加到 Web API 2 IQueryable<T> 端点?

有没有办法缩短 API 端点 URL,然后针对它发出请求?

如何在不使用 ImageView 的情况下从 API 端点下载图像或位图?

Auth0 端点 API 的自定义实现?

查询阻止 CORS 的 API

如何修复 PHP MySQL 中达到 508 资源限制