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
Proxy image gets #1686
Proxy image gets #1686
Conversation
Your preview environment pr-1686-bttf has been deployed. Preview environment endpoints are available at: |
@@ -50,6 +50,7 @@ const Carousel: FC<{ | |||
open={true} | |||
header={"Screenshot"} | |||
close={() => setModalOpen(false)} | |||
bodyClassName="d-flex justify-content-center align-items-center" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This aligns the loading spinner in the middle of the variation area.
@@ -28,7 +28,7 @@ const ScreenshotUpload = ({ | |||
const [loading, setLoading] = useState(0); | |||
|
|||
const onDrop = async (files: File[]) => { | |||
setLoading(loading + files.length); | |||
setLoading((previous) => previous + files.length); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This and the ones blow fixed a pre-existing bug where we were only showing the loading spinner on put on the first image upload, but not subsequent ones.
import styles from "./Markdown.module.scss"; | ||
|
||
const md = markdown({ html: true, linkify: true }).use(sanitizer).use(mark); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changing the renderer is a pretty big change. How thoroughly did you test this with different markdown text? Does it turn URLs into links automatically? Does it sanitize html like the previous one did? Does it use the same custom CSS styles we configured to make the output match the rest of the app styles?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How thoroughly did you test this with different markdown text?
I tested on: https://markdown-it.github.io/. The only thing the new one doesn't render that the old one did is==mark==
as<mark>
Does it turn URLs into links automatically?
yes
Does it sanitize html like the previous one did?
Neither the old one nor this one renders html. The html is escaped.
Does it use the same custom CSS styles we configured to make the output match the rest of the app styles?
yes we surround theReactMarkdown
with<div {...props} className={clsx(className, styles.markdown)}>
which is what the markdown was wrapped with before. So it should all look the same as before. I didn't notice any differences.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IDK if it's worth doing at this point (up to you) but it might be worth separating this distinct change (updating our markdown renderer) in a separate PR that can be deployed/tested and potentially rolled back easily if we need to.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we store the same thing in the database now, we should be able to revert the whole changeset without a problem, as long as no one locked down their bucket in the meantime.
Deploy preview for docs ready! ✅ Preview Built with commit 3418d79. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- We may want to start limiting the size of images we accept in
putUpload
- Have we considered leveraging browser-based caching (
Cache-Control
header)? Is security a blocker? - The github issue mentions using pre-signed URLs for fetching images. This was my first thought at an approach as well... Have we considered this? It does come at a cost to security but it can be minimized. And it would allow for a more lightweight implementation.
|
@@ -71,3 +71,43 @@ export async function uploadFile( | |||
} | |||
return fileURL; | |||
} | |||
|
|||
export async function getImageData(filePath: string) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this needs to be async
import styles from "./Markdown.module.scss"; | ||
|
||
const md = markdown({ html: true, linkify: true }).use(sanitizer).use(mark); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IDK if it's worth doing at this point (up to you) but it might be worth separating this distinct change (updating our markdown renderer) in a separate PR that can be deployed/tested and potentially rolled back easily if we need to.
} else if ( | ||
usingFileProxy() && | ||
getGcsDomain() && | ||
src.startsWith(getGcsDomain()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For this (and for the similar s3 check below) I'm having trouble understanding when the src
property will be set to an S3 url and not a GB host. When the user uploads a screenshot, would we not update the variation with the GB proxy URL? Is this meant for existing customers to accomplish a backfill?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We had gone back and forth on this a bit, but if you look in files.ts now you will see that we store the GCS location where it is actually stored on the mongo model and not the Growthbook proxy. Only when usingFileProxy() is true will we then use the proxy and rewrite it to be a GB url. This will hence behave the same for both old and new urls and they can go ahead and lock their buckets down.
@@ -7,6 +7,9 @@ import { useAuth } from "@/services/auth"; | |||
import { trafficSplitPercentages } from "@/services/utils"; | |||
import Carousel from "../Carousel"; | |||
import ScreenshotUpload from "../EditExperiment/ScreenshotUpload"; | |||
import AuthorizedImage from "../AuthorizedImage"; | |||
|
|||
const imageCache = {}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This might be better suited to be defined by a useState variable, and reset when variation.id
changes
const [imageCache, setImageCache] = useState({});
useEffect(() => {
setImageCache({});
}, [variation.id]);
// you can still set imageCache as it's currently done
imageCache[src] = blob;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doing that would make the cache disappear as they navigate to other pages and come back. Keeping it as is makes the cache last longer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for reviewing again @bttf. I have removed the async's and responded to your other comments. I noticed that react was sometimes call useEffect multiple times before the api call could finish running, so now I put it in a lock so that it only fetches it from the proxy once.
} else if ( | ||
usingFileProxy() && | ||
getGcsDomain() && | ||
src.startsWith(getGcsDomain()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We had gone back and forth on this a bit, but if you look in files.ts now you will see that we store the GCS location where it is actually stored on the mongo model and not the Growthbook proxy. Only when usingFileProxy() is true will we then use the proxy and rewrite it to be a GB url. This will hence behave the same for both old and new urls and they can go ahead and lock their buckets down.
@@ -7,6 +7,9 @@ import { useAuth } from "@/services/auth"; | |||
import { trafficSplitPercentages } from "@/services/utils"; | |||
import Carousel from "../Carousel"; | |||
import ScreenshotUpload from "../EditExperiment/ScreenshotUpload"; | |||
import AuthorizedImage from "../AuthorizedImage"; | |||
|
|||
const imageCache = {}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doing that would make the cache disappear as they navigate to other pages and come back. Keeping it as is makes the cache last longer.
import styles from "./Markdown.module.scss"; | ||
|
||
const md = markdown({ html: true, linkify: true }).use(sanitizer).use(mark); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we store the same thing in the database now, we should be able to revert the whole changeset without a problem, as long as no one locked down their bucket in the meantime.
3c17589
to
3418d79
Compare
Features and Changes
Before this change for files stored on s3 and google-cloud we were creating a link that required the buckets to be open to the public.
A few notes on the implementation:
Closes: #857
Testing
For each of the three UPLOAD_METHOD's:
For markdown testing: