Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

An error occurred uploading an image #4586

Closed
2 tasks done
SysAdminSmith opened this issue Sep 28, 2023 · 11 comments
Closed
2 tasks done

An error occurred uploading an image #4586

SysAdminSmith opened this issue Sep 28, 2023 · 11 comments

Comments

@SysAdminSmith
Copy link

SysAdminSmith commented Sep 28, 2023

Attempted Debugging

  • I have read the debugging page

Searched GitHub Issues

  • I have searched GitHub for the issue.

Describe the Scenario

Greetings:

I am running Bookstack within a LXC container (Debian 12) on a ProxMox host. Bookstack is served up and reverse-proxied via Cloudflare Tunnel Services which also handles the cert.

Cloudflare is configured as follows: https://bookstack.foo.bar/ -> http://192.168.1.1/

Apache2 receives the request with the following config:

Details

<VirtualHost *:80>

	# This is a simple example of an Apache VirtualHost configuration
	# file that could be used with BookStack.
	# This assumes mod_php has been installed and is loaded.
	#
	# Change the "docs.example.com" usage in the "ServerName" directive
	# to be your web domain for BookStack.
	#
	# Change the "/var/www/bookstack/public/", used twice below, to the
	# location of the "public" folder within your BookStack installation.
	#
	# This configuration is only for HTTP, Not HTTPS.
	# For HTTPS we recommend using https://certbot.eff.org/

	ServerName bookstack.foo.bar
	DocumentRoot /var/www/bookstack/public/

	<Directory /var/www/bookstack/public/>
		Options Indexes FollowSymLinks
		AllowOverride None
		Require all granted
		<IfModule mod_rewrite.c>
			<IfModule mod_negotiation.c>
				Options -MultiViews -Indexes
			</IfModule>

			RewriteEngine On

			# Handle Authorization Header
			RewriteCond %{HTTP:Authorization} .
			RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

			# Redirect Trailing Slashes If Not A Folder...
			RewriteCond %{REQUEST_FILENAME} !-d
			RewriteCond %{REQUEST_URI} (.+)/$
			RewriteRule ^ %1 [L,R=301]

			# Handle Front Controller...
			RewriteCond %{REQUEST_FILENAME} !-d
			RewriteCond %{REQUEST_FILENAME} !-f
			RewriteRule ^ index.php [L]
		</IfModule>
	</Directory>

	ErrorLog ${APACHE_LOG_DIR}/error.log
	CustomLog ${APACHE_LOG_DIR}/access.log combined

</VirtualHost>

My .env is as follows:

Details

# This file, when named as ".env" in the root of your BookStack install
# folder, is used for the core configuration of the application.
# By default this file contains the most common required options but
# a full list of options can be found in the '.env.example.complete' file.
#APP_DEBUG=true
# NOTE: If any of your values contain a space or a hash you will need to
# wrap the entire value in quotes. (eg. MAIL_FROM_NAME="BookStack Mailer")

# Application key
# Used for encryption where needed.
# Run `php artisan key:generate` to generate a valid key.
APP_KEY=base64:firidoX8NFE1bZNjwowzQcv62K0rr7F93ijGuinSLcg=

# Application URL
# This must be the root URL that you want to host BookStack on.
# All URLs in BookStack will be generated using this value
# to ensure URLs generated are consistent and secure.
# If you change this in the future you may need to run a command
# to update stored URLs in the database. Command example:
# php artisan bookstack:update-url https://old.example.com https://new.example.com
APP_URL=https://bookstack.foo.bar

#Database details
DB_HOST=localhost
DB_DATABASE=bookstack
DB_USERNAME=bookstack
DB_PASSWORD=extremelysecurepassword

# Mail system to use
# Can be 'smtp' or 'sendmail'
MAIL_DRIVER=smtp

# Mail sender details
MAIL_FROM_NAME="BookStack"
MAIL_FROM=bookstack.ldap@foo.bar

# SMTP mail options
# These settings can be checked using the "Send a Test Email"
# feature found in the "Settings > Maintenance" area of the system.
# For more detailed documentation on mail options, refer to:
# https://www.bookstackapp.com/docs/admin/email-webhooks/#email-configuration
MAIL_HOST=smtp.office365.com
MAIL_PORT=587
MAIL_USERNAME=bookstack.ldap@foo.bar
MAIL_PASSWORD=extremelysecurepassword_too
MAIL_ENCRYPTION=tls

STORAGE_TYPE=local
FILE_UPLOAD_SIZE_LIMIT=100

So, my setup is:

Cloudflare (https://bookstack.foo.bar/) -> Apache2 (*:80) -> /var/www/bookstack

Additionally, all of /var/www/bookstack is owned recursively by www-data:www-data

Still, any time I attempt to upload an image to a page whilst editing, I get this:

image

Finally, browser debugging panel looks thusly:

Details

app.js?version=v23.08:43 Refused to set the document's base URI to '' because it violates the following Content Security Policy directive: "base-uri 'self'".

init_instance_callback @ app.js?version=v23.08:43
edit:1 Mixed Content: The page at 'https://bookstack.foo.bar/books/azure/page/create-the-storage-account/edit' was loaded over HTTPS, but requested an insecure resource 'http://bookstack.foo.bar/images/gallery/'. This request has been blocked; the content must be served over HTTPS.
app.js?version=v23.08:25 TypeError: Failed to fetch
    at Go (app.js?version=v23.08:18:1286)
    at an (app.js?version=v23.08:18:1752)
    at Object.Gu (app.js?version=v23.08:18:1858)
    at jf (app.js?version=v23.08:25:32608)
    at app.js?version=v23.08:25:32980
(anonymous) @ app.js?version=v23.08:25
edit:1 Mixed Content: The page at 'https://bookstack.foo.bar/books/azure/page/create-the-storage-account/edit' was loaded over HTTPS, but requested an insecure resource 'http://bookstack.foo.bar/images/gallery/'. This request has been blocked; the content must be served over HTTPS.
app.js?version=v23.08:25 TypeError: Failed to fetch
    at Go (app.js?version=v23.08:18:1286)
    at an (app.js?version=v23.08:18:1752)
    at Object.Gu (app.js?version=v23.08:18:1858)
    at jf (app.js?version=v23.08:25:32608)
    at app.js?version=v23.08:25:32980

Any thoughts? Any help is greatly appreciated!

Also, I posted this over on Redit but am posting here in case this is the better location. If this is viewed as spam, I will happily take one down.

Exact BookStack Version

v23.08

Log Content

tail -f for /var/log/apache2/access.log at time of error

Note: 192.168.1.50 is the IP for my Cloudflare Tunnel Container

Details

192.168.1.50 - - [28/Sep/2023:12:58:57 +0000] "POST /login HTTP/1.1" 302 2006 "https://bookstack.dauntlessdiscovery.work/login" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36"
192.168.1.50 - - [28/Sep/2023:12:58:57 +0000] "GET / HTTP/1.1" 200 8401 "https://bookstack.dauntlessdiscovery.work/login" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36"
192.168.1.50 - - [28/Sep/2023:12:59:01 +0000] "GET /books/azure/page/create-the-storage-account HTTP/1.1" 200 10271 "https://bookstack.dauntlessdiscovery.work/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36"
192.168.1.50 - - [28/Sep/2023:12:59:07 +0000] "GET /books/azure/page/create-the-storage-account/edit HTTP/1.1" 200 16139 "https://bookstack.dauntlessdiscovery.work/books/azure/page/create-the-storage-account" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36"
192.168.1.50 - - [28/Sep/2023:12:59:07 +0000] "GET /search/entity-selector?types=book%2Cchapter%2Cpage&permission=view HTTP/1.1" 200 3567 "https://bookstack.dauntlessdiscovery.work/books/azure/page/create-the-storage-account/edit" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36"
192.168.1.50 - - [28/Sep/2023:12:59:31 +0000] "POST /images/gallery?uploaded_to=21 HTTP/1.1" 301 686 "https://bookstack.dauntlessdiscovery.work/books/azure/page/create-the-storage-account/edit" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36"
192.168.1.50 - - [28/Sep/2023:12:59:38 +0000] "PUT /ajax/page/21/save-draft HTTP/1.1" 200 1615 "https://bookstack.dauntlessdiscovery.work/books/azure/page/create-the-storage-account/edit" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36"   

tail -f for /var/www/bookstack/storage/laravel.log at time of error

Details

#27 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ValidatePostSize.php(27): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()                                                                                       
#28 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\\Foundation\\Http\\Middleware\\ValidatePostSize->handle()                                                                                                             
#29 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php(86): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()                                                                       
#30 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\\Foundation\\Http\\Middleware\\PreventRequestsDuringMaintenance->handle()                                                                                             
#31 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(116): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()                                                                                                                
#32 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(165): Illuminate\\Pipeline\\Pipeline->then()
#33 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(134): Illuminate\\Foundation\\Http\\Kernel->sendRequestThroughRouter()                                                                                                            
#34 /var/www/bookstack/public/index.php(52): Illuminate\\Foundation\\Http\\Kernel->handle()                                           
#35 {main}                                                                                                                            
"}

Hosting Environment

PHP 8.2.10
Apache2 2.4.57 (Debian)
Debian 12 (bookworm)

Housed in a LXC container within a ProxMox environment

PVE: pve-manager/8.0.3/bbf3993334bfa916
Kernel: Linux 6.2.16-3-pve #1 SMP PREEMPT_DYNAMIC PVE 6.2.16-3 (2023-06-17T05:58Z)

@ssddanbrown
Copy link
Member

Could you get a bigger chunk from laravel.log when the error occurs? Right now that only provides the tail end of the log stack. Getting 100 lines should do the trick tail -n 100 /var/www/bookstack/storage/laravel.log. The most relevant lines should start with a datetime for the error, ideally matching when you reproduced the error in the UI.

If you're running tail -f /var/www/bookstack/storage/laravel.log and don't see new lines appear when you cause this specific error, then this may not be a back-end error. Possible that the request is not hitting the server due to the browser console errors you're reporting.

@SysAdminSmith
Copy link
Author

SysAdminSmith commented Sep 28, 2023

If you're running tail -f /var/www/bookstack/storage/laravel.log and don't see new lines appear when you cause this specific error, then this may not be a back-end error. Possible that the request is not hitting the server due to the browser console errors you're reporting.

I suspect your suspicion may be correct. No new laravel entries once the bookstack container restarts:

Details

[stacktrace]
#0 /var/www/bookstack/app/Api/ApiTokenGuard.php(103): BookStack\\Api\\ApiTokenGuard->validateToken()
#1 /var/www/bookstack/app/Api/ApiTokenGuard.php(58): BookStack\\Api\\ApiTokenGuard->getAuthorisedUserFromRequest()
#2 /var/www/bookstack/app/Api/ApiTokenGuard.php(77): BookStack\\Api\\ApiTokenGuard->user()
#3 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Auth/AuthManager.php(340): BookStack\\Api\\ApiTokenGuard->authenticate()
#4 /var/www/bookstack/app/Http/Middleware/ApiAuthenticate.php(46): Illuminate\\Auth\\AuthManager->__call()
#5 /var/www/bookstack/app/Http/Middleware/ApiAuthenticate.php(19): BookStack\\Http\\Middleware\\ApiAuthenticate->ensureAuthorizedBySessionOrToken()
#6 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): BookStack\\Http\\Middleware\\ApiAuthenticate->handle()
#7 /var/www/bookstack/app/Http/Middleware/StartSessionIfCookieExists.php(20): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#8 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): BookStack\\Http\\Middleware\\StartSessionIfCookieExists->handle()
#9 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php(67): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#10 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\\Cookie\\Middleware\\EncryptCookies->handle()
#11 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Routing/Middleware/ThrottleRequests.php(126): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#12 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Routing/Middleware/ThrottleRequests.php(57): Illuminate\\Routing\\Middleware\\ThrottleRequests->handleRequest()
#13 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\\Routing\\Middleware\\ThrottleRequests->handle()
#14 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(116): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#15 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Routing/Router.php(797): Illuminate\\Pipeline\\Pipeline->then()
#16 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Routing/Router.php(776): Illuminate\\Routing\\Router->runRouteWithinStack()
#17 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Routing/Router.php(740): Illuminate\\Routing\\Router->runRoute()
#18 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Routing/Router.php(729): Illuminate\\Routing\\Router->dispatchToRoute()
#19 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(190): Illuminate\\Routing\\Router->dispatch()
#20 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(141): Illuminate\\Foundation\\Http\\Kernel->Illuminate\\Foundation\\Http\\{closure}()
#21 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Http/Middleware/TrustProxies.php(39): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#22 /var/www/bookstack/app/Http/Middleware/TrustProxies.php(41): Illuminate\\Http\\Middleware\\TrustProxies->handle()
#23 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): BookStack\\Http\\Middleware\\TrustProxies->handle()
#24 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#25 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TrimStrings.php(40): Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest->handle()
#26 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\\Foundation\\Http\\Middleware\\TrimStrings->handle()
#27 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ValidatePostSize.php(27): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#28 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\\Foundation\\Http\\Middleware\\ValidatePostSize->handle()
#29 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php(86): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#30 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\\Foundation\\Http\\Middleware\\PreventRequestsDuringMaintenance->handle()
#31 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(116): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#32 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(165): Illuminate\\Pipeline\\Pipeline->then()
#33 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(134): Illuminate\\Foundation\\Http\\Kernel->sendRequestThroughRouter()
#34 /var/www/bookstack/public/index.php(52): Illuminate\\Foundation\\Http\\Kernel->handle()
#35 {main}
"} 

Any ideas where to go next if that is the case?

And, as always, thank you for your time and expertise!

@ssddanbrown
Copy link
Member

Can you got to edit a page, open the browser development console, then paste in the below and hit enter?:

document.querySelector(`[option\\:dropzone\\:url]`).getAttribute('option:dropzone:url')

When confirm if the value it returns starts with a https:// or http:// or if it doesn't match your main APP_URL value.

@SysAdminSmith
Copy link
Author

Can you got to edit a page, open the browser development console, then paste in the below and hit enter?:

document.querySelector(`[option\\:dropzone\\:url]`).getAttribute('option:dropzone:url')

When confirm if the value it returns starts with a https:// or http:// or if it doesn't match your main APP_URL value.

The output: https://bookstack.foo.bar/attachments/upload?uploaded_to=21 which is to be expected (where foo.bar is a substituted for my domain)

When I click the pic upload icon/link:
Mixed Content: The page at 'https://bookstack.foo.bar/books/azure/page/create-the-storage-account/edit' was loaded over HTTPS, but requested an insecure resource 'http://bookstack.foo.bar/images/gallery/?page=1&uploaded_to=21'. This request has been blocked; the content must be served over HTTPS.

@ssddanbrown
Copy link
Member

Does a similar console error/warning appear if you start typing a search in the header search bar (at least 3 characters, without pressing enter)?

@SysAdminSmith
Copy link
Author

SysAdminSmith commented Sep 29, 2023

Does a similar console error/warning appear if you start typing a search in the header search bar (at least 3 characters, without pressing enter)?

Dan:
No, the only errors that appear in the console are those that are referenced above and only when you are a) editing and/or b) attempting to insert a picture.

One critical element I left out (and I apologize, I can't believe it slipped my mind) is that this bookstack instance started clean and then an existing, backup was imported in (we had a hardware failure). Existing articles, books, etc. show the same errors as when dealing with new (ones created post import) however, on the old instance, there were no errors.

@ssddanbrown
Copy link
Member

That shouldn't really affect things to be honest, really unsure why this is occuring just here though.
Your access logs show a an image upload POST resulting in a 301 response, which I really don't understand being possible from a BookStack handling point of view.

  • Again when editing the page, can you go to the console and run document.querySelector('[option\\:dropzone\\:url].image-manager').getAttribute('option:dropzone:url') to confirm if that starts with http or https.
  • Do attachments upload fine?
  • If you add an image, via drag + dropping an image file directly into the editor, does that work?
  • Do you have in play, or have you attempted to set, any additional apache config upon that shown in your original post?
  • Has anything been set on the apache or Cloudlfare side to manipulate URLs (Force or strip slashes for example).

@SysAdminSmith
Copy link
Author

That shouldn't really affect things to be honest, really unsure why this is occuring just here though. Your access logs show a an image upload POST resulting in a 301 response, which I really don't understand being possible from a BookStack handling point of view.

  • Again when editing the page, can you go to the console and run document.querySelector('[option\\:dropzone\\:url].image-manager').getAttribute('option:dropzone:url') to confirm if that starts with http or https.

This is the response with the above command:
'https://bookstack.foo.bar/images/gallery?uploaded_to=21'

  • Do attachments upload fine?

No, they produce the same error

  • If you add an image, via drag + dropping an image file directly into the editor, does that work?

No, it produces a similar error:

app.js?version=v23.08:25 TypeError: Failed to fetch at Go (app.js?version=v23.08:18:1286) at an (app.js?version=v23.08:18:1752) at Object.Gu (app.js?version=v23.08:18:1858) at jf (app.js?version=v23.08:25:32608) at app.js?version=v23.08:25:32980

  • Do you have in play, or have you attempted to set, any additional apache config upon that shown in your original post?

I have not

  • Has anything been set on the apache or Cloudlfare side to manipulate URLs (Force or strip slashes for example).

Nothing that I am aware of outside of using a new tunnel on this new instance (the old tunnel died with the hardware that housed the old bookstack)

@ssddanbrown
Copy link
Member

Coming back to this, there's not much else I can think of to understand why the wrong URL is being attempted here.

The only other thing that might provide some answers, is if you can provide a HAR capture that covers the time from loading up the editor to attempting an image upload. That way I can get a fuller picture of the browser-side of things.

There's details here on how to capture a HAR file in various browsers.
It can contain private information, so probably best not to post here, but you can send it to my email (shown in my Github profile), just reference this issue within the email itself.

@SysAdminSmith
Copy link
Author

Coming back to this, there's not much else I can think of to understand why the wrong URL is being attempted here.

The only other thing that might provide some answers, is if you can provide a HAR capture that covers the time from loading up the editor to attempting an image upload. That way I can get a fuller picture of the browser-side of things.

There's details here on how to capture a HAR file in various browsers. It can contain private information, so probably best not to post here, but you can send it to my email (shown in my Github profile), just reference this issue within the email itself.

Dan:

Ultimately I decided to start from scratch so unfortunately I can't go down this path. Thank you so much for checking back. Even I forgot about it.

@ssddanbrown
Copy link
Member

Okay, no worries, I'll therefore close this off.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

2 participants