XF 2.2 Thread creation API suddenly doesn't work

lpickup

Member
My site uses the Xenforo API to automatically create new threads from a PHP script using the Curl library and the POST api/threads/ endpoint. This has worked fine for the past two years, and then suddenly earlier this week it stopped working. My code had not changed, nor had my XF install (although I did upgrade to the latest version to see if that resolved the problem, which it did not).

What appears to be happening is that the server is returning an HTTP 406 status (Not acceptable) and the thread is not created.

Not Acceptable

An appropriate representation of the requested resource could not be found on this server.

When I try to manually submit the request using requestly, it appears to work just fine, so it seems to be something unique to the PHP/Curl environment, yet I can't see what could be causing any differences in this relatively simple request.

Here is a copy of my code:

PHP:
    function makeThread ($fid, $subject, $text) {

      // Send a POST request to the API as follows:
      // <URL_PREFIX>/threads/
      // with the following JSON elements:
      //   node_id = ID of the forum to create the thread in (fid)
      //   title   = Title of the thread (subject)
      //   message = Body of the first post in the thread (text)
      // Should return:
      //   success = true
      //   thread  = Thread data structure

      $url = $this->xf_api_prefix . "threads/";

      $curl = curl_init($url);
      if ($curl === false) {
        error_log ('CURL init failure');
        return false;
      }

      $curl_opts = array (
             CURLOPT_URL => $url,
             CURLOPT_POST => true,
             CURLOPT_RETURNTRANSFER => true,
             CURLOPT_HEADER => true,
      );

      curl_setopt_array($curl, $curl_opts);

      $headers = array(
        "Accept: application/json",
        "XF-Api-Key: " . $this->xf_api_key,
        "Content-Type: application/x-www-form-urlencoded",
      );
      curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);

      $data = "node_id=" . $fid .
              "&title=" . urlencode($subject) .
              "&message=" . urlencode($text);

      curl_setopt($curl, CURLOPT_POSTFIELDS, $data) or die ("curl_setopt fail POSTFIELDS");

      $json = curl_exec($curl);
      if ($json === false) {
        error_log ("CURL exec failure");
        error_log (curl_error($curl));
        error_log (var_export(curl_getinfo($curl),true));
        return false;
      }
      curl_close($curl);

      $resp = json_decode ($json, true);
      if ($resp['success'] != true) {
        return false;
      } else
        return($resp['thread']['view_url']);

    } // makeThread

Any ideas on what could be causing this and how to resolve?

Here is the output of the getinfo call:

[13-Jan-2024 22:20:12 UTC] CURL getinfo:
array (
'url' => 'https://discuss.fastcharger.info/api/threads/',
'content_type' => 'text/html; charset=iso-8859-1',
'http_code' => 406,
'header_size' => 134,
'request_size' => 636,
'filetime' => -1,
'ssl_verify_result' => 0,
'redirect_count' => 0,
'total_time' => 0.0121239999999999993607335824208348640240728855133056640625,
'namelookup_time' => 0.00097999999999999996835864379818303859792649745941162109375,
'connect_time' => 0.00108299999999999997830901765638600409147329628467559814453125,
'pretransfer_time' => 0.01090799999999999929378713403593792463652789592742919921875,
'size_upload' => 433.0,
'size_download' => 249.0,
'speed_download' => 20537.0,
'speed_upload' => 35714.0,
'download_content_length' => 249.0,
'upload_content_length' => 433.0,
'starttransfer_time' => 0.01209099999999999931754590676291627460159361362457275390625,
'redirect_time' => 0.0,
'redirect_url' => '',
'primary_ip' => '199.250.199.11',
'certinfo' =>
array (
),
'primary_port' => 443,
'local_ip' => '199.250.196.7',
'local_port' => 37842,
'http_version' => 3,
'protocol' => 2,
'ssl_verifyresult' => 0,
'scheme' => 'HTTPS',
'appconnect_time_us' => 10587,
'connect_time_us' => 1083,
'namelookup_time_us' => 980,
'pretransfer_time_us' => 10908,
'redirect_time_us' => 0,
'starttransfer_time_us' => 12091,
'total_time_us' => 12124,
'request_header' => 'POST /api/threads/ HTTP/2
Host: discuss.fastcharger.info
Accept: application/json
XF-Api-Key: <my API key redacted>
Content-Type: application/x-www-form-urlencoded
Content-Length: 433

',
)


As I said, this has been working perfectly for over a year now and suddenly stopped working this past week.
 
The error message suggests it's being denied by Apache rather than PHP/XF. I'd suspect mod_security or similar, but I'd check your web server error log to be sure.
 
Thanks. I do agree that it's Apache that's throwing the error, but the question is still why?

Unfortunately my server is a strange hybrid of a VPS server where the provider has removed a lot of my visibility and control of the the web server setup and logs. I do get a snapshot of the Apache access logs a day later, but obviously that makes it difficult to debug real-time.

I was able to look at a snapshot of the access logs for successful posts up until the time where it began to fail, but nothing jumps out (other than perhaps the fact that there is no data between 08/Jan and 13/Jan when I started to debug this--there should have at least been some attempts on the 9th-12th, but perhaps the script was bailing out due to a similar error earlier.

199.250.196.7 - - [05/Jan/2024:02:52:29 -0500] "POST /api/threads/ HTTP/2.0" 200 5044 "-" "-"
199.250.196.7 - - [05/Jan/2024:17:09:18 -0500] "POST /api/threads/ HTTP/2.0" 200 5006 "-" "-"
199.250.196.7 - - [06/Jan/2024:02:52:03 -0500] "POST /api/threads/ HTTP/2.0" 200 5028 "-" "-"
199.250.196.7 - - [06/Jan/2024:02:52:04 -0500] "POST /api/threads/ HTTP/2.0" 200 5047 "-" "-"
199.250.196.7 - - [06/Jan/2024:02:52:05 -0500] "POST /api/threads/ HTTP/2.0" 200 5024 "-" "-"
199.250.196.7 - - [06/Jan/2024:02:52:06 -0500] "POST /api/threads/ HTTP/2.0" 200 5044 "-" "-"
199.250.196.7 - - [06/Jan/2024:02:52:07 -0500] "POST /api/threads/ HTTP/2.0" 200 4855 "-" "-"
199.250.196.7 - - [07/Jan/2024:02:52:04 -0500] "POST /api/threads/ HTTP/2.0" 200 5132 "-" "-"
199.250.196.7 - - [07/Jan/2024:02:52:05 -0500] "POST /api/threads/ HTTP/2.0" 200 5093 "-" "-"
199.250.196.7 - - [08/Jan/2024:02:52:03 -0500] "POST /api/threads/ HTTP/2.0" 200 5045 "-" "-"
199.250.196.7 - - [13/Jan/2024:13:58:45 -0500] "POST /api/threads/ HTTP/2.0" 406 249 "-" "-"
199.250.196.7 - - [13/Jan/2024:14:16:47 -0500] "POST /api/threads/ HTTP/2.0" 406 249 "-" "-"
199.250.196.7 - - [13/Jan/2024:14:17:21 -0500] "POST /api/threads/ HTTP/2.0" 406 249 "-" "-"
199.250.196.7 - - [13/Jan/2024:14:19:37 -0500] "POST /api/threads/ HTTP/2.0" 406 249 "-" "-"

I'm just wondering if there is anything in any XF logs that I could be looking for?
 
Actually I went ahead and wrote a very simple script to receive POST requests and even that fails, so it definitely appears to be something in my environment rather than XF. I've reached out to my hosting provider's customer support to see if they can provide any guidance. Thanks for your help.
 
Just to close this out, after some more investigation, it appeared that ALL CURL requests (even simple GET requests, and even from the curl command line) were resulting in 406 errors. So in my code I set the CURLOPT_USERAGENT option to a known browser and voila, it's now working again. I'm not sure if this was an attempt at increased security or a misconfiguration on the part of my web host provider, but at least I have a working solution again.
 
Top Bottom