Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
130 commits
Select commit Hold shift + click to select a range
3f4baab
feat: async type classes
algebraic-dev Sep 12, 2025
437fb04
feat: remove outparams
algebraic-dev Sep 20, 2025
0bad6ae
fix: remove useless function
algebraic-dev Sep 20, 2025
992b946
fix: stream can only return one type
algebraic-dev Sep 20, 2025
9dbca20
feat: async traits
algebraic-dev Sep 15, 2025
9337835
fix: small fixes
algebraic-dev Sep 15, 2025
1170afb
fix: wrong function
algebraic-dev Sep 20, 2025
f8e4ca4
fix: channel
algebraic-dev Sep 16, 2025
8a61ba5
feat: basics stream map
algebraic-dev Sep 16, 2025
b4165be
fix: stream map
algebraic-dev Sep 16, 2025
46b1352
fix: channel
algebraic-dev Sep 16, 2025
1ad1eaf
fix: async stream
algebraic-dev Sep 20, 2025
9ed922e
fix: streammap
algebraic-dev Sep 20, 2025
39a3086
fix: async
algebraic-dev Sep 24, 2025
1f0e383
fix: small comments
algebraic-dev Sep 24, 2025
cf67727
fix: async
algebraic-dev Sep 24, 2025
6ddd405
fix: simplify
algebraic-dev Sep 22, 2025
527a5d3
feat: cancellation
algebraic-dev Sep 22, 2025
0fe4086
fix: streammap
algebraic-dev Sep 25, 2025
f4d67f4
fix: async
algebraic-dev Sep 24, 2025
78f2f96
feat: http
algebraic-dev Sep 20, 2025
1bf975b
fix: copyright notice
algebraic-dev Sep 20, 2025
284825c
fix: coe option
algebraic-dev Sep 20, 2025
73aa8e7
fix: imports
algebraic-dev Sep 20, 2025
4b4e4dc
fix: remove orphaned module
algebraic-dev Sep 20, 2025
cc3776a
fix: funnel imports
algebraic-dev Sep 21, 2025
66a9dfa
fix: imports
algebraic-dev Sep 21, 2025
505f986
feat: tests and small changes
algebraic-dev Sep 23, 2025
1fe5b21
fix: bytestream
algebraic-dev Sep 25, 2025
7cfd285
fix: remove useless coe
algebraic-dev Sep 25, 2025
de91f32
feat: add header value validation
algebraic-dev Sep 25, 2025
6ce62bb
fix: merge
algebraic-dev Sep 25, 2025
1922fda
fix: test and small comments
algebraic-dev Sep 25, 2025
594e713
feat: small changes
algebraic-dev Sep 26, 2025
58b4f98
fix: url parser
algebraic-dev Sep 26, 2025
9205242
fix: comment and bytebuffer
algebraic-dev Sep 26, 2025
3df4884
fix: comments
algebraic-dev Sep 26, 2025
87c960d
fix: bytestream comments
algebraic-dev Sep 26, 2025
4019179
fix: comments
algebraic-dev Sep 26, 2025
10d58c5
fix: style changes
algebraic-dev Sep 26, 2025
ac80739
feat: improve comment of serveConnection
algebraic-dev Sep 26, 2025
4df0c69
fix: small changes
algebraic-dev Sep 26, 2025
0912602
feat: small changes
algebraic-dev Oct 3, 2025
71b83c0
fix: update to master
algebraic-dev Oct 7, 2025
51d8cfc
fix: timeout
algebraic-dev Oct 7, 2025
2e03c22
fix: test
algebraic-dev Oct 7, 2025
957fe41
feat: rename
algebraic-dev Oct 9, 2025
761b703
refactor: http
algebraic-dev Oct 10, 2025
974c9ec
feat: http client
algebraic-dev Oct 14, 2025
a31a891
feat: async type classes
algebraic-dev Sep 12, 2025
c446ecf
feat: remove outparams
algebraic-dev Sep 20, 2025
aacbe82
fix: remove useless function
algebraic-dev Sep 20, 2025
d590af5
fix: stream can only return one type
algebraic-dev Sep 20, 2025
883bf66
feat: async traits
algebraic-dev Sep 15, 2025
586c171
fix: small fixes
algebraic-dev Sep 15, 2025
4dc56a4
fix: wrong function
algebraic-dev Sep 20, 2025
d63e682
fix: channel
algebraic-dev Sep 16, 2025
510707f
feat: basics stream map
algebraic-dev Sep 16, 2025
b6fb42c
fix: stream map
algebraic-dev Sep 16, 2025
1cde50a
fix: channel
algebraic-dev Sep 16, 2025
78daa21
fix: async stream
algebraic-dev Sep 20, 2025
f46367a
fix: streammap
algebraic-dev Sep 20, 2025
131b53f
fix: async
algebraic-dev Sep 24, 2025
01a0aae
fix: small comments
algebraic-dev Sep 24, 2025
f0fcdff
fix: async
algebraic-dev Sep 24, 2025
3288469
fix: simplify
algebraic-dev Sep 22, 2025
ee9bd54
feat: cancellation
algebraic-dev Sep 22, 2025
ae003a9
fix: streammap
algebraic-dev Sep 25, 2025
a7ae09d
fix: async
algebraic-dev Sep 24, 2025
e4b5ca9
feat: http
algebraic-dev Sep 20, 2025
4660d4a
fix: remove orphaned module
algebraic-dev Sep 20, 2025
eeb47fc
fix: funnel imports
algebraic-dev Sep 21, 2025
37fc80f
feat: tests and small changes
algebraic-dev Sep 23, 2025
a666d29
fix: bytestream
algebraic-dev Sep 25, 2025
1bc8051
feat: add header value validation
algebraic-dev Sep 25, 2025
f380b3b
feat: small changes
algebraic-dev Sep 26, 2025
28a3cfd
fix: comment and bytebuffer
algebraic-dev Sep 26, 2025
082ac99
fix: comments
algebraic-dev Sep 26, 2025
424fb96
fix: comments
algebraic-dev Sep 26, 2025
9355655
fix: style changes
algebraic-dev Sep 26, 2025
8af48ff
feat: small changes
algebraic-dev Oct 3, 2025
45395fc
fix: update to master
algebraic-dev Oct 7, 2025
cdaed1f
fix: http
algebraic-dev Oct 14, 2025
d73e211
fix: remove orphaned modules
algebraic-dev Oct 14, 2025
aea10b7
fix: selectors
algebraic-dev Oct 17, 2025
9074763
feat: small changes
algebraic-dev Oct 17, 2025
56dd8f4
feat: closePeerConnection
algebraic-dev Oct 17, 2025
da1d565
fix: behavior of the client
algebraic-dev Oct 17, 2025
232fc85
fix: copyright header
algebraic-dev Oct 20, 2025
ef8c989
fix: remove macro
algebraic-dev Oct 20, 2025
78df363
fix: comment
algebraic-dev Oct 20, 2025
2f91b3c
feat: improve chunk extensions and handling of shutdown
algebraic-dev Oct 20, 2025
9ab5445
fix: remove log
algebraic-dev Oct 20, 2025
f612eca
feat: big refactor
algebraic-dev Oct 30, 2025
ce0c271
refactor: part of the connection API
algebraic-dev Oct 31, 2025
75b24dd
fix: headers
algebraic-dev Oct 31, 2025
f00b88d
fix: protocol
algebraic-dev Nov 1, 2025
bbc7a19
fix: small issues with chunks and comments
algebraic-dev Nov 1, 2025
5afc6c6
feat: remove useless variable
algebraic-dev Nov 1, 2025
e88e84d
fix: remove small useless things
algebraic-dev Nov 11, 2025
562f504
fix: loop
algebraic-dev Nov 13, 2025
6052b2a
feat: header detection and duplication
algebraic-dev Nov 13, 2025
9c10bc5
feat: limits and tests
algebraic-dev Nov 15, 2025
7391d81
fix: copyright header
algebraic-dev Nov 15, 2025
47d71cd
fix: test
algebraic-dev Nov 15, 2025
e36bb26
fix: import structure
algebraic-dev Nov 15, 2025
87fe876
feat: small improvements in tests and client
algebraic-dev Nov 22, 2025
59c617b
feat: header changes
algebraic-dev Nov 22, 2025
59a0171
fix: test
algebraic-dev Nov 23, 2025
7b7d49e
fix: bug fixes and improvement in performance
algebraic-dev Nov 23, 2025
148f83f
fix: tests
algebraic-dev Nov 23, 2025
edd9759
fix: remove client related
algebraic-dev Nov 23, 2025
a389f93
fix: details of connection: close
algebraic-dev Nov 23, 2025
ce85f65
fix: test
algebraic-dev Nov 23, 2025
fd36c96
fix: weird behaviro when message as not sent :)
algebraic-dev Nov 27, 2025
942c044
fix: multiple small problems
algebraic-dev Nov 30, 2025
9e7d485
fix: string changes
algebraic-dev Nov 30, 2025
beaa1e6
fix: trailers parsing
algebraic-dev Dec 2, 2025
ba27d70
feat: parse chunk
algebraic-dev Dec 2, 2025
a0c9b3a
fix: trailer
algebraic-dev Dec 2, 2025
709fea1
fix: parser
algebraic-dev Dec 3, 2025
1c590b5
fix: grammatical issues
algebraic-dev Dec 3, 2025
b9d0c50
fix: gramatic issues
algebraic-dev Dec 3, 2025
99bc6ce
fix: ext chunk
algebraic-dev Dec 4, 2025
912025d
fix: context
algebraic-dev Dec 5, 2025
dfdb3b5
feat: contextual fixes
algebraic-dev Dec 5, 2025
6c3e392
feat: add more tests
algebraic-dev Dec 6, 2025
aa5a6d3
fix: docs
algebraic-dev Dec 6, 2025
0489523
fix: comments
algebraic-dev Dec 8, 2025
db6975c
feat: cancellation backwards
algebraic-dev Dec 8, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/Std/Internal.lean
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ prelude
public import Std.Internal.Async
public import Std.Internal.Parsec
public import Std.Internal.UV
public import Std.Internal.Http

@[expose] public section

Expand Down
100 changes: 100 additions & 0 deletions src/Std/Internal/Http.lean
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/-
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Sofia Rodrigues
-/
module

prelude
public import Std.Internal.Http.Server

public section

/-!
# Http

A "low-level" HTTP 1.1 Server implementation for Lean. It is designed to be used with or without the
`Async` library if you want to implement a custom `Connection`.

# Overview

This module of the standard library defines many concepts related to the HTTP protocol and its semantics
in a sans I/O format.

**sans I/O** means that the core logic of the library doesn’t perform any actual input/output itself,
it just defines how data *should* be processed. This separation allows the protocol implementation
to remain pure and testable, while different transports (like TCP sockets or mocks) can handle
the actual reading and writing of bytes.

The main function of this library is `Std.Http.Server.serve`,
located in the module `Std.Internal.Http.Server`. It starts a simple HTTP/1.1 server that
handles all requests and sends them to a simple handler function. It uses the default `Std.Internal.Async`
library, but it can be customized to use whatever IO library you want, as the protocol implementation
is pure.

If you want to customize how your server handles sockets, you can use `Std.Http.Server.serveConnection`,
which is a simple function to bind a handler to a `Transport`.

# Minimal Example

```lean
import Std.Internal.Http
import Std.Internal.Async

open Std.Internal.IO.Async
open Std Http

def handler (req : Request Body) : ContextAsync (Response Body) := do
let some data ← req.body.collectString
| return Response.badRequest "expected a utf8 body"

return Response.ok ("hi, " ++ data)

def mainAsync : Async Unit := do
let address := .v4 (.mk (.ofParts 0 0 0 0) 8080)
let server ← Server.serve address handler
server.waitShutdown

def main := mainAsync.block
```

# Main Concepts

## Transport

`Std.Http.Server.Transport` is a type class that defines how communication occurs between a `Connection`
and the outside world. It can be implemented by, for example, a `Mock.Client`, which sends and receives
byte arrays for deterministic HTTP connection testing, or by a `TCP.Socket.Client`, which is the
standard way to communicate over the internet in HTTP/1.1.

## Connection

`Std.Http.Server.Connection` is a structure that holds both a `Transport` and a `Machine`. The machine is
a `Protocol.H1.Machine`, which implements the state machine responsible for parsing HTTP/1.1 requests and responses.
It can change in the future if some other protocols are implemented

If you want to customize how your server handles sockets, you can use `Std.Http.Server.serveConnection`,
a simple function that binds a handler to a `ClientConnection`.

# Minimal Example

```lean
import Std.Internal.Http
import Std.Internal.Async

open Std.Internal.IO.Async
open Std Http

def handler (req : Request Body) : ContextAsync (Response Body) := do
let some data ← req.body.collectString
| return Response.badRequest "expected a utf8 body"

return Response.ok ("hi, " ++ data)

def mainAsync : Async Unit := do
let server ← Server.serve (.v4 (.mk (.ofParts 0 0 0 0) 8080)) handler
server.waitShutdown

def main := mainAsync.block
```
-/
17 changes: 17 additions & 0 deletions src/Std/Internal/Http/Data.lean
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/-
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Sofia Rodrigues
-/
module

prelude
public import Std.Internal.Http.Data.Body
public import Std.Internal.Http.Data.Headers
public import Std.Internal.Http.Data.Method
public import Std.Internal.Http.Data.Version
public import Std.Internal.Http.Data.Request
public import Std.Internal.Http.Data.Response
public import Std.Internal.Http.Data.URI
public import Std.Internal.Http.Data.Status
public import Std.Internal.Http.Data.Version
109 changes: 109 additions & 0 deletions src/Std/Internal/Http/Data/Body.lean
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/-
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Sofia Rodrigues
-/
module

prelude
public import Std.Internal.Async.Context
public import Std.Internal.Http.Data.Body.Length
public import Std.Internal.Http.Data.Body.ByteStream

public section

/-!
# Body

This module defines the `Body` type, which represents the body of an HTTP request or response.
-/

namespace Std.Http

open Std Internal IO Async

/--
Type that represents the body of a request or response with streams of byte arrays or byte arrays of fixed
size.
-/
inductive Body where
/--
Empty body with no content
-/
| zero

/--
Body containing raw byte data stored in memory
-/
| bytes (data : ByteArray)

/--
Body containing streaming data from a byte stream channel
-/
| stream (channel : Body.ByteStream)
deriving Inhabited

namespace Body

/--
Get content length of a body (if known).
-/
def getContentLength (body : Body) : Length :=
match body with
| zero => .fixed 0
| .bytes data => .fixed data.size
| .stream _ => .chunked

/--
Close the body and release any associated resources. For streaming bodies, this closes the underlying
channel. For other body types, this is a no-op.
-/
def close (body : Body) : Async Unit :=
match body with
| .stream channel => channel.close
| _ => pure ()

instance : Coe String Body where
coe := .bytes ∘ String.toUTF8

instance : Coe ByteArray Body where
coe := .bytes

instance : Coe Body.ByteStream Body where
coe := .stream

instance : EmptyCollection Body where
emptyCollection := Body.zero

instance : ForIn Async Body Chunk where
forIn body acc step :=
match body with
| .zero => pure acc
| .bytes data => return (← step (Chunk.mk data #[]) acc).value
| .stream stream' => ByteStream.forIn stream' acc step

instance : ForIn ContextAsync Body Chunk where
forIn body acc step :=
match body with
| .zero => pure acc
| .bytes data => return (← step (Chunk.mk data #[]) acc).value
| .stream stream' => ByteStream.forIn' stream' acc step

/--
Collect all data from the body into a single `ByteArray`. This reads the entire body content into memory
and consumes significant memory for large bodies.
-/
def collectByteArray (body : Body) : Async ByteArray := do
let mut result := .empty
for x in body do result := result ++ x.data
return result

/--
Collect all data from the body into a single `String`. This reads the entire body content into memory
and consumes significant memory for large bodies. Returns `some` if the data is valid UTF-8, otherwise
`none`.
-/
def collectString (body : Body) : Async (Option String) := do
let mut result := .empty
for x in body do result := result ++ x.data
return String.fromUTF8? result
Loading
Loading