[DigitalPoint] App for Cloudflare®

[DigitalPoint] App for Cloudflare® 1.8.2

No permission to download
How to limit "Cache pages for guests" to subdomain having forum only? It looks like it applies to all subdomains in the account.
 
@digitalpoint could use your help on something. Yandex Webmaster Tool is going crazy telling me I have errors in my sitemaps

Apparently there are URLs pointing to //data.domain.com/ and not https://data.domain.com

Any way I can fix this with the R2 buckets implementation?

Thank you.
It’s a valid URL without protocol, but if Yandex doesn’t understand it (and you care), you can add the protocol under Admin -> Options -> External service providers

Although I’m not sure why anything from that subdomain would be in your sitemaps.

How to limit "Cache pages for guests" to subdomain having forum only? It looks like it applies to all subdomains in the account.
You can adjust the guest page caching rule to be specific to a certain hostname if you want in your Cache Rules in Cloudflare. Although the only thing that should happen is you would be saying things are eligible for cache (not forced to cache), so if your other subdomains are sending wrong cache control headers in their http responses you probably want to sort that out either way.
 
You can adjust the guest page caching rule to be specific to a certain hostname if you want in your Cache Rules in Cloudflare. Although the only thing that should happen is you would be saying things are eligible for cache (not forced to cache), so if your other subdomains are sending wrong cache control headers in their http responses you probably want to sort that out either way.
Maybe the add-on should add caching rule based on forum URL to avoid this issue?
 
The issue there would be a problem for sites that use multiple subdomains for their setup. But like I said, I can’t think of a reason why making something eligible for cache should affect much of anything because that’s how most file extensions work by default with Cloudflare, so only real change would be html pages are also eligible (but you would need to still set a cache control header to instruct it to actually be cached). The addon is definitely not adding cache control headers to anything outside of XenForo, so if your other pages are insteucting Cloudflare to cache it by setting a public cache control header (and you don’t want it cached), you really need to look at why those pages are asking to be cached.

Again, it doesn’t force anything to cache, it’s simply telling Cloudflare listen to what a page is instructing to do as far as cache based on its cache control http header.

Do you have an example of a URL that’s being cached that shouldn’t be?
 
In case somebody else needs this too, here is the @digitalpoint solution.

To limit guest page caching to subdomain, use CloudFlare dashboard under Caching -> Cache Rules -> pick "Cache XenForo guest pages" from the list, click "Edit" then "And" and add "Hostname" "equals" subdomain.example.com

Expression Preview should look like this:
Code:
(not http.cookie contains "xf_session=" and not http.cookie contains "xf_user=" and http.host eq "subdomain.example.com")
 
Well, that’s technically the last way I would address applications outside of XenForo running on the same domain personally. 😀

Best option: Have your server set proper cache control headers.
Second best option: Use Cloudflare transform rules to set proper cache control headers.
Third best option: Use an independent cache rule to do it.

Leaving no cache control headers is your server telling proxies and browsers to cache if you want, or not. Do whatever you want. It’s best to have a specific cache control policy so you know how everything will be cached.
 
@digitalpoint

Got following 3 entries in the server error log twice since updating to 1.5.7 yesterday, once yesterday at 6:56PM and once this morning at 8:10AM.

Everything seems to be working, but figured I'd let you know :)

Server error log

ErrorException: Cloudflare: Invalid response, code: 499 / src/XF/Error.php:77

Generated by: Unknown account Feb 9, 2023 at 6:56 PM

Stack trace

#0 src/XF.php(219): XF\Error->logError('Cloudflare: Inv...', false)
#1 src/addons/DigitalPoint/Cloudflare/Traits/XF.php(144): XF::logError('Cloudflare: Inv...')
#2 src/addons/DigitalPoint/Cloudflare/Api/Cloudflare.php(491): DigitalPoint\Cloudflare\Api\Cloudflare->logError('Cloudflare: Inv...')
#3 src/addons/DigitalPoint/Cloudflare/Api/Advanced.php(389): DigitalPoint\Cloudflare\Api\CloudflareAbstract->makeRequest('HEAD', 'attachments/0/9...', Array, true, 'xenforodev-attachm...')
#4 src/addons/DigitalPoint/Cloudflare/League/Flysystem/Adapter/R2.php(195): DigitalPoint\Cloudflare\Api\Advanced->headR2Object('xenforodev-attachm...', 'attachments/0/9...')
#5 src/addons/DigitalPoint/Cloudflare/League/Flysystem/Adapter/R2.php(83): DigitalPoint\Cloudflare\League\Flysystem\Adapter\R2->getMetadata('attachments/0/9...')
#6 src/vendor/league/flysystem/src/Filesystem.php(57): DigitalPoint\Cloudflare\League\Flysystem\Adapter\R2->has('attachments/0/9...')
#7 [internal function]: League\Flysystem\Filesystem->has('attachments/0/9...', Array)
#8 src/vendor/league/flysystem-eventable-filesystem/src/EventableFilesystem.php(431): call_user_func_array('League\\Flysyste...', Array)
#9 src/vendor/league/flysystem-eventable-filesystem/src/EventableFilesystem.php(395): League\Flysystem\EventableFilesystem\EventableFilesystem->callFilesystemMethod('has', Array)
#10 src/vendor/league/flysystem-eventable-filesystem/src/EventableFilesystem.php(128): League\Flysystem\EventableFilesystem\EventableFilesystem->delegateMethodCall('has', Array)
#11 src/vendor/league/flysystem/src/MountManager.php(313): League\Flysystem\EventableFilesystem\EventableFilesystem->has('attachments/0/9...')
#12 src/XF/Util/File.php(245): League\Flysystem\MountManager->has('attachments/0/9...')
#13 src/addons/ThemeHouse/ImageOptimizer/ContentHandler/Attachment.php(101): XF\Util\File::abstractedPathExists('internal-data:/...')
#14 src/addons/ThemeHouse/ImageOptimizer/ContentHandler/AbstractHandler.php(197): ThemeHouse\ImageOptimizer\ContentHandler\Attachment->hasImage(Object(SV\AttachmentImprovements\XF\Entity\AttachmentData))
#15 src/addons/ThemeHouse/ImageOptimizer/Cron/Optimize.php(31): ThemeHouse\ImageOptimizer\ContentHandler\AbstractHandler->optimize(Object(ThemeHouse\ImageOptimizer\Entity\Status))
#16 src/XF/Job/Cron.php(37): ThemeHouse\ImageOptimizer\Cron\Optimize::eek:ptimizeImages(Object(XF\Entity\CronEntry))
#17 src/XF/Job/Manager.php(260): XF\Job\Cron->run(8)
#18 src/XF/Job/Manager.php(202): XF\Job\Manager->runJobInternal(Array, 8)
#19 src/XF/Job/Manager.php(86): XF\Job\Manager->runJobEntry(Array, 8)
#20 src/XF/Cli/Command/RunJobs.php(59): XF\Job\Manager->runQueue(false, 8)
#21 src/vendor/symfony/console/Command/Command.php(255): XF\Cli\Command\RunJobs->execute(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#22 src/vendor/symfony/console/Application.php(992): Symfony\Component\Console\Command\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#23 src/vendor/symfony/console/Application.php(255): Symfony\Component\Console\Application->doRunCommand(Object(XF\Cli\Command\RunJobs), Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#24 src/vendor/symfony/console/Application.php(148): Symfony\Component\Console\Application->doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#25 src/XF/Cli/Runner.php(111): Symfony\Component\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#26 cmd.php(15): XF\Cli\Runner->run()
#27 {main}

Request state

array(1) {
["cli"] => string(80) "/home/nginx/domains/domain.com/public/xenforo/cmd.php --quiet xf:run-jobs"
}

Server error log

ErrorException: Cloudflare: String could not be parsed as XML / null src/XF/Error.php:77

Generated by: Unknown account Feb 9, 2023 at 6:56 PM

Stack trace

#0 src/XF.php(219): XF\Error->logError('Cloudflare: Str...', false)
#1 src/addons/DigitalPoint/Cloudflare/Traits/XF.php(144): XF::logError('Cloudflare: Str...')
#2 src/addons/DigitalPoint/Cloudflare/Api/Cloudflare.php(530): DigitalPoint\Cloudflare\Api\Cloudflare->logError('Cloudflare: Str...')
#3 src/addons/DigitalPoint/Cloudflare/Api/Advanced.php(389): DigitalPoint\Cloudflare\Api\CloudflareAbstract->makeRequest('HEAD', 'attachments/0/9...', Array, true, 'xenforodev-attachm...')
#4 src/addons/DigitalPoint/Cloudflare/League/Flysystem/Adapter/R2.php(195): DigitalPoint\Cloudflare\Api\Advanced->headR2Object('xenforodev-attachm...', 'attachments/0/9...')
#5 src/addons/DigitalPoint/Cloudflare/League/Flysystem/Adapter/R2.php(83): DigitalPoint\Cloudflare\League\Flysystem\Adapter\R2->getMetadata('attachments/0/9...')
#6 src/vendor/league/flysystem/src/Filesystem.php(57): DigitalPoint\Cloudflare\League\Flysystem\Adapter\R2->has('attachments/0/9...')
#7 [internal function]: League\Flysystem\Filesystem->has('attachments/0/9...', Array)
#8 src/vendor/league/flysystem-eventable-filesystem/src/EventableFilesystem.php(431): call_user_func_array('League\\Flysyste...', Array)
#9 src/vendor/league/flysystem-eventable-filesystem/src/EventableFilesystem.php(395): League\Flysystem\EventableFilesystem\EventableFilesystem->callFilesystemMethod('has', Array)
#10 src/vendor/league/flysystem-eventable-filesystem/src/EventableFilesystem.php(128): League\Flysystem\EventableFilesystem\EventableFilesystem->delegateMethodCall('has', Array)
#11 src/vendor/league/flysystem/src/MountManager.php(313): League\Flysystem\EventableFilesystem\EventableFilesystem->has('attachments/0/9...')
#12 src/XF/Util/File.php(245): League\Flysystem\MountManager->has('attachments/0/9...')
#13 src/addons/ThemeHouse/ImageOptimizer/ContentHandler/Attachment.php(101): XF\Util\File::abstractedPathExists('internal-data:/...')
#14 src/addons/ThemeHouse/ImageOptimizer/ContentHandler/AbstractHandler.php(197): ThemeHouse\ImageOptimizer\ContentHandler\Attachment->hasImage(Object(SV\AttachmentImprovements\XF\Entity\AttachmentData))
#15 src/addons/ThemeHouse/ImageOptimizer/Cron/Optimize.php(31): ThemeHouse\ImageOptimizer\ContentHandler\AbstractHandler->optimize(Object(ThemeHouse\ImageOptimizer\Entity\Status))
#16 src/XF/Job/Cron.php(37): ThemeHouse\ImageOptimizer\Cron\Optimize::eek:ptimizeImages(Object(XF\Entity\CronEntry))
#17 src/XF/Job/Manager.php(260): XF\Job\Cron->run(8)
#18 src/XF/Job/Manager.php(202): XF\Job\Manager->runJobInternal(Array, 8)
#19 src/XF/Job/Manager.php(86): XF\Job\Manager->runJobEntry(Array, 8)
#20 src/XF/Cli/Command/RunJobs.php(59): XF\Job\Manager->runQueue(false, 8)
#21 src/vendor/symfony/console/Command/Command.php(255): XF\Cli\Command\RunJobs->execute(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#22 src/vendor/symfony/console/Application.php(992): Symfony\Component\Console\Command\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#23 src/vendor/symfony/console/Application.php(255): Symfony\Component\Console\Application->doRunCommand(Object(XF\Cli\Command\RunJobs), Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#24 src/vendor/symfony/console/Application.php(148): Symfony\Component\Console\Application->doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#25 src/XF/Cli/Runner.php(111): Symfony\Component\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#26 cmd.php(15): XF\Cli\Runner->run()
#27 {main}

Request state

array(1) {
["cli"] => string(80) "/home/nginx/domains/domain.com/public/xenforo/cmd.php --quiet xf:run-jobs"
}

Server error log

Error: Call to a member function getBody() on array src/addons/DigitalPoint/Cloudflare/Traits/XF.php:132

Generated by: Unknown account Feb 9, 2023 at 6:56 PM

Stack trace

#0 src/addons/DigitalPoint/Cloudflare/Api/Cloudflare.php(538): DigitalPoint\Cloudflare\Api\Cloudflare->parseResponse(Array)
#1 src/addons/DigitalPoint/Cloudflare/Api/Advanced.php(389): DigitalPoint\Cloudflare\Api\CloudflareAbstract->makeRequest('HEAD', 'attachments/0/9...', Array, true, 'xenforodev-attachm...')
#2 src/addons/DigitalPoint/Cloudflare/League/Flysystem/Adapter/R2.php(195): DigitalPoint\Cloudflare\Api\Advanced->headR2Object('xenforodev-attachm...', 'attachments/0/9...')
#3 src/addons/DigitalPoint/Cloudflare/League/Flysystem/Adapter/R2.php(83): DigitalPoint\Cloudflare\League\Flysystem\Adapter\R2->getMetadata('attachments/0/9...')
#4 src/vendor/league/flysystem/src/Filesystem.php(57): DigitalPoint\Cloudflare\League\Flysystem\Adapter\R2->has('attachments/0/9...')
#5 [internal function]: League\Flysystem\Filesystem->has('attachments/0/9...', Array)
#6 src/vendor/league/flysystem-eventable-filesystem/src/EventableFilesystem.php(431): call_user_func_array('League\\Flysyste...', Array)
#7 src/vendor/league/flysystem-eventable-filesystem/src/EventableFilesystem.php(395): League\Flysystem\EventableFilesystem\EventableFilesystem->callFilesystemMethod('has', Array)
#8 src/vendor/league/flysystem-eventable-filesystem/src/EventableFilesystem.php(128): League\Flysystem\EventableFilesystem\EventableFilesystem->delegateMethodCall('has', Array)
#9 src/vendor/league/flysystem/src/MountManager.php(313): League\Flysystem\EventableFilesystem\EventableFilesystem->has('attachments/0/9...')
#10 src/XF/Util/File.php(245): League\Flysystem\MountManager->has('attachments/0/9...')
#11 src/addons/ThemeHouse/ImageOptimizer/ContentHandler/Attachment.php(101): XF\Util\File::abstractedPathExists('internal-data:/...')
#12 src/addons/ThemeHouse/ImageOptimizer/ContentHandler/AbstractHandler.php(197): ThemeHouse\ImageOptimizer\ContentHandler\Attachment->hasImage(Object(SV\AttachmentImprovements\XF\Entity\AttachmentData))
#13 src/addons/ThemeHouse/ImageOptimizer/Cron/Optimize.php(31): ThemeHouse\ImageOptimizer\ContentHandler\AbstractHandler->optimize(Object(ThemeHouse\ImageOptimizer\Entity\Status))
#14 src/XF/Job/Cron.php(37): ThemeHouse\ImageOptimizer\Cron\Optimize::optimizeImages(Object(XF\Entity\CronEntry))
#15 src/XF/Job/Manager.php(260): XF\Job\Cron->run(8)
#16 src/XF/Job/Manager.php(202): XF\Job\Manager->runJobInternal(Array, 8)
#17 src/XF/Job/Manager.php(86): XF\Job\Manager->runJobEntry(Array, 8)
#18 src/XF/Cli/Command/RunJobs.php(59): XF\Job\Manager->runQueue(false, 8)
#19 src/vendor/symfony/console/Command/Command.php(255): XF\Cli\Command\RunJobs->execute(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#20 src/vendor/symfony/console/Application.php(992): Symfony\Component\Console\Command\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#21 src/vendor/symfony/console/Application.php(255): Symfony\Component\Console\Application->doRunCommand(Object(XF\Cli\Command\RunJobs), Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#22 src/vendor/symfony/console/Application.php(148): Symfony\Component\Console\Application->doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#23 src/XF/Cli/Runner.php(111): Symfony\Component\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#24 cmd.php(15): XF\Cli\Runner->run()
#25 {main}

Request state

array(1) {
["cli"] => string(80) "/home/nginx/domains/domain.com/public/xenforo/cmd.php --quiet xf:run-jobs"
}
 
If it "fixed itself" and you only saw some errors briefly at the same time (from the logs you posted, it looks like they all happened at the same time there), my guess is that it was something going on with the server/network. It got an HTTP code 499, which is the response you get if the HTTP client (in this case GuzzleHttp) unexpectedly disconnected. So if there was a network issue between your server and Cloudflare momentarily (Internet routes constantly get re-routed), you might see that momentarily while the network was changing routes (maybe a fiber was cut somewhere at the same time or a router was rebooted right then). Could be one of a lot of things... but if it's not something ongoing, I wouldn't worry about it. There's never going to be a scenario where Internet network connectivity is 100% stable (rerouting, packet loss, congestion, etc.), the best you can do is minimize it.
 
I have been waiting SO long to get cheap storage for attachments in R2 by using this plugin! Thanks for making it so easy!

Stupid question maybe: once I start using R2 as storage, must I move all existing attachments there or can they stay on the webhost while new ones are uploaded in the bucket? I don't have access to the CLI on the webhost, so I'll try RClone shortly...
 
If you switch to R2, things uploaded new will go to R2, but until you have moved old stuff, they won’t be available. I’d check out rclone and move things first (rclone has the ability to do just changes, so you can run it multiple times and it only will need to process new stuff since it last run).
 
Just noticed that previous attachments are no longer visible, and I'm digging into how to use rclone.

We didn't allow attachments uploaded on the forum due to usual space constraints in a regular web host over the years. Only admins could upload screenshots to use in tutorials, for instance.

But users are struggling more and more to get decent free photo hosting elsewhere and embed linked photos in posts. So with the availability of R2 and very decent free tier limits, I'll open the gates... just need to get it working well. :)

[edit] Ok, transfer in progress. For a forum that didn't allow attachments, it's a bit odd that data had like 2GB files and internal_data had attachments totalling 8GB :D It was easier to create a ZIP archive at the host, download it and run the rclone copy, than try to do it live over FTP as source.

Once the data is fully transferred in buckets, can the folders with attachments be deleted from current webhost?
 
Last edited:
If you switch to R2, things uploaded new will go to R2, but until you have moved old stuff, they won’t be available. I’d check out rclone and move things first (rclone has the ability to do just changes, so you can run it multiple times and it only will need to process new stuff since it last run).
So, i) create the bucket on CF R2 first, ii) rclone contents of the dir from XF to R2, iii) visit /admin.php?cloudflare/r2 to switch on R2 integration and select to use an existing bucket. Is this correct?
 
Yeah, something like that. You'll need 2 buckets, and do an initial data replication before you switch storage setting. Then you can do a subsequent sync for any difference that may have popped up on your live forum.
 
What time limit do you recommend for guest caching? I see 60 minutes is the default all the way down to 5. What would you recommend? I was using the Litespeed cache before but thought I might try this one out. It seems like it does the exact same thing.

EDIT* I just set it at 5 minutes
 
Last edited:
Just wanted to post this in here as well:


Since swapping from the standard XF S3 support to this, it appears the rotate addon is no longer working.

I'm not sure which would addon would be the cause though :unsure:
 
Top Bottom