### Description

When a file is uploaded to GCS, [by default](https://cloud.google.com/storage/docs/metadata#cache-control), public files will get `Cache-Control: public, max-age=3600`.

I've tried setting `cors` for the whole bucket (didn't work) and setting `Cache-Control` on individual file (disappears on file re-upload from airflow)

Setting `metadata` for GCSHook is for different field (can't be used to set cache-control)

### Use case/motivation

Allow GCSHook to set cache control rather than overriding the `upload` function

### Related issues

_No response_

### Are you willing to submit a PR?

- [X] Yes I am willing to submit a PR!

### Code of Conduct

- [X] I agree to follow this project's [Code of Conduct](https://github.com/apache/airflow/blob/main/CODE_OF_CONDUCT.md)

destination_object_prefix_len = len(destination_object) if destination_object else 0
        delimiter = "/" if not recursive else None
        
        source_blobs = list(source_bucket.list_blobs(prefix=source_object, delimiter=delimiter))
        destination_blobs = list(
            destination_bucket.list_blobs(prefix=destination_object, delimiter=delimiter)
        )
        
        source_names_index = {a.name[source_object_prefix_len:]: a for a in source_blobs}
        destination_names_index = {a.name[destination_object_prefix_len:]: a for a in destination_blobs}
        
        source_names = set(source_names_index.keys())
        destination_names = set(destination_names_index.keys())
        
        to_copy = source_names - destination_names
        to_delete = destination_names - source_names
        to_copy_blobs: set[storage.Blob] = {source_names_index[a] for a in to_copy}
        to_delete_blobs: set[storage.Blob] = {destination_names_index[a] for a in to_delete}
        
        names_to_check = source_names.intersection(destination_names)
        to_rewrite_blobs: set[storage.Blob] = set()
        
        for current_name in names_to_check:
            source_blob = source_names_index[current_name]
            destination_blob = destination_names_index[current_name]
            
            if source_blob.crc32c != destination_blob.crc32c:
                to_rewrite_blobs.add(source_blob)
        return to_copy_blobs, to_delete_blobs, to_rewrite_blobs
def gcs_object_is_directory(bucket: str) -> bool: