-
-
Notifications
You must be signed in to change notification settings - Fork 10.6k
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
🐛 Fix invalid image URLs not being cached and causing timeouts #8986
🐛 Fix invalid image URLs not being cached and causing timeouts #8986
Conversation
74220cd
to
7e6e944
Compare
@ErisDS one question I have on my mind is the handling of the different errors in |
686706f
to
77c2a1f
Compare
core/server/utils/image-size.js
Outdated
message: err.message, | ||
code: 'IMAGE_SIZE', | ||
err: err, | ||
context: { |
This comment was marked as abuse.
This comment was marked as abuse.
Sorry, something went wrong.
This comment was marked as abuse.
This comment was marked as abuse.
Sorry, something went wrong.
There seems to be still some issues with the errors returned from the So here's what's happening: Any filtered catch (e. g. |
We don't do anything with not found errors because they are an expected case. Images will 404 over time. We don't want to fill up the logs, nothing went wrong :)
This is expected behaviour as far as I know. If you catch an error in a predicate and then re-throw (reject) it, it will next get caught by the catch all. The way to deal with this is to check in the catch-all for any errors which are not already GhostErrors. If not, wrap them, else, just reject again. |
I am sorry, I expressed myself wrong :( I was referring to logging the errors. My concern was only, that also timeout errors might now increase (because of the ability to follow redirects and they actually take a bit longer and might hit the timeout) and will therefore be logged. My question was, if we want them to be logged as well? |
@AileenCGN sounds like you might be onto something - my advice would be to experiment with what feels right. |
@ErisDS This PR is ready for review and merge 🎉 |
core/server/utils/image-size.js
Outdated
@@ -143,6 +143,9 @@ getImageSizeFromUrl = function getImageSizeFromUrl(imagePath) { | |||
context: err.url || imagePath | |||
})); | |||
}).catch(function (err) { | |||
if (err instanceof errors.NotFoundError || err instanceof errors.InternalServerError) { |
This comment was marked as abuse.
This comment was marked as abuse.
Sorry, something went wrong.
This comment was marked as abuse.
This comment was marked as abuse.
Sorry, something went wrong.
core/server/utils/image-size.js
Outdated
@@ -199,6 +202,9 @@ getImageSizeFromFilePath = function getImageSizeFromFilePath(imagePath) { | |||
} | |||
})); | |||
}).catch(function (err) { | |||
if (err instanceof errors.NotFoundError || err instanceof errors.InternalServerError) { |
This comment was marked as abuse.
This comment was marked as abuse.
Sorry, something went wrong.
Just checking: as a result of these changes, what now happens in the original error case I had with the old-nonsubdirectory local path? |
This case will result in an The cache issue is resolved as well, so a second request results in reading from the cache. |
Awesome 👍 There are a couple of minor amends needed. Will review again first thing in the am :) |
1a01fc0
to
1fa3dbe
Compare
Summary of cases I successfully tested:
Of course I tested positive cases as well ;) |
refs TryGhost#8868 - swapped the usage of `got` for requests with the request util
refs TryGhost#8868 - Uses catch predicates instead of conditionals in `getImageSizeFromUrl` - Return `NotFoundError` if applicable in `getImageSizeFromFilePath` as the caller function `cachedImageSizeFromUrl` is differentiating those between this error and others.
- Using `ImageObject` as a global var resulted in having the `url` property being the same for all requests coming in. - The logic that checked for an existing protocol (e. g. gravatar URLs) was overly complicated. Refactored it to be more simple. - Passing the correct value to `fetchDimensionsFromBuffer` as the population of `imageObject.url` happens there. These are used in our structured data and need to be full URLs (in case of locally stored files) or the original URL (in case of URLs missing the protocol) - Added two more debug logs in `getCachedImageSizeFromUrl` so it's logged when an image is added to the cache even tho it was returned as error.
We're always resolving the result in `getCachedImageSizeFromUrl`, so there's no need to return the values with a `Promise.resolve()`. The caller fn uses waits for the Promises to be fulfilled.
closes TryGhost/Support#361 - adds a guard that checks the image URL for `/assets/` in the beginning and passes a completed URL to the request util to try and fetch the image size - adds tests
1fa3dbe
to
f7afb8b
Compare
@ErisDS fyi I left commits separate to make the review easier, but they should totally be squashed when being merged. |
closes #8589, refs #8868 This PR ports most of the changes of #8892 and #8986 to improve the image-size util. - Swapped `request` with `got` in `getImageSizeFromUrl` fn. - wrapped `got` request library in its own `request.js` util that returns bluebird promises and validates URL before starting a request - Used catch predicates instead of conditionals in `getImageSizeFromUrl` - Returned `NotFoundError` if applicable as the caller function `cachedImageSizeFromUrl` is differentiating those between this error and others. - The logic that checked for an existing protocol (e. g. gravatar URLs) was overly complicated. Refactored it to be more simple. - We're always resolving the result in `getCachedImageSizeFromUrl`, so there's no need to return the values with a `Promise.resolve()`. The caller fn uses waits for the Promises to be fulfilled. - added and improved tests
refs #8868
got
for requests with the request util, which validates a URL before doing a request and resolving the Promises in image-size so it gets saved in the image-size cache.getImageSizeFromUrl
NotFoundError
if applicable ingetImageSizeFromFilePath
as the caller functioncachedImageSizeFromUrl
is differentiating those between this error and others.ImageObject
as a global var resulted in having theurl
property being the same for all requests coming in.fetchDimensionsFromBuffer
as the population ofimageObject.url
happens there. These are used in our structured data and need to be full URLs (in case of locally stored files) or the original URL (in case of URLs missing the protocol)getCachedImageSizeFromUrl
so it's logged when an image is added to the cache even tho it was returned as error.getCachedImageSizeFromUrl
, so there's no need to return the values with aPromise.resolve()
. The caller fn uses waits for the Promises to be fulfilled.Todos:
Promise.resolve()
in cached image sizeNotFoundError
handling to storage.read request, as the calling fncachedImageSizeFromUrl
is differentiating those errorsimageObject
interferes with image size cache