Skip to content

Request & Response

Request

Request is defined in src/request/mod.rs:

pub struct Request {
pub method: String, // "GET", "POST", etc.
pub request_uri: String, // "/search?q=rust"
pub http_version: String, // "HTTP/1.1"
pub headers: Vec<Header>,
pub body: Vec<u8>, // raw bytes
}

METHOD constants

Compare request.method against the METHOD constant instead of string literals:

use rust_web_server::request::{METHOD, Request};
fn is_get(request: &Request) -> bool {
request.method == METHOD.get
}

Available fields: METHOD.get, METHOD.head, METHOD.post, METHOD.put, METHOD.delete, METHOD.connect, METHOD.options, METHOD.trace, METHOD.patch.

Helper methods

// Parse the query string into a HashMap<String, String>
let query: Option<HashMap<String, String>> = request.get_query().unwrap();
// Extract just the path, stripping the query string
let path: String = request.get_path().unwrap();
// Get a specific header (case-insensitive)
let content_type: Option<&Header> = request.get_header("Content-Type".to_string());
// Extract the Host header's domain component
let domain: Option<String> = request.get_domain().unwrap();

Response

Response is defined in src/response/mod.rs:

pub struct Response {
pub http_version: String, // "HTTP/1.1"
pub status_code: i16, // 200, 404, etc.
pub reason_phrase: String, // "OK", "Not Found", etc.
pub headers: Vec<Header>,
pub content_range_list: Vec<ContentRange>, // response body parts
pub stream_file: Option<String>, // absolute path for chunked file streaming
}

Building a response with get_response

The most concise way to build a response:

use rust_web_server::response::{Response, STATUS_CODE_REASON_PHRASE};
use rust_web_server::header::Header;
use rust_web_server::range::Range;
use rust_web_server::mime_type::MimeType;
let body = Range::get_content_range(
b"{\"ok\":true}".to_vec(),
MimeType::APPLICATION_JSON.to_string(),
);
let response = Response::get_response(
STATUS_CODE_REASON_PHRASE.n200_ok,
Some(Header::get_header_list(request)), // standard response headers
Some(vec![body]),
);

Response::get_response signature:

pub fn get_response(
status_code_reason_phrase: &StatusCodeReasonPhrase,
boxed_header_list: Option<Vec<Header>>,
boxed_content_range_list: Option<Vec<ContentRange>>,
) -> Response

Pass None for headers to get an empty header list. Pass None for the body list to get an empty body (useful for 204 No Content).

Streaming large files

For files larger than ~8 MB, set stream_file instead of loading bytes into content_range_list. The server uses Transfer-Encoding: chunked and a constant memory footprint:

response.stream_file = Some("/var/data/large-export.csv".to_string());

STATUS_CODE_REASON_PHRASE constants

The STATUS_CODE_REASON_PHRASE constant provides typed access to every standard HTTP status code:

use rust_web_server::response::STATUS_CODE_REASON_PHRASE;
STATUS_CODE_REASON_PHRASE.n200_ok
STATUS_CODE_REASON_PHRASE.n201_created
STATUS_CODE_REASON_PHRASE.n204_no_content
STATUS_CODE_REASON_PHRASE.n400_bad_request
STATUS_CODE_REASON_PHRASE.n401_unauthorized
STATUS_CODE_REASON_PHRASE.n403_forbidden
STATUS_CODE_REASON_PHRASE.n404_not_found
STATUS_CODE_REASON_PHRASE.n409_conflict
STATUS_CODE_REASON_PHRASE.n422_unprocessable_entity
STATUS_CODE_REASON_PHRASE.n429_too_many_requests
STATUS_CODE_REASON_PHRASE.n500_internal_server_error
// ... and all other 1xx–5xx codes

Each entry has .status_code: &'static i16 and .reason_phrase: &'static str. Set them on a response:

response.status_code = *STATUS_CODE_REASON_PHRASE.n201_created.status_code;
response.reason_phrase = STATUS_CODE_REASON_PHRASE.n201_created.reason_phrase.to_string();

Header constants

Header in src/header/mod.rs exposes string constants for all standard HTTP header names:

use rust_web_server::header::Header;
Header::_CONTENT_TYPE // "Content-Type"
Header::_CONTENT_LENGTH // "Content-Length"
Header::_CONTENT_RANGE // "Content-Range"
Header::_AUTHORIZATION // "Authorization"
Header::_CACHE_CONTROL // "Cache-Control"
Header::_LOCATION // "Location"
Header::_SET_COOKIE // "Set-Cookie"
Header::_X_FORWARDED_FOR // "X-Forwarded-For"
// ... all standard request and response headers

Create a header value pair:

use rust_web_server::header::Header;
let location = Header {
name: Header::_LOCATION.to_string(),
value: "/new-path".to_string(),
};
response.headers.push(location);

get_header_list

Header::get_header_list(request) returns the standard set of response headers (CORS, cache control, security headers, client hints) pre-populated from the request context. Call it at the start of a controller’s process method when building a response from scratch:

let mut header_list = Header::get_header_list(request);
header_list.push(Header {
name: Header::_CACHE_CONTROL.to_string(),
value: "no-store".to_string(),
});

MimeType constants

MimeType in src/mime_type/mod.rs provides string constants for common content types:

use rust_web_server::mime_type::MimeType;
MimeType::APPLICATION_JSON // "application/json"
MimeType::APPLICATION_OCTET_STREAM // "application/octet-stream"
MimeType::TEXT_PLAIN // "text/plain"
MimeType::TEXT_HTML // "text/html"
MimeType::TEXT_CSS // "text/css"
MimeType::TEXT_JAVASCRIPT // "text/javascript"
// ... and many more

Use MimeType::detect_mime_type(filepath) to derive the MIME type from a file extension at runtime.

Range::get_content_range

Wrap any Vec<u8> in a ContentRange for use in response.content_range_list:

use rust_web_server::range::Range;
use rust_web_server::mime_type::MimeType;
let body = Range::get_content_range(
serde_json::to_vec(&payload).unwrap(),
MimeType::APPLICATION_JSON.to_string(),
);
response.content_range_list = vec![body];

For multipart range responses (e.g. Accept-Ranges support), push multiple ContentRange values into the list. The framework serialises them as multipart/byteranges automatically.