0

I can see that postman is being redirected for some reason. I have just started using postman so not sure what a normal request would look like. When I make the following request;

POST https://development.example.com/Api/Register
form-data
KEY name
VALUE Thomas
KEY _method
VALUE PUT

For some reason it returns my top page of my website. When I look at the apache2 log file, I can see:

124.xxx.xxx.xxx - - [27/Feb/2022:09:08:36 +0000] "POST /Api/Register HTTP/1.1" 303 5724 "-" "PostmanRuntime/7.28.4"

124.xxx.xxx.xxx - - [27/Feb/2022:09:08:36 +0000] "GET / HTTP/1.1" 200 8185 "https://development.example.com/Api/Register" "PostmanRuntime/7.28.4"

When I access it through a web browser like chrome (and I cannot submit any values of course), I get below which is expected;

 {
   "status": 500,
   "message": {
       "name": "The name field is required",
       "email": "The email field is required",
       "password": "The password field is required.",
       "password_confirmation": "The password_confirmation field is required."
   },
   "error": true,
   "data": []
}

What am I doing wrong with POSTMAN please?

My Users controller is;

public function userRegister(){
    $user = new UserEntity($this->request->getPost());
    $user->startActivation();
    if ($this->UserModel->insert($user)){
        $this->sendActivationEmail($user);
        $response =[
            'status'    => 200,
            'message'   => 'User registed.  Check email to activate account.',
            'error'     => false,
            'data'      => []
        ];
    } else {
        $response =[
            'status'    => 500,
            'message'   => $this->UserModel->errors(),
            'error'     => true,
            'data'      => []
        ];
    }
    return $this->respondCreated($response);
}

What is also puzzling is that the route is NOT accessible via;

My routes file is;

$routes->group('Api', ["namespace" => 'App\Controllers\Api\v1'] , function($routes){
    $routes->post('Register', 'Users::userRegister');
});

https://development.example.com/Api/Register
Error;  Controller or its method is not found: \App\Controllers\Api\Register::index

https://development.example.com/Api/v1/Users/userRegister 
This will work and give correct error like way above.
spreaderman
  • 918
  • 2
  • 10
  • 39
  • I have removed all routes except the $routes->group('Api',... The error I get back in postman is "title": "CodeIgniter\\Exceptions\\PageNotFoundException", "type": "CodeIgniter\\Exceptions\\PageNotFoundException", "code": 404, "message": "Controller or its method is not found: \\App\\Controllers\\Home::index", "file": – spreaderman Feb 27 '22 at 09:49
  • `https://development.example.com/Api/v1/Users/userRegister` How come this route has `v1` the API version number? – steven7mwesigwa Feb 27 '22 at 10:08
  • the actual namespace is development.example.com/Api/v1/Users/userRegister but the route is Api/Register. Yes, v1 is the version number – spreaderman Feb 27 '22 at 10:10
  • Yet `https://development.example.com/Api/Register` has no API version number? – steven7mwesigwa Feb 27 '22 at 10:10
  • Oh? Am I doing the routes incorrectly? – spreaderman Feb 27 '22 at 10:11
  • I think you're confusing [PHP Namespaces](https://www.php.net/manual/en/language.namespaces.php) with URL paths. These can't be used interchangeably. They are completely different concepts. Please read [Codeigniter 4 Grouping Routes](https://codeigniter4.github.io/userguide/incoming/routing.html#grouping-routes) – steven7mwesigwa Feb 27 '22 at 10:19
  • $routes->group('Api', ["namespace" => 'App\Controllers\Api\V1'] , function($routes){ $routes->post('Register', 'Users::userRegister'); }); I cannot see a problem with this. The documentation is the same as far as I can see. – spreaderman Feb 27 '22 at 10:32
  • `https://development.example.com/Api/v1/Users/userRegister ` Can you share the route definition corresponding to this URL path, please? – steven7mwesigwa Feb 27 '22 at 10:36
  • $routes->group('Api', ["namespace" => 'App\Controllers\Api\V1'] , function($routes){ $routes->post('Register', 'Users::userRegister'); }); I thought this is the route definition. The controller is /App/Controllers/Api/V1/Users and method registerUser(). The URL is then /Api/Register. Is that not what this group route says? Thanks! – spreaderman Feb 27 '22 at 10:39
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/242449/discussion-between-spreaderman-and-steven7mwesigwa). – spreaderman Feb 27 '22 at 10:45

1 Answers1

0

The problem is that you're essentially making a PUT request in Postman (_method PUT), yet your route definition in the file app/Config/Routes.php only responds to POST requests ($routes->post('Register', 'Users::userRegister');).

To fix this, remove the _method POST request parameter from Postman:

POST https://development.example.com/Api/Register
form-data
KEY name
VALUE Thomas

Addendum

The seemingly POST Postman request in your question is being implicitly interpreted as a PUT request by the Codeigniter framework because of HTTP Method Spoofing.

HTTP Method Spoofing

When working with HTML forms you can only use GET or POST HTTP verbs. In most cases, this is just fine. However, to support REST-ful routing you need to support other, more correct, verbs, like DELETE or PUT. Since the browsers don’t support this, CodeIgniter provides you with a way to spoof the method that is being used. This allows you to make a POST request, but tell the application that it should be treated as a different request type.

To spoof the method, a hidden input is added to the form with the name of _method. It’s value is the HTTP verb that you want the request to be:

   <form action="" method="post">
       <input type="hidden" name="_method" value="PUT" />
   </form>

This form is converted into a PUT request and is a true PUT request as far as the routing and the IncomingRequest class are concerned.

The form that you are using must be a POST request. GET requests cannot be spoofed.

steven7mwesigwa
  • 5,701
  • 3
  • 20
  • 34
  • I don't think so. The POST method is usually used for create operations, and the PUT is used for edit/update operations. So post should work. https://stackoverflow.com/questions/19096704/codeigniter-rest-api-difference-between-put-and-post. Anyway, I tried with PUT and same thing. /register should be a POST – spreaderman Feb 27 '22 at 10:58
  • Have also tried this route: $routes->post('register', 'App\Controllers\Api\V1\Users::userRegister'); And it still goes for my Home::index with this error { "title": "CodeIgniter\\Exceptions\\PageNotFoundException", "type": "CodeIgniter\\Exceptions\\PageNotFoundException", "code": 404, "message": "Controller or its method is not found: \\App\\Controllers\\Home::index", "file": – spreaderman Feb 27 '22 at 11:09
  • I think you misunderstood my answer. Please, read it again. I **never** suggested that you change the HTTP verb in Postman. I *only* pointed out that the seemingly `POST` Postman request in your question is being **implicitly interpreted** as a `PUT` request by the Codeigniter framework because of **HTTP Method Spoofing**. – steven7mwesigwa Feb 27 '22 at 11:10
  • Sorry, I don't understand. I have tried POST https://development.motorvessel.com/register KEY name VALUE Thomas and route like this $routes->post('register', 'App\Controllers\Api\V1\Users::userRegister'); but same error. How is CI implicitly interpreting this as PUT? – spreaderman Feb 27 '22 at 11:13
  • @spreaderman The implicit interpretation **only** happens if you have a `_method` request parameter in your `POST` request body. I think this is clear enough. – steven7mwesigwa Feb 27 '22 at 11:22
  • ok, so I am not using _method to spoof. – spreaderman Feb 27 '22 at 11:22