33

It should be so simple. I've followed every tutorial and forum I could find, yet I can't get it to work. I simply want to build a RESTful API in PHP on Apache2.

In my VirtualHost directive I say:

<Directory />
    AllowOverride All
    <Limit GET HEAD POST PUT DELETE OPTIONS>
        Order Allow,Deny
        Allow from all
    </Limit>
</Directory>

Yet every PUT request I make to the server, I get 405 method not supported.

Someone advocated using the Script directive, but since I use mod_php, as opposed to CGI, I don't see why that would work.

People mention using WebDAV, but to me that seems like overkill. After all, I don't need DAV locking, a DAV filesystem, etc. All I want to do is pass the request on to a PHP script and handle everything myself. I only want to enable PUT and DELETE for the clean semantics.

j0k
  • 22,600
  • 28
  • 79
  • 90
Andreas Jansson
  • 3,137
  • 2
  • 30
  • 40

5 Answers5

17

You don't need to configure anything. Just make sure that the requests map to your PHP file and use requests with path info. For example, if you have in the root a file named handler.php with this content:

<?php

var_dump($_SERVER['REQUEST_METHOD']);
var_dump($_SERVER['REQUEST_URI']);
var_dump($_SERVER['PATH_INFO']);

if (($stream = fopen('php://input', "r")) !== FALSE)
    var_dump(stream_get_contents($stream));

The following HTTP request would work:

Established connection with 127.0.0.1 on port 81
PUT /handler.php/bla/foo HTTP/1.1
Host: localhost:81
Content-length: 5
 
boo
HTTP/1.1 200 OK
Date: Sat, 29 May 2010 16:00:20 GMT
Server: Apache/2.2.13 (Win32) PHP/5.3.0
X-Powered-By: PHP/5.3.0
Content-Length: 89
Content-Type: text/html
 
string(3) "PUT"
string(20) "/handler.php/bla/foo"
string(8) "/bla/foo"
string(5) "boo
"
Connection closed remotely.

You can hide the "php" extension with MultiViews or you can make URLs completely logical with mod_rewrite.

See also the documentation for the AcceptPathInfo directive and this question on how to make PHP not parse POST data when enctype is multipart/form-data.

Community
  • 1
  • 1
Artefacto
  • 96,375
  • 17
  • 202
  • 225
  • Using cURL command line: "curl -X PUT --header "Content-Type: application/octet-stream" --data-binary "@1.gif" -v /handler.php/bla/foo" and inside PHP file dump contents into file. It works great. However, I need to send some extra information eg. token with the request to upload file. I think I should use POST. – vivek.m Nov 28 '11 at 12:11
  • The token can be in the header too ;) – Tomáš Fejfar Jun 27 '13 at 15:08
  • 20
    This doesn't answer the question. @AndreasJansson, what did you change to get it working? I have the same problem, and saying "you don't need to do anything, it already works" is NOT HELPFUL. – Benubird May 14 '14 at 09:58
  • 3
    I have the same problem. 405 error occur before it reach .php page. So I cannot map anything. – vee Oct 04 '14 at 15:37
  • _"Just make sure that the requests map to your PHP file"_ Right... but **how**? Agreed, not a helpful answer. – Asteroids With Wings Feb 21 '20 at 13:00
-2

AllowOverride AuthConfig

try this. Authentication may be the problem. I was working with a CGI script written in C++, and faced some authentication issues when passed DELETE. The above solution helped me. It may help in your case too.


Also even if you don't get the solution for your problem of PUT and DELETE, do not stop working rather use "CORS". It is a google chrome app, which will help you bypass the problem, but remember it is a temporary solution, so that your work or experiments doesn't remain freeze for long. Obviously, you cannot ask your client to have "CORS" enabled to run your solution, as it may compromise systems security.

MSharq
  • 65
  • 1
  • 3
  • 1
    Why do you think that authentication may be the root cause, despite the fact that the stated problem is a 405, not a 403? What has CORS got to do with either HTTP method acceptability, or authentication? Could you please clarify your answer, to make it clear which of these three concepts you're talking about? – AnotherSmellyGeek Jun 29 '16 at 04:32
-3

On linux, /etc/apache2/mods-enabled/php5.conf dans php5.load exists. If not, enables this modules (may require to sudo apt-get install libapache2-mod-php5).

user207421
  • 305,947
  • 44
  • 307
  • 483
-4

IIRC the purpose of the form method attribute was to define different transport methods. Consequently, HTML 5.2 only defines GET, POST, and DIALOG methods for transport and dialog action, not how the server should process the data.

Ruby-on-rails solves this problem by using POST/GET for everything and adding a hidden form variable that defines the actual ReST method. This approach is more clumsy and error-prone, but does remove the burden from both the HTML standard and browser developers.

The form method was defined before ReST, so you cannot define ReST in HTML, even after enabling Apache and PHP because the browsers conform to HTML and therefore default to GET/POST for all non-HTML defined values. That means, when you send a form to the browser with a PUT method, the browser changes that to GET and uses that instead. The hidden variable, however, passes through everything unchanged, so you can use that to customise your form handling process.

Hope that helps

  • 1
    Are you sure you meant "HTML"? – Asteroids With Wings Feb 21 '20 at 13:00
  • Yes, because the http method name is required in the html form tag. The problem is browser developers never implemented a flexible method, probably because it seemed impossible to know what data structure (transport) should be used for an arbitrary method. This is why ruby on rails uses a hidden variable instead. The answer given is actually ridiculous, because it replaces the browser with php code. Really? – Peter Gostelow Jul 07 '20 at 21:05
  • 1
    Well, [no, it isn't](https://www.w3.org/TR/html52/sec-forms.html#element-attrdef-form-method). – Asteroids With Wings Jul 07 '20 at 21:07
  • Yes, it is. From HTML 5.3: 4.10.1.3. Configuring a form to communicate with a server This section is non-normative. Form submissions are exposed to servers in a variety of ways, most commonly as HTTP GET or POST requests. To specify the exact method used, the method attribute is specified on the form element. This doesn’t specify how the form data is encoded, though; to specify that, you use the enctype attribute. You also have to specify the URL of the service that will handle the submitted data, using the action attribute. – Peter Gostelow Jul 09 '20 at 01:10
  • 1
    Click on the link I gave you. Method can be omitted. Its default is `GET`. – Asteroids With Wings Jul 09 '20 at 01:23
  • 1
    Doesn't matter, anyway; this question is about the HTTP server returning an error code, not about HTML or Ruby-on-Rails or REST or whatever else you're talking about. The OP didn't even mention `
    `.
    – Asteroids With Wings Jul 09 '20 at 01:27
  • The error code is because the PUT and DELETE don't work as the POST and GET do. They should. The OP didn't specify a mechanism, only how to enable it in apache. My answer is technically correct. What you proposed is a work-a-round. If the OP wasn't using html to POST and GET then he would know how to do PUT and DELETE in http, but he doesn't, so he isn't using http to POST and GET, which brings us to form and method. I read your link and it didn't show PUT and DELETE. It should according to the standard. – Peter Gostelow Jul 09 '20 at 02:37
  • That's your opinion which is not acceptable here. In fact there is no standard solution. https://www.w3.org/Bugs/Public/show_bug.cgi?id=10671 – Peter Gostelow Jul 09 '20 at 21:24
  • 2
    It's not my opinion. I literally linked to the standard document lol – Asteroids With Wings Jul 10 '20 at 10:01
-8

The technical limitations with using PUT and DELETE requests does not lie with PHP or Apache2; it is instead on the burden of the browser to sent those types of requests.

Simply putting <form action="" method="PUT"> will not work because there are no browsers that support that method (and they would simply default to GET, treating PUT the same as it would treat gibberish like FDSFGS). Sadly those HTTP verbs are limited to the realm of non-desktop application browsers (ie: web service consumers).

Adrian
  • 1,392
  • 9
  • 9
  • 12
    He said he wants a restful API so it may well have nothing to do browsers. Anyway, current browsers support PUT, DELETE etc. through the XmlHttpRequest – Artefacto May 29 '10 at 22:48