In today's interconnected world, websites need to constantly interact with web servers. To ensure the security of these servers, web browsers have implemented stringent measures regarding how websites can load content from sources other than their web servers. One mechanism that enables websites to load resources is Cross-Origin Resource Sharing (CORS).
In this article, we will explore how to enable CORS between JavaScript and Golang, enabling you to develop web applications that can effortlessly communicate across different origins. We'll delve into the basics of CORS, and its significance in web security, and provide you with step-by-step instructions on implementing CORS support in both JavaScript and Golang.
### What is CORS and Why it is important
**Cross-Origin Resource Sharing** ([CORS](https://developer.mozilla.org/en-US/docs/Glossary/CORS)) is an [HTTP-header-based](https://developer.mozilla.org/en-US/docs/Glossary/HTTP) mechanism that allows web servers to indicate any [origins](https://developer.mozilla.org/en-US/docs/Glossary/Origin) such as domain, scheme, or ports other than its own. In simple words, CORS allows or disallows a website to load content from web servers that are not its own. [1]
The reason why CORS are so important is that browsers have a 'same origin policy' that restricts how a document or script loaded by one [origin](https://developer.mozilla.org/en-US/docs/Glossary/Origin) can interact with a resource from another origin.This policy ensures that browsers only load resources from their specified origins, preventing fraudulent websites from accessing resources belonging to legitimate websites.[2]
Let's understand it by an example. When comparing origins such as [https://www.stackhawk.com:443](https://www.stackhawk.com/) and [https://www.stackhawk.com](https://www.stackhawk.com/), they are considered the same due to having matching protocols, hosts, and ports (where port 443 is the default for HTTPS). But on the other hand, these two origins - [https://stackhawk.com](https://stackhawk.com/) and [http://stackhawk.com](http://stackhawk.com/) are regarded as different since they have differing protocols(https and http). [3]
### How to allow CORS in Golang Server
To demonstrate how to allow CORS in a Golang server, we will create a simple HTTP server in Golang that serves a list of articles as JSON data.
If you prefer not to write the script from scratch, you can easily clone it from the GitHub repository [here](https://github.com/carlosschults/sample-go-app). Make sure to make changes to the main.go file by following the explanation below to allow CORS.
Before proceeding, please ensure Go is installed on your system.
To begin, open a text editor of your choice where you'll be writing the Golang script. Then, follow the steps outlined below:
1. Start by importing the necessary packages. The encoding/json package is used to encode the articles into JSON format, and the net/http package is used to handle HTTP requests and responses. [4] [5]
```go
package main
import (
"encoding/json"
"net/http"
)
```
2. Here, a struct named `Article` is defined with four fields: `Id`, `Title`, `Desc`, and `Content`. This struct represents the structure of an article.
```go
type Article struct {
Id string
Title string
Desc string
Content string
}
```
3. A slice named `Articles` is declared to hold a collection of `Article` instances.
```go
var Articles []Article
```
4. In the `main` function, a couple of sample articles are added to the `Articles` slice. Then, the code sets up a route using `http.HandleFunc` to handle requests made to the "/articles" endpoint. The handler function `foo` is registered to handle those requests. Finally, `http.ListenAndServe` is called to start the server on port 8002.
```go
func main() {
Articles = []Article{
{Id: "1", Title: "First article", Desc: "Title of this fine article", Content: "Content for this fine article"},
{Id: "2", Title: "Second article", Desc: "Title of this majestic article", Content: "Content for this majestic article"},
}
http.HandleFunc("/articles", foo)
http.ListenAndServe(":8002", nil)
}
```
5. The `foo` function is the handler function for the "/articles" endpoint. It first calls the `enableCors` function to enable Cross-Origin Resource Sharing (CORS) by setting the appropriate header. Then, it uses `json.Marshal` to convert the `Articles` slice into JSON format.
If any error occurs during the marshaling process, an HTTP error response is sent. Otherwise, the response header is set to indicate that the response contains JSON data, and the JSON data is written to the response body.
```go
func foo(w http.ResponseWriter, r *http.Request) {
enableCors(&w)
js, err := json.Marshal(Articles)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
w.Write(js)
}
```
6. The `enableCors` function sets the "Access-Control-Allow-Origin" header on the response to allow requests from any origin by setting its value to "*". This is a basic way to enable CORS for all origins. It takes a pointer to the `http.ResponseWriter` as a parameter and uses the dereference operator `*` to access the actual response writer and modify its header.
```go
func enableCors(w *http.ResponseWriter) {
(*w).Header().Set("Access-Control-Allow-Origin", "*")
}
```
Note: Using the dereference operation opens the port universally, which makes it unsafe because now any website can load contents from this web server. To avoid it, you can set the `Access-Control-Allow-Origin` to a specific port or to a specific URL. [6]
For example:
```go
(*w).Header().Set("Access-Control-Allow-Origin", "http://localhost:3000")`
```
The above codes set up a Golang HTTP server that responds to requests made to the "/articles" and also enables CORS to allow requests from any origin.
Now all is left is to build the application and run the HTTP server. Follow these steps to build the application and run the server on a localhost:
1. Save the text document where the Golang script is written with the filename - 'main'. We will be building this `main.go` file.
2. Open a Command Line Interpreter like cmd or PowerShell. When inside the command prompt, navigate to the directory where you have stored the `main.go` file.
Executing the following commands will build the application and run it:
```text
C:\> cd sample-go-app
C:\sample-go-app> go build main.go
C:\sample-go-app> go run main.go
```
Once the aforementioned commands are executed successfully, a page will be launched on the local host. It is important to note that you should not close the tab or command prompt, as this will keep the server process running in the background. The server is hosted at `http://localhost:8002/articles`, where you can visit to check the contents of the server. The contents will be displayed in the following format:
```text
[{"Id":"1","Title":"First article","Desc":"Title of this fine article","Content":"Content for this fine article"},
{"Id":"2","Title":"Second article","Desc":"Title of this majestic article","Content":"Content for this majestic article"}]
```
### Create a JavaScript Client that loads resources from the Golang Server Using CORS
Once we have created the HTTP server, our next step is to build a client that interacts with the Golang server. To do this, you'll need to [clone another GitHub repository containing a React client](https://github.com/carlosschults/cors-sample). This client is designed to read the JSON data returned from the Golang server and display the array of objects (in this case, texts) on the screen.
Please note that you must have Node.js and npm installed on your system before proceeding further.
To build the React client, follow the same approach as we did with the Golang server. Start by making some changes to the `package.json` file in the directory of the React client. Open the `package.json` file and replace the existing `scripts` section with the following:
```json
"scripts": {
"start": "node node_modules/react-scripts/bin/react-scripts start",
"build": "node node_modules/react-scripts/bin/react-scripts build",
"test": "node node_modules/react-scripts/bin/react-scripts test",
"eject": "node node_modules/react-scripts/bin/react-scripts eject"
},
```
Once you have made the necessary changes, save the file and close it. This ensures that the client will find the react-scripts at the path specified. With this done, we can now proceed to build the client.
To build the client, navigate to the parent directory where the React client is stored using the command prompt. Then, execute the following commands:
```
C:\> cd cors-sample-main
C:\cors-sample-main> npm install react-scripts --save
C:\cors-sample-main> npm start
```
npm install react-scripts --save: The above command installs the react-scripts package and saves it as a dependency in the package.json file. The react-scripts package is a set of scripts and configurations used to build and run React applications. By installing this package, we ensure that the necessary scripts are available for building and running the React client.
npm start: This command starts the development server for the React client. It compiles the React code and launches the application in a web browser, allowing you to view and interact with the client-side application.
If you have followed all the previous steps accordingly, the React client will be hosted on the port http://localhost:3000/. When you access this URL in your web browser, you will be able to see the contents of the Golang server, which is hosted on a different port. The displayed contents will appear as follows:
```text
1 - First article
2 - Second article
```
You have now made a Golang server, allowed CORS and interacted with it through a React client.
### Conclusion
This article explains how you can allow CORS with JavaScript and Golang. The one-origin policy makes it difficult for malicious websites to steal content from legitimate ones. But on the same hand, it also makes it difficult for legitimate websites to share their resources. Enabling CORS solves all these problems, by allowing only those websites that have correctly indicated their origin to the webserver.
We tried to provide you with step-by-step guidance on enabling CORS between JavaScript and Golang, empowering developers to build web applications that can securely interact across origins. We also have covered the process of creating a basic Golang HTTP server, cloning a React client from a GitHub repository, and configuring it to interact with the Golang server.
Overall, by understanding and implementing CORS effectively, developers can ensure secure communication and data exchange between web servers and browsers, facilitating the development of robust and reliable web applications.
References
[1]https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
[2]https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy
[3]https://www.stackhawk.com/blog/golang-cors-guide-what-it-is-and-how-to-enable-it/
[4]https://pkg.go.dev/net/http
[5]https://pkg.go.dev/encoding/json
[6]https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin