Skip to content

Commit

Permalink
First commit
Browse files Browse the repository at this point in the history
  • Loading branch information
ghivert committed Apr 23, 2024
0 parents commit 4cb35ba
Show file tree
Hide file tree
Showing 22 changed files with 722 additions and 0 deletions.
23 changes: 23 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: test

on:
push:
branches:
- master
- main
pull_request:

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: erlef/setup-beam@v1
with:
otp-version: "26.0.2"
gleam-version: "1.1.0"
rebar3-version: "3"
# elixir-version: "1.15.4"
- run: gleam deps download
- run: gleam test
- run: gleam format --check src test
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
*.beam
*.ez
/build
erl_crash.dump
1 change: 1 addition & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{ "printWidth": 80, "proseWrap": "always" }
108 changes: 108 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# cors

## Middlewares

```gleam
import gleam/http
import mist
import simple_cors as cors
import wisp.{type Request, type Response}
fn cors() {
cors.new()
|> cors.allow_origin("http://localhost:3000")
|> cors.allow_origin("http://localhost:4000")
|> cors.allow_method(http.Get)
|> cors.allow_method(http.Post)
}
fn handler(req: Request) -> Response {
use req <- cors.wisp_handle(req, cors())
wisp.ok()
}
fn main() {
handler
|> wisp.mist_handler(secret_key)
|> mist.new()
|> mist.port(3000)
|> mist.start_http()
}
```

## What is CORS?

Browsers apply a simple rules for every HTTP request: when the request
originates from a different origin than the target server URL — and if it's not
a simple request — the browser needs to authorize the cross-origin call.

> From the HTTP point of view, a simple request respects the following
> conditions:
>
> - Allowed methods are `GET`, `HEAD` or `POST`
> - Allowed headers are `Accept`, `Accept-Language`, `Content-Language` and
> `Content-Type`
> - `Content-Type` should be:
> - `application/x-www-form-urlencoded`
> - `multipart/form-data`
> - `text/plain`
> - No event listener has been added on `XMLHttpRequestUpload`.
> `XMLHttpRequestUpload.upload` is preferred.
> - No `ReadableStream` is used in the request.
To authorize the call, the browser will issue a first request, called a
"preflight" request. This request takes the form of an `OPTIONS` request, which
should be answered positively by the server (meaning the response status code
should be 2XX) and should contains the appropriate CORS headers
(`Access-Control` headers).

In case the preflight request is not successful, the server will simply cancel
the HTTP request. But if the preflight request is successful, then the browser
will then launch the real request, and the server will be able to handle it.

## What are the headers?

We distinguish different types of headers: the headers concerning the request
issuer (the caller) and the headers responded by the server.

### Response headers

Response headers are not automatically set by the server, and you should handle
them according on what you want to do. This package tries to abstract it to
simplify your development and let you focus on your application. We count 6 CORS
response headers:

- `Access-Control-Allow-Origin`, indicates which origins are allowed to access
the server. It can be a joker (`"*"`) or a unique domain
(`https://gleam.run`). It cannot contains multiple domains, but can response
to multiple different domains with the `VARY` header. You should not have to
take care of this, because the library provides it for you.
- `Access-Control-Expose-Headers`, provides a whitelist of allowed headers for
the browsers. Only the headers in the whitelist will be able to be used in the
response object in the JS code. It means if the response contains headers you
want to cache to the client, you can use this header.
- `Access-Control-Max-Age`, allows to put the preflight response in cache, for a
specified amount of time. This avoids to rerun the `OPTIONS` request multiple
times.
- `Access-Control-Allow-Credentials`, allows the request to includes credentials
authorizations. This can expose you to CSRF attack. Never activate this option
unless you carefully know what you're doing.
- `Access-Control-Allow-Methods`, provides a whitelist of subsequent authorized
methods in the future requests.
- `Access-Control-Allow-Headers`, indicates which headers are accepted by the
server, and thus, which headers the browser will be able to send in subsequent
requests.

### Request headers

Request headers are headers automatically set by the browser, when issuing a
request with `XMLHttpRequest` or `fetch`. You should not bother about it, but
they're still referenced it, in case you encounter them.We count 3 CORS request
headers:

- `Origin` contains the origin of the request. The browser will _always_ fill
this header automatically.
- `Access-Control-Request-Method` contains the desired methods to use when
talking with the server.
- `Access-Control-Request-Header` contains the desired headers that the request
want to have.
23 changes: 23 additions & 0 deletions e2e/mist_test/.github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: test

on:
push:
branches:
- master
- main
pull_request:

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: erlef/setup-beam@v1
with:
otp-version: "26.0.2"
gleam-version: "1.1.0"
rebar3-version: "3"
# elixir-version: "1.15.4"
- run: gleam deps download
- run: gleam test
- run: gleam format --check src test
4 changes: 4 additions & 0 deletions e2e/mist_test/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
*.beam
*.ez
/build
erl_crash.dump
25 changes: 25 additions & 0 deletions e2e/mist_test/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# mist_test

[![Package Version](https://img.shields.io/hexpm/v/mist_test)](https://hex.pm/packages/mist_test)
[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/mist_test/)

```sh
gleam add mist_test
```
```gleam
import mist_test
pub fn main() {
// TODO: An example of the project in use
}
```

Further documentation can be found at <https://hexdocs.pm/mist_test>.

## Development

```sh
gleam run # Run the project
gleam test # Run the tests
gleam shell # Run an Erlang shell
```
23 changes: 23 additions & 0 deletions e2e/mist_test/gleam.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name = "mist_test"
version = "1.0.0"

# Fill out these fields if you intend to generate HTML documentation or publish
# your project to the Hex package manager.
#
# description = ""
# licences = ["Apache-2.0"]
# repository = { type = "github", user = "username", repo = "project" }
# links = [{ title = "Website", href = "https://gleam.run" }]
#
# For a full reference of all the available options, you can have a look at
# https://gleam.run/writing-gleam/gleam-toml/.

[dependencies]
gleam_http = ">= 3.6.0 and < 4.0.0"
gleam_stdlib = ">= 0.34.0 and < 2.0.0"
mist = ">= 1.0.0 and < 2.0.0"
simple_cors = {path = "../.."}
gleam_erlang = ">= 0.25.0 and < 1.0.0"

[dev-dependencies]
gleeunit = ">= 1.0.0 and < 2.0.0"
33 changes: 33 additions & 0 deletions e2e/mist_test/manifest.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# This file was generated by Gleam
# You typically do not need to edit this file

packages = [
{ name = "birl", version = "1.6.1", build_tools = ["gleam"], requirements = ["gleam_stdlib", "ranger"], otp_app = "birl", source = "hex", outer_checksum = "976CFF85D34D50F7775896615A71745FBE0C325E50399787088F941B539A0497" },
{ name = "exception", version = "2.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "exception", source = "hex", outer_checksum = "F5580D584F16A20B7FCDCABF9E9BE9A2C1F6AC4F9176FA6DD0B63E3B20D450AA" },
{ name = "filepath", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "filepath", source = "hex", outer_checksum = "EFB6FF65C98B2A16378ABC3EE2B14124168C0CE5201553DE652E2644DCFDB594" },
{ name = "gleam_crypto", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_crypto", source = "hex", outer_checksum = "ADD058DEDE8F0341F1ADE3AAC492A224F15700829D9A3A3F9ADF370F875C51B7" },
{ name = "gleam_erlang", version = "0.25.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "054D571A7092D2A9727B3E5D183B7507DAB0DA41556EC9133606F09C15497373" },
{ name = "gleam_http", version = "3.6.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_http", source = "hex", outer_checksum = "8C07DF9DF8CC7F054C650839A51C30A7D3C26482AC241C899C1CEA86B22DBE51" },
{ name = "gleam_json", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "thoas"], otp_app = "gleam_json", source = "hex", outer_checksum = "8B197DD5D578EA6AC2C0D4BDC634C71A5BCA8E7DB5F47091C263ECB411A60DF3" },
{ name = "gleam_otp", version = "0.10.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_stdlib"], otp_app = "gleam_otp", source = "hex", outer_checksum = "0B04FE915ACECE539B317F9652CAADBBC0F000184D586AAAF2D94C100945D72B" },
{ name = "gleam_stdlib", version = "0.37.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "5398BD6C2ABA17338F676F42F404B9B7BABE1C8DC7380031ACB05BBE1BCF3742" },
{ name = "gleeunit", version = "1.1.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "72CDC3D3F719478F26C4E2C5FED3E657AC81EC14A47D2D2DEBB8693CA3220C3B" },
{ name = "glisten", version = "2.0.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_otp", "gleam_stdlib"], otp_app = "glisten", source = "hex", outer_checksum = "CF3A9383E9BA4A8CBAF2F7B799716290D02F2AC34E7A77556B49376B662B9314" },
{ name = "hpack_erl", version = "0.3.0", build_tools = ["rebar3"], requirements = [], otp_app = "hpack", source = "hex", outer_checksum = "D6137D7079169D8C485C6962DFE261AF5B9EF60FBC557344511C1E65E3D95FB0" },
{ name = "logging", version = "1.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "logging", source = "hex", outer_checksum = "82C112ED9B6C30C1772A6FE2613B94B13F62EA35F5869A2630D13948D297BD39" },
{ name = "marceau", version = "1.1.0", build_tools = ["gleam"], requirements = [], otp_app = "marceau", source = "hex", outer_checksum = "1AAD727A30BE0F95562C3403BB9B27C823797AD90037714255EEBF617B1CDA81" },
{ name = "mist", version = "1.0.0", build_tools = ["gleam"], requirements = ["birl", "gleam_erlang", "gleam_http", "gleam_otp", "gleam_stdlib", "glisten", "hpack_erl", "logging"], otp_app = "mist", source = "hex", outer_checksum = "7765E53DCC9ACCACF217B8E0CA3DE7E848C783BFAE5118B75011E81C2C80385C" },
{ name = "ranger", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "ranger", source = "hex", outer_checksum = "1566C272B1D141B3BBA38B25CB761EF56E312E79EC0E2DFD4D3C19FB0CC1F98C" },
{ name = "simple_cors", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_http", "gleam_stdlib", "mist", "wisp"], source = "local", path = "../.." },
{ name = "simplifile", version = "1.7.0", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "1D5DFA3A2F9319EC85825F6ED88B8E449F381B0D55A62F5E61424E748E7DDEB0" },
{ name = "thoas", version = "0.4.1", build_tools = ["rebar3"], requirements = [], otp_app = "thoas", source = "hex", outer_checksum = "4918D50026C073C4AB1388437132C77A6F6F7C8AC43C60C13758CC0ADCE2134E" },
{ name = "wisp", version = "0.14.0", build_tools = ["gleam"], requirements = ["exception", "gleam_crypto", "gleam_erlang", "gleam_http", "gleam_json", "gleam_stdlib", "logging", "marceau", "mist", "simplifile"], otp_app = "wisp", source = "hex", outer_checksum = "9F5453AF1F9275E6F8707BC815D6A6A9DF41551921B16FBDBA52883773BAE684" },
]

[requirements]
gleam_erlang = { version = ">= 0.25.0 and < 1.0.0" }
gleam_http = { version = ">= 3.6.0 and < 4.0.0" }
gleam_stdlib = { version = ">= 0.34.0 and < 2.0.0" }
gleeunit = { version = ">= 1.0.0 and < 2.0.0" }
mist = { version = ">= 1.0.0 and < 2.0.0" }
simple_cors = { path = "../.." }
30 changes: 30 additions & 0 deletions e2e/mist_test/src/mist_test.gleam
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import gleam/bytes_builder
import gleam/erlang/process
import gleam/http
import gleam/http/request.{type Request}
import gleam/http/response.{type Response}
import mist.{type Connection, type ResponseData}
import simple_cors as cors

fn cors() {
cors.new()
|> cors.allow_origin("http://localhost:3000")
|> cors.allow_method(http.Get)
|> cors.allow_method(http.Post)
}

fn main_handler(req: Request(Connection)) -> Response(ResponseData) {
use _req <- cors.mist_handle(req, cors())
let empty = mist.Bytes(bytes_builder.new())
response.new(200)
|> response.set_body(empty)
}

pub fn main() {
let assert Ok(_) =
main_handler
|> mist.new()
|> mist.port(8080)
|> mist.start_http()
process.sleep(5000)
}
12 changes: 12 additions & 0 deletions e2e/mist_test/test/mist_test_test.gleam
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import gleeunit
import gleeunit/should

pub fn main() {
gleeunit.main()
}

// gleeunit test functions end in `_test`
pub fn hello_world_test() {
1
|> should.equal(1)
}
23 changes: 23 additions & 0 deletions e2e/wisp_test/.github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: test

on:
push:
branches:
- master
- main
pull_request:

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: erlef/setup-beam@v1
with:
otp-version: "26.0.2"
gleam-version: "1.1.0"
rebar3-version: "3"
# elixir-version: "1.15.4"
- run: gleam deps download
- run: gleam test
- run: gleam format --check src test
4 changes: 4 additions & 0 deletions e2e/wisp_test/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
*.beam
*.ez
/build
erl_crash.dump
25 changes: 25 additions & 0 deletions e2e/wisp_test/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# wisp_test

[![Package Version](https://img.shields.io/hexpm/v/wisp_test)](https://hex.pm/packages/wisp_test)
[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/wisp_test/)

```sh
gleam add wisp_test
```
```gleam
import wisp_test
pub fn main() {
// TODO: An example of the project in use
}
```

Further documentation can be found at <https://hexdocs.pm/wisp_test>.

## Development

```sh
gleam run # Run the project
gleam test # Run the tests
gleam shell # Run an Erlang shell
```
24 changes: 24 additions & 0 deletions e2e/wisp_test/gleam.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name = "wisp_test"
version = "1.0.0"

# Fill out these fields if you intend to generate HTML documentation or publish
# your project to the Hex package manager.
#
# description = ""
# licences = ["Apache-2.0"]
# repository = { type = "github", user = "username", repo = "project" }
# links = [{ title = "Website", href = "https://gleam.run" }]
#
# For a full reference of all the available options, you can have a look at
# https://gleam.run/writing-gleam/gleam-toml/.

[dependencies]
gleam_http = ">= 3.6.0 and < 4.0.0"
gleam_stdlib = ">= 0.34.0 and < 2.0.0"
mist = ">= 1.0.0 and < 2.0.0"
simple_cors = {path = "../.."}
wisp = ">= 0.14.0 and < 1.0.0"
gleam_erlang = ">= 0.25.0 and < 1.0.0"

[dev-dependencies]
gleeunit = ">= 1.0.0 and < 2.0.0"
Loading

0 comments on commit 4cb35ba

Please sign in to comment.