0

Per this answer,

...header("Location: ...") sets a status code that explicitly causes the browser to use a GET request instead of whatever method it was using.

This is exactly the behavior I'm seeing for the app I'm writing that tries to add data to the database via the API.

I want the row with the red line next to it to also say POST.

enter image description here

Here is the logic that calls the API end points that's in a file called makeAPIcalls.php:

# 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);

Is there an alternative approach to header('Location: '... for hitting an API end point which keeps the original request method?

Edit: Here is the form and the 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');
    })  
}
knot22
  • 2,648
  • 5
  • 31
  • 51
  • 1
    If you need the *client* (browser) to initiate a POST request then you can't use a redirect for that. A form on the page with `method="POST"` would do the trick, which you can submit automatically via JavaScript if you need to. – David Sep 11 '19 at 02:19
  • I'm using AJAX to add data to avoid a page reload when the user clicks submit. – knot22 Sep 11 '19 at 02:21
  • 2
    And the client-side AJAX is following the redirect, still as another AJAX request? In that case instead of responding with a redirect just respond with data and have the AJAX response handler submit an AJAX POST to the API. – David Sep 11 '19 at 02:22
  • @David - Brilliant! I will remove the makeAPIcalls.php script and put all the URLs directly in the AJAX. – knot22 Sep 11 '19 at 02:27

2 Answers2

2

Returning a 307 or 308 status code is the correct way to tell a client they should repeat the entire request at the new location.

307 is for temporary redirects, and 308 is for permanent redirects.

Evert
  • 93,428
  • 18
  • 118
  • 189
  • 1
    Supported in all major browsers, happily enough. https://caniuse.com/#search=307 https://caniuse.com/#search=308 – ceejayoz Sep 11 '19 at 03:06
1

If this isn't a reduced example for brevity and this is indeed all of the server-side code in makeAPIcalls.php, then that interaction isn't even needed in the first place. The client already knows everything it needs to know to make the API call:

$.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('');
})

No need for the back-and-forth with the server, redirects, etc.

David
  • 208,112
  • 36
  • 198
  • 279
  • It worked to remove the `makeAPIcalls.php` script completely and replace the reference to it in the `.ajax` like so: `url: 'http://localhost:8080/miscellaneous/APIexamples/CRUD/mobile/add'`. – knot22 Sep 11 '19 at 02:46
  • 1
    @knot22: Oh, if the overall sequence of events doesn't need any server-side interaction at all (everything is already known client-side before calling `makeAPIcalls.php`) then that would definitely be better. I'll update the answer. – David Sep 11 '19 at 02:47
  • 1
    @David A redirect is not always a GET request. See also: https://stackoverflow.com/a/42138726/362536 – Brad Sep 11 '19 at 02:51