Skip to content
Open
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
7be9670
fix: fasthttp
enghitalo Dec 5, 2025
fc4517a
example: fasthttp
enghitalo Dec 5, 2025
fc46030
doc
enghitalo Dec 5, 2025
6ef794c
doc: ./v check-md vlib/fasthttp/
enghitalo Dec 5, 2025
97b870a
remove unused
enghitalo Dec 5, 2025
734f6b3
ops
enghitalo Dec 5, 2025
01741dc
perf: use runtime.nr_cpus()
enghitalo Dec 5, 2025
1b973a5
fix
enghitalo Dec 5, 2025
58ad72a
fix: CI
enghitalo Dec 5, 2025
4276a02
perf: make 'fixed' filds of array of Server be 'imutable'
enghitalo Dec 5, 2025
ff11217
feat, fix: error handling in run function
enghitalo Dec 5, 2025
529c82f
Update vbuild-examples.v
enghitalo Dec 6, 2025
c0521cb
Merge remote-tracking branch 'upstream/master' into fix/fasthttp
enghitalo Dec 9, 2025
214021e
v check-md examples
enghitalo Dec 9, 2025
a3784b0
ci: fix
enghitalo Dec 9, 2025
aba129c
remove C.accept
enghitalo Dec 9, 2025
37a3beb
doc
enghitalo Dec 9, 2025
4907eee
remove tiny_bad_request_d
enghitalo Dec 9, 2025
39e9b88
reorder const
enghitalo Dec 9, 2025
9473c91
fix windows CI
enghitalo Dec 9, 2025
ceb336f
finish
enghitalo Dec 10, 2025
6787995
Apply suggestion from @spytheman
spytheman Dec 10, 2025
e128a02
move .v files to top level, fix README.md description
spytheman Dec 10, 2025
141e0bf
Apply suggestion from @spytheman
spytheman Dec 10, 2025
ac8a858
Apply suggestion from @spytheman
spytheman Dec 10, 2025
7b67511
fix: veb minor changes
enghitalo Dec 10, 2025
e2024c0
fix: veb minor changes
enghitalo Dec 10, 2025
113533d
Merge remote-tracking branch 'upstream/master' into fix/fasthttp
enghitalo Dec 10, 2025
5d2115f
clean up and remove global
enghitalo Dec 10, 2025
fd1128a
fix: parse_request_head
enghitalo Dec 10, 2025
bd239bb
test
enghitalo Dec 10, 2025
fb6770a
test: compile
enghitalo Dec 10, 2025
06d19a8
fix: user_data support
enghitalo Dec 10, 2025
6b7e4fd
fix: vlib/fasthttp/fasthttp_darwin.v
enghitalo Dec 10, 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 cmd/tools/vbuild-examples.v
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const efolders = [
'examples/vweb_orm_jwt',
'examples/vweb_fullstack',
'examples/vanilla_http_server',
'examples/fasthttp',
]

pub fn normalised_vroot_path(path string) string {
Expand Down
71 changes: 71 additions & 0 deletions examples/fasthttp/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Fasthttp Example

A simple HTTP server example using the `fasthttp` module from `vlib/fasthttp`.

## Features

- Handles GET and POST requests
- Routes requests to different controllers based on HTTP method and path
- Returns appropriate HTTP responses with status codes and content

## Building

```sh
./v examples/fasthttp
```

## Running

```sh
./examples/fasthttp/fasthttp
```

The server will listen on `http://localhost:3000`

## Testing

### Home endpoint

```sh
curl http://localhost:3000/
```

### Get user by ID

```sh
curl http://localhost:3000/user/123
```

### Create user

```sh
curl -X POST http://localhost:3000/user
```

### 404 response

```sh
curl http://localhost:3000/notfound
```

## File Structure

- `main.v` - Entry point and request router
- `controllers.v` - Request handlers for different routes
- `v.mod` - Module metadata

## Architecture

The example demonstrates:

1. **Request Routing**: The `handle_request()` function routes incoming HTTP requests based on
method and path
2. **Response Handling**: Controllers return HTTP responses with proper headers and status codes
3. **Content Type**: All responses are returned as `[]u8` (byte arrays)

The fasthttp module handles:

- Low-level socket management
- Request parsing
- Connection handling
- Non-blocking I/O with epoll (Linux) or kqueue (macOS)
27 changes: 27 additions & 0 deletions examples/fasthttp/controllers.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
module main

fn home_controller() ![]u8 {
response := 'HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 13\r\n\r\nHello, World!'
return response.bytes()
}

fn get_user_controller(id string) ![]u8 {
body := 'User ID: ${id}'
content_length := body.len
response := 'HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: ${content_length}\r\n\r\n${body}'
return response.bytes()
}

fn create_user_controller() ![]u8 {
body := 'User created successfully'
content_length := body.len
response := 'HTTP/1.1 201 Created\r\nContent-Type: text/plain\r\nContent-Length: ${content_length}\r\n\r\n${body}'
return response.bytes()
}

fn not_found_response() ![]u8 {
body := '404 Not Found'
content_length := body.len
response := 'HTTP/1.1 404 Not Found\r\nContent-Type: text/plain\r\nContent-Length: ${content_length}\r\n\r\n${body}'
return response.bytes()
}
37 changes: 37 additions & 0 deletions examples/fasthttp/main.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
module main

import fasthttp

fn handle_request(req fasthttp.HttpRequest) ![]u8 {
method := req.buffer[req.method.start..req.method.start + req.method.len].bytestr()
path := req.buffer[req.path.start..req.path.start + req.path.len].bytestr()

if method == 'GET' {
if path == '/' {
return home_controller()!
} else if path.starts_with('/user/') {
id := path[6..]
return get_user_controller(id)!
}
} else if method == 'POST' {
if path == '/user' {
return create_user_controller()!
}
}

return not_found_response()!
}

fn main() {
mut server := fasthttp.new_server(fasthttp.ServerConfig{
port: 3000
handler: handle_request
}) or {
eprintln('Failed to create server: ${err}')
return
}

println('Starting fasthttp server on port http://localhost:3000...')

server.run() or { eprintln('error: ${err}') }
}
6 changes: 6 additions & 0 deletions examples/fasthttp/v.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Module {
name: 'fasthttp_example'
description: 'A simple HTTP server example using the fasthttp module'
version: '0.1.0'
license: 'MIT'
}
161 changes: 161 additions & 0 deletions vlib/fasthttp/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
# fasthttp

The `fasthttp` module is a high-performance HTTP server library for V that provides low-level socket management and non-blocking I/O.

## Features

- **High Performance**: Uses platform-specific I/O multiplexing:
- `epoll` on Linux for efficient connection handling
- `kqueue` on macOS for high-performance event notification
- **Non-blocking I/O**: Handles multiple concurrent connections efficiently
- **Simple API**: Easy-to-use request handler pattern
- **Cross-platform**: Supports Linux and macOS

## Installation

The module is part of the standard V library. Import it in your V code:

```v
import fasthttp
```

## Quick Start

Here's a minimal HTTP server example:

```v
import fasthttp

fn handle_request(req fasthttp.HttpRequest) ![]u8 {
path := req.buffer[req.path.start..req.path.start + req.path.len].bytestr()

if path == '/' {
return 'Hello, World!'.bytes()
}

return '404 Not Found'.bytes()
}

fn main() {
mut server := fasthttp.new_server(fasthttp.ServerConfig{
port: 3000
handler: handle_request
}) or {
eprintln('Failed to create server: ${err}')
return
}

println('Server listening on http://localhost:3000')
server.run() or { eprintln('error: ${err}') }
}
```

## API Reference

### `HttpRequest` Struct

Represents an incoming HTTP request.

**Fields:**

- `buffer: []u8` - The raw request buffer containing the complete HTTP request
- `method: Slice` - The HTTP method (GET, POST, etc.)
- `path: Slice` - The request path
- `version: Slice` - The HTTP version (e.g., "HTTP/1.1")
- `client_conn_fd: int` - Internal socket file descriptor

### `Slice` Struct

Represents a slice of the request buffer.

**Fields:**

- `start: int` - Starting index in the buffer
- `len: int` - Length of the slice

**Usage:**

```v ignore
method := req.buffer[req.method.start..req.method.start + req.method.len].bytestr()
path := req.buffer[req.path.start..req.path.start + req.path.len].bytestr()
```

## Request Handler Pattern

The handler function receives an `HttpRequest` and must return either:

- `[]u8` - A byte array containing the HTTP response body
- An error if processing failed

The handler should extract method and path information from the request and route accordingly.

**Example:**

```v ignore
fn my_handler(req fasthttp.HttpRequest) ![]u8 {
method := req.buffer[req.method.start..req.method.start + req.method.len].bytestr()
path := req.buffer[req.path.start..req.path.start + req.path.len].bytestr()

match method {
'GET' {
if path == '/' {
return 'Home page'.bytes()
}
}
'POST' {
if path == '/api/data' {
return 'Data received'.bytes()
}
}
else {}
}

return '404 Not Found'.bytes()
}
```

## Response Format

Responses should be returned as byte arrays.
The server will send them directly to the client as HTTP response bodies.

```v ignore
// Simple text response
return 'Hello, World!'.bytes()

// HTML response
return '<html><body>Hello</body></html>'.bytes()

// JSON response
return '{"message": "success"}'.bytes()
```

## Example

See the complete example in `examples/fasthttp/` for a more
detailed server implementation with multiple routes and controllers.

```sh
./v examples/fasthttp
./examples/fasthttp/fasthttp
```

## Platform Support

- **Linux**: Uses `epoll` for high-performance I/O multiplexing
- **macOS**: Uses `kqueue` for event notification
- **Windows**: Currently not supported

## Performance Considerations

- The `fasthttp` module is designed for high throughput and low latency
- Handler functions should be efficient; blocking operations will affect other connections
- Use goroutines within handlers if you need to perform long-running operations without
blocking the I/O loop

## Notes

- HTTP headers are currently not parsed; the entire request is available in the buffer
- Only the request method, path, and version are parsed automatically
- Response status codes and headers must be manually constructed if needed
- The module provides low-level access for maximum control and performance
Loading
Loading