XF 2.2 Running a delete request on an attachment returns a 405 error. Why?

Fullmental

Active member
I don't get this. I am using a super user key for the API with full privileges, and I've tried an admin key with all scopes allowed. I run a delete request on an attachment ID I know exists, and the response I get is a 405 error. That makes no sense. There's literally nothing I should be doing with the API other than the request and the headers which include the super user key and the "application/x-www-form-urlencoded" content type as directed in the endpoint documentation. I don't see how I can possibly get this one wrong, there's literally nothing else to do in the request:

1684108346873.webp

Code:

Code:
import requests
import json

HEADER = {'XF-Api-Key':'<REDACTED>', 'application/x-www-form-urlencoded'}

r = requests.delete("https://example.com/api/attachments/1", headers = HEADER)
print(r)

Output: <Response [405]>

Why? All the other API calls I make work just fine. This one is the only one I've tried that doesn't work.
 
Last edited:
Using some debugging statements I was able to confirm the API controller was being invoked, so there is not a firewall or other issue preventing the delete request from reaching the Xenforo instance. However, the actionDelete function is never called. I am currently stepping through all the source code trying to figure out where it goes from the controller...
 
I can't reproduce this locally. Maybe worth noting that you don't need to set the content type header since there is no request body (and I think the syntax if you did would actually be 'Content-Type': 'application-x-www-form-urlencoded'), but in my tests (albeit with a different REST client) it did not make a difference either way. I'm curious what response body you're getting beyond just the error code.
 
I can't reproduce this locally. Maybe worth noting that you don't need to set the content type header since there is no request body (and I think the syntax if you did would actually be 'Content-Type': 'application-x-www-form-urlencoded'), but in my tests (albeit with a different REST client) it did not make a difference either way. I'm curious what response body you're getting beyond just the error code.

Interesting. I don't know what might cause the discrepancy.

So, when I do a simple cURL request, for example to delete some test profile post I just made: curl -i https://example.com/forum/api/profile-posts/7982 'HEADERINFO' > response.json, I jsut get this:

Code:
HTTP/2 405
server: nginx/1.18.0 (Ubuntu)
date: Mon, 15 May 2023 01:27:09 GMT
content-type: text/html
content-length: 166

<html>
<head><title>405 Not Allowed</title></head>
<body>
<center><h1>405 Not Allowed</h1></center>
<hr><center>nginx/1.18.0 (Ubuntu)</center>
</body>
</html>

I've checked my nginx config and php-fpm, and there is nothing in the config files I can see to reject an http delete request. There's also no firewall rules that I can see rejecting this either.

When you make an API call, how does it get routed to the correct controller or function? I'd like to trace it from start to finish if I can. I suppose it's possible there is an addon or other configuration different from the default that is causing this. Since I'm only attempting this on a test instance for now, I could systematically go through and uninstall every addon one by one to see if they make a difference.
 
Last edited:
That response body comes from the web server and not XF. I know you say you are sure the API controller is being invoked, so I guess it's possible that it's intercepting the XF response, but I don't believe anything in the API would return a 405 response code. Unimplemented methods return a 404 and permission errors return a 403.

When you make an API call, how does it get routed to the correct controller or function? I'd like to trace it from start to finish if I can. I suppose it's possible there is an addon or other configuration different from the default that is causing this. Since I'm only attempting this on a test instance for now, I could systematically go through and uninstall every addon one by one to see if they make a difference.
It would go through the dispatcher (\XF\Api\Mvc\Dispatcher) and consequently the router (\XF\Api\Mvc\Router) to get a route match object. Then the route match is run through the dispatch loop until a reply object is received from the controller.
 
That response body comes from the web server and not XF. I know you say you are sure the API controller is being invoked, so I guess it's possible that it's intercepting the XF response, but I don't believe anything in the API would return a 405 response code. Unimplemented methods return a 404 and permission errors return a 403.


It would go through the dispatcher (\XF\Api\Mvc\Dispatcher) and consequently the router (\XF\Api\Mvc\Router) to get a route match object. Then the route match is run through the dispatch loop until a reply object is received from the controller.
You are right. It was a different request that was invoking the api controller. My mistake.

I just tried bypassing my CDN (cloudflare), running on a fresh install of apache2 with a fresh install of php8.0 (previously using 8.1 and nginx), same issue. I made absolutely no changes to either default config except to point apache2 to use php8.0 instead of the default 8.1, and to point apache2 to my forum directory and enable permissions on it. So maybe it's not reaching XF after all.
 
OK, I did figure out the problem. I had the following line in my nginx config for our /forum path:

Code:
    location /forum {
        try_files $uri $uri/ /forum/?$uri&$args;
    }

It appears that try_files line was not correct. I updated it to try_files $uri $uri/ /forum/index.php?$uri&$args; and it began working. I don't understand how the previous one worked at all for everything else, and just didn't work for delete requests.

Unrelated, the apache config didn't work because there was no .htaccess file with a rewriteengine config defined. I had to restore the default one from the install, don't know why it wasn't present but obviously we never had problems because we never have used apache2 before. Once that worked, it gave me a hint as to where to check nginx (namely the site config, not the engine config)

Thank you for your time and assistance! I would have spent hours digging through the src files in the xf install if not for your suggestions.
 
Last edited:
If you have an index directive in nginx pointing to index.php then it will allow GET and POST requests for directories to hit that, but not other requests.
 
Top Bottom