0

I am trying to make a POST request to the users/USER_NAME endpoint of my Chef Server and continue to receive an error response message of 405 - Method Not Allowed.

Fatal error: Uncaught exception 'Exception' with message '<html><head><title>405 Method Not Allowed</title></head><body><h1>Method Not Allowed</h1>Method Not Allowed<p><hr><address>mochiweb+webmachine web server</address></body></html>' in ..\..\..\Chef.php:191

However, when I try to make the same request using the GET method, everything works out fine.

{username: "jsmith", email: "", display_name: "unknown", first_name: "John", last_name: "Smith",…}
city:"unknown"
country:"unknown"
display_name:"unknown"
email:""
first_name:"John"
last_name:"Smith"
middle_name:""
public_key:"-----BEGIN PUBLIC KEY----- -----END PUBLIC KEY-----"
username:"jsmith"

Mind you, as per the documentation (Query For Users and Orgs), I am using the pivotal username along with the pivotal.pem file.

Here is an example of the information I am sending:

Example Chef Server User Request

As I mentioned above, the only thing I change is the method used (GET/POST).

Here is my extJS code for the form I am using:

var enrollUserForm = Ext.create('Ext.form.Panel', {
    title: 'Enroll User',
    height: 200,
    width: 300,
    bodyPadding: 10,
    url: '../../../../chefEnrollUser.php',
    defaultType: 'textfield',
    items: [{
        fieldLabel: 'First Name',
        name: 'firstName'
    }, {
        fieldLabel: 'Last Name',
        name: 'lastName'
    }, {
        fieldLabel: 'Email Address',
        name: 'emailAddress'
    }, {
        fieldLabel: 'Username',
        name: 'username'
    }, {
        xtype: 'textfield',
        inputType: 'password',
        fieldLabel: 'Password',
        name: 'password'
    }],
    buttons: [{
        text: 'Enroll',
        formBind: true,
        handler: function() {
            var enrollUserInformation = enrollUserForm.getForm();
            var firstName = enrollUserInformation.findField('firstName')['value'];
            var lastName = enrollUserInformation.findField('lastName')['value'];
            var emailAddress = enrollUserInformation.findField('emailAddress')['value'];
            var username = enrollUserInformation.findField('username')['value'];
            var password = enrollUserInformation.findField('password')['value'];

            if (firstName != null && lastName != null && emailAddress != null && password != null) {
                if (firstName.length == 0 || lastName.length == 0 || emailAddress.length == 0 ||
                    username.length == 0 || password.length == 0) {
                    alert("Please fill in all fields");
                } else {
                    if (validateEmail(emailAddress)) {
                        // proceed to enrolling
                          enrollUserForm.getForm().submit({
                            params: {
                                firstName: firstName,
                                lastName: lastName,
                                emailAddress: emailAddress,
                                username: username,
                                password: password
                            }
                          })
                    } else {
                        alert("Please enter a valid email address.");
                    }
                }
            } else {
                alert("Please fill in all fields.");
            }
        }
    }]
});

Here is my chefEnrollUser.php file:

<?php

namespace Jenssegers\Chef;

session_start();

header('Accept: application/json');
header('Content-type: application/json');

ini_set('display_errors', 'On');
error_reporting(E_ALL | E_STRICT);

// Retrieve parameters from Enroll User Form
$firstName    = $_REQUEST['firstName'];
$lastName     = $_REQUEST['lastName'];
$emailAddress = $_REQUEST['emailAddress'];
$username     = $_REQUEST['username'];
$password     = $_REQUEST['password'];

if (!isset($_REQUEST['firstName']) || !isset($_REQUEST['lastName']) || !isset($_REQUEST['emailAddress']) || !isset($_REQUEST['username']) ||
        !isset($_REQUEST['password'])) {
    echo "One or more parameters were not passed in correctly.";
}

require_once '../../../Chef.php';

// ENVIRONMENT VARIABLES
// The URL for the Chef Server
$server  = "mychefserver.com";
// The name used when authenticating
$client  = "pivotal";
// The location of the file which contains the client key
$key     = "../../../pivotal.pem";
// The version of the Chef Server API that is being used
$version = "12.0.2";

// Create a Chef object
$chef = new Chef($server, $client, $key, $version);

// API Request
$createUserRequest = $chef->get('/users/' . $username);

// Return JSON representation of value
// $encoded_role = json_encode($role_information);

// Decode a JSON string
// $decoded_role = json_decode($encoded_role, true);

echo json_encode($createUserRequest);

//echo json_encode($run_list_array);
?>
User 5842
  • 2,849
  • 7
  • 33
  • 51

1 Answers1

0

That's more or less normal as per REST standards (See this question).

A POST request should be used to create an user, not to update it. So if you POST on an already existing user, the server disallow it (the meaning of the 405 code).

Quoting the documentation here:

The POST method is used to create a new user. If a public key is not specified, both public and private keys will be generated and returned. If a public key is specified, only the public key will be returned.

The PUT method is used to update a specific user. If values are not specified for the PUT method, the Chef server will use the existing values rather than assign default values.

So your code should test (with a GET) the existence of user to choose to POST or PUT according to what you wish to do.

After your edit I would write this code instead of your $chef->get (untested):

$createUserRequest = array("name"=>"$firtname $lastname")
$chef->post("/users/$username", json_encode($createUserRequest) )

I let you extend the arry to include other informations, the json_encode should do on associative arrays, so you just have to send a correct json to the chef server.

Community
  • 1
  • 1
Tensibai
  • 15,557
  • 1
  • 37
  • 57
  • Thank you for the information, however, I tried making a POST request using a different user and unfortunately received the same error. Any ideas as to why? – User 5842 Oct 20 '16 at 11:59
  • I've no idea on what you're sending exactly at end, nor which version your chef-server is running, and I can't read your server log. So no, I've no idea on what's going wrong if you post to a non-existing user name actually. Shwoing your `chefEnrollUser.php` may help – Tensibai Oct 20 '16 at 12:13
  • Okay, I've added the chefEnrollUser.php file for some more clarification. – User 5842 Oct 20 '16 at 12:29
  • @User5842 Extended the answer – Tensibai Oct 20 '16 at 12:37
  • Doing some more research into the 405 Error, I found that the reason for this is: – User 5842 Oct 20 '16 at 12:45
  • 405 Method Not Allowed: A request was made of a resource using a request method not supported by that resource; for example, using GET on a form which requires data to be presented via POST, or using PUT on a read-only resource. – User 5842 Oct 20 '16 at 12:46
  • @User5842 Yes, that's what happen when you post to an existing user.... – Tensibai Oct 20 '16 at 12:49
  • Seems like this question can be of use: http://stackoverflow.com/questions/17333013/jquery-ajax-post-request-throws-405-method-not-allowed-on-restful-wcf – User 5842 Oct 20 '16 at 12:50