To implement file upload handling in Kito, we need to add multipart/form-data parsing support to the Rust core, expose the API in TypeScript, and maintain compatibility with the existing system.
Files to Modify
1. Core Rust - Request Parsing
packages/core/src/http/request.rs
- Add
UploadedFile structure to represent uploaded files
- Modify
RequestCore to include files field
- Implement multipart/form-data parser
// New structure for files
pub struct UploadedFile {
pub filename: String,
pub content_type: String,
pub size: usize,
pub data: Bytes,
}
// Modify RequestCore
pub struct RequestCore {
// ... existing fields ...
pub files: HashMap<String, UploadedFile>,
pub multipart_boundary: Option<String>,
}
2. Core Rust - Multipart Parser
New file: packages/core/src/http/multipart.rs
pub struct MultipartParser {
boundary: String,
data: Bytes,
}
impl MultipartParser {
pub fn new(boundary: String, data: Bytes) -> Self { ... }
pub fn parse(&mut self) -> Result<(HashMap<String, String>, HashMap<String, UploadedFile>), MultipartError> { ... }
}
pub enum MultipartError {
InvalidBoundary,
InvalidFormat,
IoError(std::io::Error),
}
3. TypeScript Types
packages/types/src/http/request.d.ts
export interface UploadedFile {
filename: string;
contentType: string;
size: number;
data: Buffer;
}
export interface RequestFiles {
[fieldName: string]: UploadedFile | UploadedFile[];
}
// Modify KitoRequest
export interface KitoRequest {
// ... existing properties ...
files?: RequestFiles;
}
4. Request Builder TypeScript
packages/kitojs/src/server/request.ts
- Add cache for files
- Implement getter for
files
- Import new N-API functions
export class RequestBuilder implements KitoRequest {
// ... existing fields ...
private _files?: Record<string, UploadedFile | UploadedFile[]>;
get files(): Record<string, UploadedFile | UploadedFile[]> | undefined {
if (!this._files) {
this._files = getAllFiles(this.core);
}
return this._files;
}
}
5. N-API Bindings
packages/core/src/lib.rs
- Expose new functions for file access
#[napi]
pub fn get_all_files(req: &RequestCore) -> HashMap<String, UploadedFile> { ... }
#[napi]
pub fn get_file(req: &RequestCore, name: String) -> Option<UploadedFile> { ... }
Implementation Details
Multipart Parser in Rust
The parser must:
- Identify boundary from
Content-Type header
- Split body into parts using boundary
- Parse headers for each part (Content-Disposition, Content-Type)
- Extract binary data for files
- Handle multiple files per field
Integration with RequestCore
In RequestCore::new() 1 :
// After parsing body
if let Some(content_type) = headers_raw.get("content-type") {
if content_type.starts_with("multipart/form-data") {
if let Some(boundary) = extract_boundary(content_type) {
let mut parser = MultipartParser::new(boundary, body.clone());
match parser.parse() {
Ok((fields, files)) => {
// Merge fields with query_raw if needed
self.files = files;
}
Err(e) => return Err(RequestError::MultipartError(e)),
}
}
}
}
Validation Middleware
Optionally, add middleware for file validation:
New file: packages/kitojs/src/helpers/fileValidator.ts
export interface FileValidationOptions {
maxSize?: number;
allowedTypes?: string[];
required?: boolean;
}
export function validateFiles(options: FileValidationOptions) {
return middleware((ctx, next) => {
// Validation logic
});
}
Usage Example
import { server } from 'kitojs';
const app = server();
app.post('/upload', async (ctx) => {
const files = ctx.req.files;
if (files?.avatar) {
const avatar = Array.isArray(files.avatar) ? files.avatar[0] : files.avatar;
console.log(`File received: ${avatar.filename} (${avatar.size} bytes)`);
// Save file, process, etc.
await saveFile(avatar.data, avatar.filename);
}
ctx.res.json({ success: true });
});
app.listen(3000);
Considerations
Security
- Validate maximum file size
- Verify allowed content types
- Sanitize filenames
Performance
- Streaming for large files
- Memory limit for parsing
- Option to write files directly to disk
Compatibility
- Maintain backward compatibility
- Don't affect parsing of other content-types
- Integrate with existing validation system
To implement file upload handling in Kito, we need to add
multipart/form-dataparsing support to the Rust core, expose the API in TypeScript, and maintain compatibility with the existing system.Files to Modify
1. Core Rust - Request Parsing
packages/core/src/http/request.rsUploadedFilestructure to represent uploaded filesRequestCoreto includefilesfield2. Core Rust - Multipart Parser
New file:
packages/core/src/http/multipart.rs3. TypeScript Types
packages/types/src/http/request.d.ts4. Request Builder TypeScript
packages/kitojs/src/server/request.tsfiles5. N-API Bindings
packages/core/src/lib.rsImplementation Details
Multipart Parser in Rust
The parser must:
Content-TypeheaderIntegration with RequestCore
In
RequestCore::new()1 :Validation Middleware
Optionally, add middleware for file validation:
New file:
packages/kitojs/src/helpers/fileValidator.tsUsage Example
Considerations
Security
Performance
Compatibility