-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
fix: fasthttp #25906
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
enghitalo
wants to merge
34
commits into
vlang:master
Choose a base branch
from
enghitalo:fix/fasthttp
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+1,063
−711
Open
fix: fasthttp #25906
Changes from 23 commits
Commits
Show all changes
34 commits
Select commit
Hold shift + click to select a range
7be9670
fix: fasthttp
enghitalo fc4517a
example: fasthttp
enghitalo fc46030
doc
enghitalo 6ef794c
doc: ./v check-md vlib/fasthttp/
enghitalo 97b870a
remove unused
enghitalo 734f6b3
ops
enghitalo 01741dc
perf: use runtime.nr_cpus()
enghitalo 1b973a5
fix
enghitalo 58ad72a
fix: CI
enghitalo 4276a02
perf: make 'fixed' filds of array of Server be 'imutable'
enghitalo ff11217
feat, fix: error handling in run function
enghitalo 529c82f
Update vbuild-examples.v
enghitalo c0521cb
Merge remote-tracking branch 'upstream/master' into fix/fasthttp
enghitalo 214021e
v check-md examples
enghitalo a3784b0
ci: fix
enghitalo aba129c
remove C.accept
enghitalo 37a3beb
doc
enghitalo 4907eee
remove tiny_bad_request_d
enghitalo 39e9b88
reorder const
enghitalo 9473c91
fix windows CI
enghitalo ceb336f
finish
enghitalo 6787995
Apply suggestion from @spytheman
spytheman e128a02
move .v files to top level, fix README.md description
spytheman 141e0bf
Apply suggestion from @spytheman
spytheman ac8a858
Apply suggestion from @spytheman
spytheman 7b67511
fix: veb minor changes
enghitalo e2024c0
fix: veb minor changes
enghitalo 113533d
Merge remote-tracking branch 'upstream/master' into fix/fasthttp
enghitalo 5d2115f
clean up and remove global
enghitalo fd1128a
fix: parse_request_head
enghitalo bd239bb
test
enghitalo fb6770a
test: compile
enghitalo 06d19a8
fix: user_data support
enghitalo 6b7e4fd
fix: vlib/fasthttp/fasthttp_darwin.v
enghitalo File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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() | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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}') } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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' | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.