Sep 25, 2025

Firebase Storage: A Simple Guide to CORS Configuration

Cross-Origin Resource Sharing (CORS) is a critical part of web development, especially when working with cloud storage solutions like Firebase Storage. This post will walk you through a simple, yet powerful, CORS configuration to get your Firebase Storage bucket talking to your web app.

What's CORS and Why Does It Matter?

CORS is a security feature built into modern web browsers. It's a mechanism that allows a web page to request resources from a different domain than the one that served the web page. Imagine you have your website at `www.mywebsite.com` and you're trying to display an image stored in your Firebase Storage bucket at `my-project.appspot.com`. Without a proper CORS policy, your browser would block the request, seeing it as a potential security risk.

Configuring Your `cors.json`

To configure your CORS policy for a Firebase Storage bucket, you need to create a JSON file. 


[
  {
    "origin": ["*"],
    "method": ["GET", "HEAD", "PUT", "POST", "DELETE"],
    "responseHeader": [
      "Content-Type",
      "Access-Control-Allow-Origin"
    ],
    "maxAgeSeconds": 3600
  }
]

origin: This is the most crucial part. The `*` acts as a wildcard, allowing any domain to access your resources. While convenient for development and public assets, for production, it's best practice to replace `*` with your specific domain, e.g., `["https://www.yourdomain.com"]`, for enhanced security.

method: This specifies the HTTP methods (like `GET`, `POST`, `PUT`, `DELETE`) that are allowed. By including all of them, you're granting full control to your allowed origins. This is helpful if you need to perform actions beyond just fetching data, like uploading or deleting files.

responseHeader: These are the headers that the browser is allowed to access. Content-Type is a standard one, and Access-Control-Allow-Origin is the header that confirms the origin is allowed, which is essential for CORS to work correctly.

maxAgeSeconds: This tells the browser how long it can cache the CORS preflight response for. The value 3600 means one hour, which helps reduce the number of preflight requests for the same resource, making your application a bit faster.

Applying the Policy with gsutil

Once your cors.json file is ready, you need to apply it to your Firebase Storage bucket. You've already done this with the `gsutil` command in the Firebase Studio terminal:


studio-45:~/studio{main}$ gsutil cors set cors.json gs://studio-45-e8723.firebasestorage.app
Setting CORS on gs://studio-45-e8723.firebasestorage.app/...

  * gsutil cors set: This is the command to set a new CORS configuration.

  * cors.json: This is the path to your configuration file.

  * gs://studio-45-e8723.firebasestorage.app: This is the URI for your specific Firebase Storage bucket.

After running this command, your Firebase Storage bucket will now be configured with the CORS policy you defined. This means your web application, running on any origin, can now access the files in your bucket using the specified methods and headers\!


Sep 1, 2025

Connect Firebase Project & Workspace in Firebase Studio

It’s a common setup mistake: you create a Firebase project, then a Firebase Studio workspace but they’re not connected. 

  • A Firebase project in the Firebase Console
  • A Firebase workspace in Firebase Studio


🛠️ The Fix: Link Your Workspace to the Firebase Project

1. Open the Firebase Studio Terminal

In Firebase Studio, navigate to your workspace and open the terminal window. This is where you’ll run CLI commands.

2. Run firebase init

firebase init

This command starts the setup wizard. You’ll be prompted to:

  • Grant access to Google Cloud resources

  • Select a Google Cloud project
    Choose the correct Firebase project from the list — this links your workspace to it.

  • Choose Firebase features
    Continue with terminal window. Pick the services you plan to use (e.g. Firestore, Functions, Hosting).

This step creates two key files in your workspace:

  • .firebaserc — maps your workspace to the selected Firebase project
  • firebase.json — configures Firebase services

3. Verify the Connection

Run:

firebase projects:list

Your selected project should appear with a * next to it, indicating it’s active.


studio-77:~/studio{main}$ firebase projects:list
✔ Preparing the list of your Firebase projects

┌──────────────────────┬──────────────────────────┬────────────────┬──────────────────────┐
│ Project Display Name │ Project ID               │ Project Number │ Resource Location ID │
├──────────────────────┼──────────────────────────┼────────────────┼──────────────────────┤
│ Asset                │ asset-90d38 (current)    │ XXXXXXXXXXXX   │ [Not specified]      │
├──────────────────────┼──────────────────────────┼────────────────┼──────────────────────┤

✅ Result

Your Firebase Studio workspace is now properly connected to your Firebase project. All CLI commands will target the correct environment, and you can deploy, emulate, or manage resources without errors.


🧠 Pro Tip

If you work across multiple Firebase projects, use:

firebase use --add

This lets you assign aliases and switch between them easily:

firebase use dev
firebase use prod

Firebase init output (Web app hosting option)

✔ Please select an option: Use an existing project
✔ Select a default Firebase project for this directory: asset-90d38 (asset)
i  Using project asset-90d38 (asset)

=== App Hosting Setup
i  This command links your local project to Firebase App Hosting. You will be able to deploy your web app with `firebase deploy` after setup.
✔ Please select an option Create a new backend
i  === Set up your backend
✔ Select a primary region to host your backend:
 us-central1
✔  Location set to us-central1.

✔ Provide a name for your backend [1-30 characters] asset-backend
✔  Name set to asset-backend

✔  Created a new Firebase web app named "asset-backend"
✔ Successfully created backend!
        projects/asset-90d38/locations/us-central1/backends/asset-backend

i  === Deploy local source setup
✔ Specify your app''s root directory relative to your firebase.json directory /
✔  Wrote configuration info to firebase.json
i  Writing default settings to apphosting.yaml...
✔ File /home/user/studio/apphosting.yaml already exists. Overwrite? Yes
✔  Wrote /home/user/studio/apphosting.yaml
✔  Firebase initialization complete!

✔  Wrote configuration info to firebase.json
✔  Wrote project information to .firebaserc

✔  Firebase initialization complete!

Sync Firebase Workspace & Project

studio-77:~/studio{main}$ firebase use --add
✔ Which project do you want to add? asset-90d38
✔ What alias do you want to use for this project? (e.g. staging) asset-dev

Created alias asset-dev for asset-90d38.
Now using alias asset-dev (asset-90d38)

studio-77:~/studio{main}$ firebase use asset-dev
Updating Studio Workspace active project to match Firebase CLI 'asset-90d38'
Now using alias asset-dev (asset-90d38)

May 6, 2024

Mar 15, 2024

AI means everyone can now be a programmer(?)

Is it that easy?

Assuming you are not a developer and want to create an app to take screenshots on macOS.

You started to ask questions to AI and installed developer tools. Now you are ready for development.

  1. Gemini
  2. How to take a screenshot on macos xcode using swift?

    You paste the code to XCode and see an error!

    Ask Gemini to provide another solution.
    The code you provided in swift didn't work. Suggest another swift way to capture a screenshot.

    Gemini gives an apology and suggests another solution.

    Let's see in XCode.

    Can you see a strange code that contains Arabic letters?

    guard let contentFilter = SCC محتوى الشاشة(sharingMode: .none) else { return nil }

    You want to switch to ChatGPT to accomplish this easy task with the same prompt. 👇

  3. ChatGPT
  4. You paste the code provided by ChatGPT. Again, there is a problem in the code!

    context.makeCurrent() didn't work. Is there any other way?

    You pasted this code, and it worked! After a few trials, now think you are a programmer.

    What will you do if you see CGDisplayCreateImage(_:) is deprecated?

    So you keep asking for alternative ways, and you learn that there is a shiny framework named ScreenCaptureKit.

    I recommend trying to ask both Gemini and ChatGPT to take a screenshot using ScreenCaptureKit. I tried, on several attempts, AI suggested wrong code each time.

    Then you will decide how easy programming is!

May 17, 2023

How to stream image from generic handler

This article provides an example of streaming images from a generic handler in .NET.

If you store your images in a database table as byte[] then you can utilize a handler to display them in a data grid.

The process involves sending a request to the handler (.ashx) page, retrieving the image, and then displaying it.

In the given example, we have a grid that stores IDs in one column and displays the corresponding images in another column using an asp:ImageField.

Create a generic handler that streams image. In this example ImageField requests image from getFaceImage.ashx by DataImageUrlField parameter in DataImageUrlFormatString format

public void ProcessRequest(HttpContext context)
{
    int id;

    if (context.Request.QueryString["id"] != null)
    {
        id = Convert.ToInt32(context.Request.QueryString["id"]);

        if (id > 0)
        {
            context.Response.ContentType = "image/jpeg";

            Stream strm = new MemoryStream();
            GetImage(id).Save(strm, ImageFormat.Jpeg);
            strm.Position = 0;

            byte[] buffer = new byte[4096];
            int byteSeq = strm.Read(buffer, 0, 4096);
            while (byteSeq > 0)
            {
                context.Response.OutputStream.Write(buffer, 0, byteSeq);
                byteSeq = strm.Read(buffer, 0, 4096);
            }
        }
    }
    else
        return;
}

public Image GetImage(int id)
{
    //Make appropriate calls for image according to id
    //...

    //return the image
    return new Bitmap("");
}

Nov 22, 2022

Gitlab with Visual Studio 2022

Gitlab extension is not available for Visual Studio 2022.

VS Marketplace: GitLab Extension for Visual Studio
You can login any of your favorite GitLab servers and start your great job!
The GitLab Extension for Visual Studio provides GitLab integration in Visual Studio 2015/2017/2019.

In VS 2022, I created a new project and added to local git on user interface.

I also created an empty project on gitlab with the same name.

In gitlab project homepage it helps you what to do.


  cd existing_repo

  git remote add origin https://gitlab.com/git_username/project.git

  git branch -M main

  git push -uf origin main

I switched to command line and run commands above.

When you push the project to remote repository git shows a window for authentication.

I selected browser login and git command got credentials from browser.


C:\project>git push -uf origin main
info: please complete authentication in your browser...
Enumerating objects: 1718, done.
Counting objects: 100% (1718/1718), done.
Delta compression using up to 4 threads
Compressing objects: 100% (1688/1688), done.
Writing objects: 100% (1718/1718), 35.76 MiB | 540.00 KiB/s, done.
Total 1718 (delta 470), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (470/470), done.
remote: GitLab: You are not allowed to force push code to a protected branch on this project.
To https://gitlab.com/git_username/project.git
 ! [remote rejected] main -> main (pre-receive hook declined)
error: failed to push some refs to 'https://gitlab.com/git_username/project.git'

The problem was VS created a branch named master, but in gitlab branch name was main.

I created a new branch named master on gitlab.

In command line switch to branch named master and push project to master.

C:\projectO>git branch -M master

C:\project>git push -uf origin master
Enumerating objects: 1718, done.
Counting objects: 100% (1718/1718), done.
Delta compression using up to 4 threads
Compressing objects: 100% (1688/1688), done.
Writing objects: 100% (1718/1718), 35.76 MiB | 561.00 KiB/s, done.
Total 1718 (delta 470), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (470/470), done.
remote:
remote: To create a merge request for master, visit:
remote:   https://gitlab.com/git_username/project/-/merge_requests/new?merge_request%5Bsource_branch%5D=master
remote:
To https://gitlab.com/git_username/project.git

You can create a merge request in gitlab to push master branch into main.

Oct 9, 2021

Windows 10 window border change

Problem

Losing title bar when multiple windows overlap, finding drag position becomes harder.

Solution

>Windows > Settings > Colors
Select "Title bars and windows borders".

Windows Activation Issue

If Windows is not activated you can not change color settings.
We can enable window borders by regedit commands.

reg add "HKEY_CURRENT_USER\Software\Microsoft\Windows\DWM" /v "ColorPrevalence" /t REG_DWORD /d "1" /f

reg add "HKEY_CURRENT_USER\Software\Microsoft\Windows\DWM" /v "AccentColor" /t REG_DWORD /d "7439985" /f

reg add "HKEY_CURRENT_USER\Software\Microsoft\Windows\DWM" /v "AccentColorInactive" /t REG_DWORD /d "13882323" /f

May 8, 2021

[Tips] Random string generators C#

Testing 2 different Random string generators.

void Main()
{
 for(int i=0;i<10;i++){
  Console.WriteLine("GetRandomString: " + GetRandomString(8));
 }
 for(int i=0;i<10;i++){
  Console.WriteLine("GetRandomFileName: " + GetRandomFileName());
 } 
}

public static string GetRandomString(int length)
{
    Random random = new Random();
    const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    return new string(Enumerable.Repeat(chars, length)
      .Select(s => s[random.Next(s.Length)]).ToArray());
}

public static string GetRandomFileName()
{
    string path = Path.GetRandomFileName();
    path = path.Replace(".", ""); // Remove period.
    return path;
}

Result
GetRandomString: tpZIDi0C
GetRandomString: tpZIDi0C
GetRandomString: tpZIDi0C
GetRandomString: tpZIDi0C
GetRandomString: tpZIDi0C
GetRandomString: tpZIDi0C
GetRandomString: tpZIDi0C
GetRandomString: tpZIDi0C
GetRandomString: tpZIDi0C
GetRandomString: tpZIDi0C
GetRandomFileName: smb1u03pvyf
GetRandomFileName: 2ccre5kihis
GetRandomFileName: 24thz5is1pj
GetRandomFileName: ni0z42lexag
GetRandomFileName: 1u11tcvd3qv
GetRandomFileName: vtiqp2sevwy
GetRandomFileName: y2jhumy1hcx
GetRandomFileName: 5o0gsyronpk
GetRandomFileName: m0zva3mhdfn
GetRandomFileName: 2a2dzcdkpbl

Apr 4, 2020

Failed to install Intel HAXM

When installing Android SDK Platform-Tools on Windows you may see following error:

Running Intel® HAXM installer Failed to install Intel HAXM. 
For details, please check the installation log: HAXM installation failed. To install HAXM follow the instructions found at:
https://software.intel.com/android/articles/installation-instructions-for-intel-hardware-accelerated-execution-manager-windows
This computer does not support Intel Virtualization Technology (VT-x)
or it is being exclusively used by Hyper-V.
HAXM cannot be installed. Please ensure Hyper-V is disabled in Windows Features,
or refer to the Intel HAXM documentation for more information.
I will list 3 different options.

1. Program and Features

Be sure Hyper-V not marked. If installed uncheck it.

2. Command line (CMD)

dism.exe /Online /Disable-Feature:Microsoft-Hyper-V
or
bcdedit /set hypervisorlaunchtype off

3. Device Guard and Credential Guard hardware readiness tool

Download tool, unzip and open powershell window.

First change execution policy.
PS C:\temp\dgreadiness_v3.6> set-executionpolicy remotesigned 
Execution Policy Change The execution policy helps protect you from scripts that you do not trust.
Changing the execution policy might expose you to the security risks described in the about_Execution_Policies help topic at https:/go.microsoft.com/fwlink/?LinkID=135170.
Do you want to change the execution policy? [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "N"): a
Run command.
PS C:\temp\dgreadiness_v3.6> .\DG_Readiness_Tool_v3.6.ps1 -Disable 
Do you want to run software from this untrusted publisher?
File C:\temp\dgreadiness_v3.6\DG_Readiness_Tool_v3.6.ps1 is published by CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US and is not trusted on your system. Only run scripts from trusted publishers.
[V] Never run [D] Do not run [R] Run once [A] Always run [?] Help (default is "D"): a
You will see success messages.
Disabling Hyper-V and IOMMU
Disabling Hyper-V and IOMMU successful
Please reboot the machine, for settings to be applied.
After reboot continue to install HAXM.

Mar 16, 2020

Dynamic Assembly Loading (C# Reflection)

We will achieve following task with dynamic assembly loading in C#.

using System.Net.Http;
using System;
using System.Linq;

var client = new HttpClient();
client.BaseAddress = new Uri("http://api.open-notify.org/astros.json");
string result = client.GetStringAsync("").Result;


Don't add System.Net.Http dll to your reference list. It will be automatically loaded from GAC.

using System;
using System.Linq;
using System.Reflection;

//We don't have "using System.Net.Http" 

//Load System.Net.Http
string name1 = "System.Net.Http,Version=4.0.0.0," + "Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a";
Assembly a1 = Assembly.Load(name1);

//Create HttpClient instance
Type clientType = a1.GetTypes().Where(t => t.Name.Equals("HttpClient")).Single();
object client = Activator.CreateInstance(clientType);

//Set BaseAddress on client
PropertyInfo propertyBaseAddress = clientType.GetProperties().Where(p => p.Name == "BaseAddress").Single();
Uri url = new Uri("http://api.open-notify.org/astros.json");
propertyBaseAddress.SetValue(client, url);

//Test property value
var BaseAddressValue = propertyBaseAddress.GetValue(client);

//Get HttpResponseMessage Task
var methodGetStringAsync = clientType.GetMethod("GetStringAsync", new Type[] { typeof(Uri) });
var responseTask = methodGetStringAsync.Invoke(client, new string[] { null });

//Get HttpResponseMessage result from Task
var responseType = responseTask.GetType();
PropertyInfo propResponse = responseType.GetProperties().Where(p => p.Name == "Result").Single();

var responseResult = propResponse.GetValue(responseTask);  //This is the string result


Bonus: List your loaded assemblies

Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();

foreach (Assembly a in assemblies)
{
     Console.WriteLine(a.GetName());
}


Output
mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Net.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System.Net.Http is displayed here even not referenced in Visual Studio.