English Documentation πΊπΈ
Aetherλ GleamμΌλ‘ μμ±λ μλ² νλ μμν¬μ΄μ νμ΅μ© λ€νΈμνΉ μ€νμ λλ€. μ μμ€ TCP/UDP μμΌ λνΌλΆν° HTTP/1.x νμ/λΉλ, HTTP/2 νλ μ΄λ°κ³Ό HPACK, νμ΄νλΌμΈ μ‘°ν©, λΌμ°ν°, JSON μ§λ ¬νμ content negotiationκΉμ§ ν μ μ₯μ μμμ λ€λ£Ήλλ€.
νμ¬ μ½λλ² μ΄μ€λ λ€μ λ μΆμΌλ‘ ꡬμ±λ©λλ€.
- νλ μμν¬ λͺ¨λ:
src/aether/** - μ€ν μμ μ ν΅ν© μ§μ
μ :
src/aether/examples/**,src/aether.gleam
μ΄ νλ‘μ νΈλ κ²½ν¬λνκ΅ μ»΄ν¨ν°κ³΅νκ³Ό νμ€ν μλΉμ€ λ€νΈμνΉ μμ κ³Όμ λ‘ μ μλμμ΅λλ€.
- νμ
μμ ν μμ²/μλ΅ μ²λ¦¬μ
ResultκΈ°λ° μ€λ₯ λͺ¨λΈ - TCP/UDP μμΌ μΆμν, μ΅μ ꡬμ±, μλ¬ λ§€ν, μ°κ²° κ΄λ¦¬
- HTTP/1.x μμ² νμ±, μλ΅ μμ±, URL μΈμ½λ©/λμ½λ©, νμ΄νλΌμΈ μ€ν μ΄μ§
- HTTP/2 νλ μ νμ±/μμ±, HPACK, μ€νΈλ¦Ό κ΄λ¦¬, νλ¦ μ μ΄
- νλ‘ν μ½ λ μ§μ€νΈλ¦¬, κ²μ¦κΈ°, νμ΄νλΌμΈ λΉλ
- ν¨ν΄ λ§€μΉ λΌμ°ν°, λΌμ°νΈ κ·Έλ£Ή, path/query νλΌλ―Έν° μ²λ¦¬
- JSON μ§λ ¬νμ
Acceptν€λ κΈ°λ° content negotiation - νλμ ν¬νΈμμ
HTTP/1.1 + h2cλλTLS + ALPN(h2, http/1.1)μμ μλ²
| νλͺ© | κ° |
|---|---|
src/aether Gleam λͺ¨λ |
70κ° |
src μ 체 νμΌ |
74κ° |
test νμΌ |
53κ° |
src μ½λ λΌμΈ |
29,555 |
test μ½λ λΌμΈ |
18,813 |
| λ‘컬 κ²μ¦ κ²°κ³Ό | gleam test 1308 passing |
μ μμΉλ νμ¬ μ μ₯μ νΈλ¦¬λ₯Ό κΈ°μ€μΌλ‘ κ³μ°νμ΅λλ€.
tcp,udp,socket,transportconnection,connection_manager,connection_supervisorconnection_config,socket_options,socket_error
- HTTP/1.x: request/response model, parser, builder, stage, URL utilities
- HTTP/2: frame layer, connection state, stream management, flow control
- HPACK: encoder, decoder, table, huffman, integer, string
- TCP νμ΅μ© νλ‘ν μ½ κ³μΈ΅: header, parser, builder, checksum, state, stage, mode
- νλ‘ν μ½ μ‘°ν©:
protocol,registry,validator,pipeline_builder
pipeline/*λ‘ μ‘°ν© κ°λ₯ν μ²λ¦¬ λ¨κ³ ꡬμ±router/*λ‘ path pattern, route group, params κΈ°λ° λΌμ°νserialization/json,serialization/negotiationμΌλ‘ μλ΅ μ§λ ¬νμ νμ μ²λ¦¬
src/aether.gleam: HTTP/1.x / HTTP/2 λ°λͺ¨ μ€νsrc/aether/examples/server_main.gleam: λ©ν°νλ‘ν μ½ CRUD μλ²src/aether/examples/http1/*: HTTP/1.x CRUD λΌμ°ν°μ νΈλ€λ¬src/aether/examples/http2/*: HTTP/2 νλ μ λ 벨 CRUD μμ src/aether/examples/multiprotocol/*: h2c / TLS ALPN λ°νμ ꡬμ±κ³Ό μλ² λ°μΈλ©
src/aether.gleamsrc/aether/examples/server_main.gleam
src/aether/core/data.gleamsrc/aether/core/message.gleam
src/aether/examples/common/store.gleamsrc/aether/examples/common/user.gleamsrc/aether/examples/http1/handlers.gleamsrc/aether/examples/http1/http2_handlers.gleamsrc/aether/examples/http1/server.gleamsrc/aether/examples/http2/handlers.gleamsrc/aether/examples/http2/server.gleamsrc/aether/examples/multiprotocol/runtime.gleamsrc/aether/examples/multiprotocol/server.gleam
src/aether/network/connection.gleamsrc/aether/network/connection_config.gleamsrc/aether/network/connection_manager.gleamsrc/aether/network/connection_supervisor.gleamsrc/aether/network/socket.gleamsrc/aether/network/socket_error.gleamsrc/aether/network/socket_options.gleamsrc/aether/network/tcp.gleamsrc/aether/network/transport.gleamsrc/aether/network/udp.gleam
src/aether/pipeline/compose.gleamsrc/aether/pipeline/error.gleamsrc/aether/pipeline/executor.gleamsrc/aether/pipeline/pipeline.gleamsrc/aether/pipeline/stage.gleam
src/aether/protocol/pipeline_builder.gleamsrc/aether/protocol/protocol.gleamsrc/aether/protocol/registry.gleamsrc/aether/protocol/validator.gleam
src/aether/protocol/http/builder.gleamsrc/aether/protocol/http/parser.gleamsrc/aether/protocol/http/request.gleamsrc/aether/protocol/http/response.gleamsrc/aether/protocol/http/stage.gleamsrc/aether/protocol/http/unified.gleamsrc/aether/protocol/http/url.gleam
src/aether/protocol/http2/connection.gleamsrc/aether/protocol/http2/error.gleamsrc/aether/protocol/http2/flow_control.gleamsrc/aether/protocol/http2/frame.gleamsrc/aether/protocol/http2/frame_builder.gleamsrc/aether/protocol/http2/frame_parser.gleamsrc/aether/protocol/http2/preface.gleamsrc/aether/protocol/http2/stage.gleamsrc/aether/protocol/http2/stream.gleamsrc/aether/protocol/http2/stream_manager.gleam
src/aether/protocol/http2/hpack/decoder.gleamsrc/aether/protocol/http2/hpack/encoder.gleamsrc/aether/protocol/http2/hpack/huffman.gleamsrc/aether/protocol/http2/hpack/integer.gleamsrc/aether/protocol/http2/hpack/string.gleamsrc/aether/protocol/http2/hpack/table.gleam
src/aether/protocol/tcp/builder.gleamsrc/aether/protocol/tcp/checksum.gleamsrc/aether/protocol/tcp/connection.gleamsrc/aether/protocol/tcp/header.gleamsrc/aether/protocol/tcp/mode.gleamsrc/aether/protocol/tcp/parser.gleamsrc/aether/protocol/tcp/stage.gleamsrc/aether/protocol/tcp/state.gleam
src/aether/router/group.gleamsrc/aether/router/params.gleamsrc/aether/router/pattern.gleamsrc/aether/router/router.gleam
src/aether/serialization/json.gleamsrc/aether/serialization/negotiation.gleam
src/aether/util/benchmark.gleamsrc/aether/util/time.gleam
src/aether_examples_runtime_ffi.erlsrc/aether_tcp_ffi.erlsrc/aether_udp_ffi.erl
| μ»΄ν¬λνΈ | ν¨ν€μ§ | λ²μ λ²μ | μν |
|---|---|---|---|
| νμ€ λΌμ΄λΈλ¬λ¦¬ | gleam_stdlib |
>= 0.44.0 and < 2.0.0 |
κΈ°λ³Έ μλ£κ΅¬μ‘°μ μ νΈλ¦¬ν° |
| Erlang μ°λ | gleam_erlang |
>= 1.0.0 and < 2.0.0 |
BEAM/OTP μ°λ |
| HTTP νμ | gleam_http |
>= 4.0.0 and < 5.0.0 |
HTTP λ©μλ/νμ |
| JSON | gleam_json |
>= 2.0.0 and < 4.0.0 |
JSON μ²λ¦¬ |
| OTP | gleam_otp |
>= 1.0.0 and < 2.0.0 |
μ‘ν°/μνΌλ°μ΄μ ν¨ν΄ |
| μ μμ€ λ€νΈμνΉ | glisten |
>= 8.0.1 and < 9.0.0 |
μμΌκ³Ό 리μ€λ |
| HTTP μλ² | mist |
>= 5.0.0 and < 6.0.0 |
HTTP μλ² ν΅ν© |
| ν μ€νΈ | gleeunit |
>= 1.8.0 and < 2.0.0 |
ν μ€νΈ λ¬λ |
- Gleam
>= 1.11.0 - Erlang/OTP
>= 26 - Git
git clone https://github.com/jisung-02/aether.git
cd aether
gleam build# μ 체 λΉλ
gleam build
# λ°λͺ¨ μ€ν (src/aether.gleam)
gleam run
# λ©ν°νλ‘ν μ½ CRUD μλ² μ€ν
gleam run -m aether/examples/server_main
# ν
μ€νΈ
gleam test
# ν¬λ§· κ²μ¬
gleam format --check src testsrc/aether/examples/server_main.gleamμ νλμ 리μ€λμμ μλ λ λͺ¨λλ₯Ό μ§μν©λλ€.
- κΈ°λ³Έ λͺ¨λ:
HTTP/1.1 + h2c - TLS λͺ¨λ:
HTTP/1.1 + HTTP/2withALPN
| λ³μ | μ€λͺ | κΈ°λ³Έκ° |
|---|---|---|
AETHER_PORT |
μλ² ν¬νΈ | 3000(κΈ°λ³Έ), TLS μ¬μ© μ 3443 |
AETHER_TLS_CERT |
TLS μΈμ¦μ κ²½λ‘ | λ―Έμ€μ |
AETHER_TLS_KEY |
TLS κ°μΈν€ κ²½λ‘ | λ―Έμ€μ |
AETHER_TLS_CERTμ AETHER_TLS_KEYλ λ λ€ μμ΄μΌ TLS λͺ¨λκ° νμ±νλ©λλ€.
gleam run -m aether/examples/server_main
curl http://localhost:3000/api/users
curl --http2-prior-knowledge http://localhost:3000/api/usersAETHER_TLS_CERT=./cert.pem \
AETHER_TLS_KEY=./key.pem \
gleam run -m aether/examples/server_main
curl -k --http1.1 https://localhost:3443/api/users
curl -k --http2 https://localhost:3443/api/usersGET /api/usersGET /api/users/:idPOST /api/usersPUT /api/users/:idDELETE /api/users/:idGET /api/http2/usersGET /api/http2/users/:idPOST /api/http2/usersPUT /api/http2/users/:idDELETE /api/http2/users/:id
μλ μμ λ νμ¬ λΌμ°ν° APIμ λ§λ μ΅μ ꡬμ±μ λλ€.
import aether/core/data.{type Data}
import aether/protocol/http/request
import aether/protocol/http/response
import aether/router/params
import aether/router/router
fn health(
_req: request.ParsedRequest,
_params: params.Params,
_data: Data,
) -> Result(response.HttpResponse, router.RouteError) {
Ok(response.text_response(200, "ok"))
}
pub fn app() -> router.Router {
router.new()
|> router.get("/health", health)
}Path/query νλΌλ―Έν°λ aether/router/paramsμμ μ½μ΅λλ€.
case params.get_int(route_params, "id") {
Some(id) -> // use id
None -> // invalid or missing
}μ€μ μλ²μ Mist ν΅ν© μμλ src/aether/examples/server_main.gleamμ μ°Έκ³ νλ©΄ λ©λλ€.
νμ¬ HTTP/2 μ°κ²° APIλ μλ νλ¦μΌλ‘ μ¬μ©ν©λλ€.
import aether/protocol/http2/connection
pub fn handle_request(incoming_frame) {
let conn = connection.new_server()
case connection.handle_frame(conn, incoming_frame) {
connection.RequestComplete(conn, stream_id, headers, body) -> {
let #(conn, response_frames) = connection.build_response(
conn,
stream_id,
200,
[#("content-type", "application/json")],
body,
)
// send response_frames
}
connection.SendFrames(conn, frames) -> {
// send control frames
}
connection.HandleOk(conn) -> {
// state updated, nothing to send
}
connection.HandleError(conn, error) -> {
// connection-level error handling
}
}
}| νλͺ© | μν | λΉκ³ |
|---|---|---|
| TCP/UDP μμΌ κ³μΈ΅ | β ꡬν | λ¨μ/ν΅ν© ν μ€νΈ ν¬ν¨ |
| μ°κ²° κ΄λ¦¬ | β ꡬν | manager/supervisor ν¬ν¨ |
| HTTP/1.x νμ±/λΉλ© | β ꡬν | parser, builder, stage μ 곡 |
| HTTP/2 νλ μ΄λ° | β ꡬν | frame/frame_parser/frame_builder |
| HPACK | β ꡬν | encoder/decoder/table/huffman ν¬ν¨ |
| μ€νΈλ¦Ό κ΄λ¦¬/νλ¦ μ μ΄ | β ꡬν | stream_manager, flow_control |
| h2c + TLS/ALPN μμ μλ² | β ꡬν | examples/multiprotocol/* |
| λΌμ°ν° | β ꡬν | route group, params, mount μ§μ |
| JSON μ§λ ¬ν | β ꡬν | serialization/json |
| Content negotiation | β ꡬν | serialization/negotiation |
| graceful shutdown timeout | connection_managerμ placeholder μ‘΄μ¬ |
|
| benchmark μΈ‘μ μ νλ | util/benchmarkμ TODO μ‘΄μ¬ |
|
| WebSocket | β 미ꡬν | README μ°¨μμμ λ³λ μ 곡 μμ |
| HTTP/2 Server Push | β 미ꡬν | README μ°¨μμμ λ³λ μ 곡 μμ |
GitHub Actionsλ μλ λͺ λ Ήμ κΈ°μ€μΌλ‘ κ²μ¦ν©λλ€.
gleam test
gleam format --check src testνμ¬ μν¬νλ‘μ° κΈ°μ€ CI λ²μ μ Gleam 1.12.0, Erlang/OTP 27.1.2μ
λλ€.
μμΌ ν΅ν© ν μ€νΈκ° ν¬ν¨λμ΄ μμΌλ―λ‘, μ€ν νκ²½μ λ°λΌ λ€νΈμν¬ κΆνμ΄ νμν μ μμ΅λλ€.
κΈ°μ¬ μ κΆμ₯ μ μ°¨:
gleam format
gleam testPR ν
νλ¦Ώμ .github/pull_request_template.mdλ₯Ό μ¬μ©ν©λλ€.
MIT License