References Getting Started Getting Started Architecture Architecture Application Application Window Window WebView WebView Deployment Deployment Components Components Framework Integrations Framework Integrations Examples Examples Community Community github GitHub github Get Started arrow_up_right
Getting Started Getting Started Architecture Architecture Application Application Window Window WebView WebView Deployment Deployment Components Components Framework Integrations Framework Integrations Examples Examples Community Community

Components

HTTP URI HTTP Body Decoder HTTP Static Provider PHP Globals Provider OS Info CPU Info Assembly Weak Types Getting Started Architecture Application Window WebView Deployment Components Framework Integrations Examples Community

HTTP

The component provides a set of HTTP structures that provide information about requests, responses, and their dependencies.

This component already included in the boson-php/runtime, so no separate installation is required when using the runtime.

Installation

Via Composer:

composer require boson-php/http

Requirements:

  • PHP ^8.4

Request

The Request class represents an immutable HTTP request:

use Boson\Component\Http\Request;

// Create a new request with default values
$request = new Request();

// Create a custom request
$request = new Request(
    method: 'POST',
    url: 'https://example.com/api/users',
    headers: [
        'content-type' => 'application/json',
        'authorization' => 'Bearer token123'
    ],
    body: '{"name": "John", "age": 30}'
);

All properties are immutable and can only be accessed, not modified.

All request objects are created by the Boson itself within events, such as SchemeRequestReceived. Therefore, to ensure that the object within an event or intention will NOT be changed and all listeners receive identical information, the request object is immutable.

$app->on(function (SchemeRequestReceived $e): void {
    $request = $e->request;

    echo $request->url;
    echo $request->method;
    // etc.
});

Response

The Response class represents a mutable HTTP response:

use Boson\Component\Http\Response;

// Create a new response with default values
$response = new Response();

// Create a custom response
$response = new Response(
    body: '<h1>Hello World</h1>',
    headers: [
        'content-type' => 'text/html',
        'x-custom-header' => 'value'
    ],
    status: 200
);

// Modify response
$response->headers->add('x-new-header', 'new value');
$response->body = 'New content';
$response->status = 201;

All responses are created by developer in any form. Therefore, for convenience, they are made mutable by default.

$app->on(function (SchemeRequestReceived $e): void {
    $e->response = new Response('hello!');
    $e->response->status = 404;
});

Headers

Both request and response use the HeadersMap class for header management. To get a list of headers, use the headers property in HTTP objects (for example, $request->headers or $response->headers).

The request contains an immutable HeadersMap object which provides methods for reading header information.

// Check if header exists
if ($request->headers->has('content-type')) {
    // Get header value
    $contentType = $request->headers->first('content-type');
}

While the response contains a mutable implementation of the list of MutableHeadersMap headers which represents not only methods of obtaining information, but also its modifications.

// Add new header
if (!$response->headers->has('x-custom-header')) {
    $response->headers->add('x-custom-header', 'value');
}

// Remove header
$response->headers->remove('content-type');

The headers map is case-insensitive (lowercased) for header names

Header Line by Name

To obtain a specific header's value, you can use the first() method.

$type = $request->headers->first('content-type'); // null or string

// The name's case does not affect the result
$type = $request->headers->first('Content-Type'); // null or string

If the specified header is missing, the null value will be returned. You can pass a second argument to specify a default value.

$type = $request->headers->first('content-type', 'text/html');

// The "$type" will contain expected value
// from headers or "text/html"

All Headers by Name

The HTTP specification allows for multiple headers with the same name to be specified. Although this is a rare case, in those cases where this is needed you can get all the passed header values with the specified name.

$values = $request->headers->all('x-example-header');

//
// If headers were passed
//
//  X-Example-Header: 23
//  X-Example-Header: 42
//
// The "$values" will be
//
//  array:2 [
//    0 => "23"
//    1 => "42"
//  ]
//

Existence Check

To check the existence of the specified header (whether it was passed), you should use the has() method.

if ($request->headers->has('upgrade')) {
    throw new LogicException('HTTP/2 disallows the use of this header');
}

Value Existence Check

To check that a header with the specified value was passed, you can use the contains() method.

if (! $request->headers->contains('content-type', 'application/json')) {
    throw new LogicException('Only JSON requests are available');
}

Method

HTTP defines a set of request methods to indicate the purpose of the request and what is expected if the request is successful. Although they can also be nouns, these request methods are sometimes referred to as HTTP verbs. Each request method has its own semantics, but some characteristics are shared across multiple methods, specifically request methods can be safe, idempotent, or cacheable.

The HTTP request`s method can be represented and set as a string, but it implements a full-fledged enum-like value object containing a lot of additional information.

use Boson\Component\Http\Request;

// A string may be used during instantiation.
$request = new Request(method: 'GET');

// The method can be output as a string
echo $request->method; 

//
// Expected Output:
//
//  GET
//

Method Class

Methods are part of the request, but you can use them separately. For this, Boson component provides an enum-like Boson\Component\Http\Component\Method class containing a set of known HTTP cases:

Since the Method class implements behavior similar to PHP enums, you also have access to the from(), tryFrom() and cases() methods.

Due to many technical limitations of the PHP (for example, unable to use properties, unable to define the __toString() method, unable to override from() & tryFrom() methods, etc.), this class cannot be implemented using the classic PHP enum.

use Boson\Component\Http\Component\Method;

echo Method::from('get');
// GET

echo Method::from('wtf');
// Uncaught ValueError: "wtf" is not a valid backing value for
// enum-like Boson\Component\Http\Component\Method

echo Method::tryFrom('wtf'); 
// null

Please note that the from() and tryFrom() methods are case-insensitive. Method value will be uppercased.

use Boson\Component\Http\Component\Method;

foreach (Method::cases() as $method) {
    echo $method . "\n";
}

//
// Expected Output:
//
//   GET
//   HEAD
//   OPTIONS
//   TRACE
//   PUT
//   DELETE
//   POST
//   PATCH
//   CONNECT
//

Method Name

To get the name of the HTTP method, you can use the read-only name property.

Method name is case-insensitive and always converted to uppercase. For example, if you write "get" or "post", then the method name will always be GET or POST.

use Boson\Component\Http\Request;

$request = new Request(method: 'get');

echo $request->method->name; // GET

Method Idempotency

An HTTP method is idempotent if the intended effect on the server of making a single request is the same as the effect of making several identical requests.

For example, the HTTP specification defines several HTTP methods and their semantics, which includes whether they are idempotent or not. All safe methods are idempotent, as well as PUT and DELETE. The POST and PATCH methods are not guaranteed to be idempotent.

In any case, you don't need to remember by heart which HTTP methods are idempotent, it is enough to use the isIdempotent property to get this information.

$get = new Request(method: 'get');

if ($get->method->isIdempotent) {
    echo 'GET is idempotent';
}

$post = new Request(method: 'post');

if ($post->method->isIdempotent) {
    echo 'POST is idempotent';
}

//
// Expected Output:
//
//  GET is idempotent
//

Method Safety

An HTTP method is safe if it doesn't alter the state of the server. In other words, a method is safe if it leads to a read-only operation. Several common HTTP methods are safe: GET, HEAD, or OPTIONS. All safe methods are also idempotent, but not all idempotent methods are safe. For example, PUT and DELETE are both idempotent but unsafe.

To get information about the methods safety you can use the isSafe property.

use Boson\Component\Http\Request;

$get = new Request(method: 'get');

if ($get->method->isSafe) {
    echo 'GET is safe';
}

$post = new Request(method: 'post');

if ($post->method->isSafe) {
    echo 'POST is safe';
}

//
// Expected Output:
//
//  GET is safe
//

User Defined Method

In addition to the basic HTTP methods, you may need to create your own non-HTTP method. This is a rare task, but it can happen.

To do this, you should create an instance of the Method object.

use Boson\Component\Http\Component\Method;

echo new Method('PROPFIND'); // PROPFIND

The Methods constructor is case-sensitive. Name will be uppercased.

Note that the safety and idempotency properties for such methods are undefined.

use Boson\Component\Http\Component\Method;

$method = new Method('PROPFIND');

$method->isSafe;        // null
$method->isIdempotent;  // null

You should specify them explicitly if you want to provide this information.

use Boson\Component\Http\Component\Method;

$method = new Method(
    name: 'PROPFIND',
    isIdempotent: true,
    isSafe: false,
);

$method->isSafe;        // false
$method->isIdempotent;  // true

Method Comparison

You can use the strict comparison Method objects, but if the objects are different, the result will be a false although technically both objects implement an identical HTTP method.

use Boson\Component\Http\Component\Method;

Method::Get === new Method('GET'); // false

To compare methods by meaning, even if the implementations may differ, there is the equals() method, which guarantees true if the HTTP methods are identical, even if they implement different objects.

use Boson\Component\Http\Component\Method;

new Method('GET')->equals(Method::Get);  // true

new Method('POST')->equals(Method::Get); // false

Status Code

HTTP response status codes indicate whether a specific HTTP request has been successfully completed.

To get information about the status code, use the status property of the response object.

use Boson\Component\Http\Response;

echo new Response(status: 200)
    ->status;

//
// Expected Output:
//
//  200 OK
//

echo new Response(status: 418)
    ->status;

//
// Expected Output:
//
//  418 I’m A Teapot
//

Status Code Class

Status codes are part of the response, but you can use them separately. For this, Boson component provides an enum-like Boson\Component\Http\Component\StatusCode class containing a set of known HTTP cases:

  • StatusCode::Continue – 100 Continue
  • StatusCode::SwitchingProtocols – 101 Switching Protocols
  • StatusCode::Processing – 102 Processing
  • StatusCode::EarlyHints – 103 Early Hints
  • StatusCode::ResponseIsStale – 110 Response Is Stale
  • StatusCode::RevalidationFailed – 111 Revalidation Failed
  • StatusCode::DisconnectedOperation – 112 Disconnected Operation
  • StatusCode::HeuristicExpiration – 113 Heuristic Expiration
  • StatusCode::MiscellaneousWarning – 199 Miscellaneous Warning
  • StatusCode::Ok – 200 OK
  • StatusCode::Created – 201 Created
  • StatusCode::Accepted – 202 Accepted
  • StatusCode::NonAuthoritativeInformation – 203 Non-Authoritative Information
  • StatusCode::NoContent – 204 No Content
  • StatusCode::ResetContent – 205 Reset Content
  • StatusCode::PartialContent – 206 Partial Content
  • StatusCode::MultiStatus – 207 Multi-Status
  • StatusCode::AlreadyReported – 208 Already Reported
  • StatusCode::TransformationApplied – 214 Transformation Applied
  • StatusCode::ImUsed – 226 IM Used
  • StatusCode::MiscellaneousPersistentWarning – 299 Miscellaneous Persistent Warnin
  • StatusCode::MultipleChoices – 300 Multiple Choices
  • StatusCode::MovedPermanently – 301 Moved Permanently
  • StatusCode::Found – 302 Found
  • StatusCode::SeeOther – 303 See Other
  • StatusCode::NotModified – 304 Not Modified
  • StatusCode::UseProxy – 305 Use Proxy
  • StatusCode::Unused – 306 Unused
  • StatusCode::TemporaryRedirect – 307 Temporary Redirect
  • StatusCode::PermanentRedirect – 308 Permanent Redirect
  • StatusCode::BadRequest – 400 Bad Request
  • StatusCode::Unauthorized – 401 Unauthorized
  • StatusCode::PaymentRequired – 402 Payment Required
  • StatusCode::Forbidden – 403 Forbidden
  • StatusCode::NotFound – 404 Not Found
  • StatusCode::MethodNotAllowed – 405 Method Not Allowed
  • StatusCode::NotAcceptable – 406 Not Acceptable
  • StatusCode::ProxyAuthenticationRequired – 407 Proxy Authentication Required
  • StatusCode::RequestTimeout – 408 Request Timeout
  • StatusCode::Conflict – 409 Conflict
  • StatusCode::Gone – 410 Gone
  • StatusCode::LengthRequired – 411 Length Required
  • StatusCode::PreconditionFailed – 412 Precondition Failed
  • StatusCode::PayloadTooLarge – 413 Payload Too Large
  • StatusCode::UriTooLong – 414 URI Too Long
  • StatusCode::UnsupportedMediaType – 415 Unsupported Media Type
  • StatusCode::RangeNotSatisfiable – 416 Range Not Satisfiable
  • StatusCode::ExpectationFailed – 417 Expectation Failed
  • StatusCode::ImATeapot – 418 I’m A Teapot
  • StatusCode::MisdirectedRequest – 421 Misdirected Request
  • StatusCode::UnprocessableEntity – 422 Unprocessable Entity
  • StatusCode::EntityLocked – 423 Locked
  • StatusCode::FailedDependency – 424 Failed Dependency
  • StatusCode::HttpTooEarly – 425 Too Early
  • StatusCode::UpgradeRequired – 426 Upgrade Required
  • StatusCode::PreconditionRequired – 428 Precondition Required
  • StatusCode::TooManyRequests – 429 Too Many Requests
  • StatusCode::RequestHeaderFieldsTooLarge – 431 Request Header Fields Too Large
  • StatusCode::Close – 444 No Response
  • StatusCode::UnavailableForLegalReasons – 451 Unavailable For Legal Reasons
  • StatusCode::ClientClosedRequest – 499 Client Closed Request
  • StatusCode::InternalServerError – 500 Internal Server Error
  • StatusCode::NotImplemented – 501 Not Implemented
  • StatusCode::BadGateway – 502 Bad Gateway
  • StatusCode::ServiceUnavailable – 503 Service Unavailable
  • StatusCode::GatewayTimeout – 504 Gateway Timeout
  • StatusCode::HttpVersionNotSupported – 505 HTTP Version Not Supported
  • StatusCode::HttpVariantAlsoNegotiates – 506 Variant Also Negotiates
  • StatusCode::HttpInsufficientStorage – 507 Insufficient Storage
  • StatusCode::HttpLoopDetected – 508 Loop Detected
  • StatusCode::HttpNotExtended – 510 Not Extended
  • StatusCode::HttpNetworkAuthenticationRequired – 511 Network Authentication Required
  • StatusCode::NetworkConnectTimeout – 599 Network Connect Timeout Error

Since the StatusCode class implements behavior similar to PHP enums, you also have access to the from(), tryFrom() and cases() methods.

Due to many technical limitations of the PHP (for example, unable to use properties, unable to define the __toString() method, unable to override from() & tryFrom() methods, etc.), this class cannot be implemented using the classic PHP enum.

use Boson\Component\Http\Component\Method;

echo StatusCode::from(418);
// 418 I’m A Teapot

echo StatusCode::from(42);
// Uncaught ValueError: "42" is not a valid backing value for
// enum-like Boson\Component\Http\Component\StatusCode

echo StatusCode::tryFrom(42); 
// null

To obtain a list of known HTTP codes, you can use the cases() method.

use Boson\Component\Http\Component\StatusCode;

foreach (StatusCode::cases() as $status) {
    echo $status . "\n";
}

//
// Expected Output:
//
//   100 Continue
//   101 Switching Protocols
//   102 Processing
//   103 Early Hints
//   110 Response Is Stale
//   111 Revalidation Failed
//   112 Disconnected Operation
//   113 Heuristic Expiration
//   ...etc.
//

Status Codes and Messages

As with the method, the status code is a value object. The status code instance contains information about the response code and message.

use Boson\Component\Http\Response;

$response = new Response(status: 418);

echo 'Code: ' . $response->status->code;
echo 'Message: ' . $response->status->reason;

//
// Expected Output:
//
//  Code: 418
//  Message: I’m A Teapot
//

Status Categories

Responses are grouped in five categories:

  • Informational responses (100199)
  • Successful responses (200299)
  • Redirection messages (300399)
  • Client error responses (400499)
  • Server error responses (500599)

To get information about category of the status, you can use the category property.

$response = new Response(status: 418);

echo $response->status->category;

//
// Expected Output:
//
//  Client Error
//

User Defined Status

In some cases you may need to define your own status code. To do this, you should create an instance of the StatusCode class.

The status code message is optional.

use Boson\Component\Http\Component\StatusCode;

echo new StatusCode(1001, 'DNS Resolution Error');

//
// Expected Output:
//
//   1001 DNS Resolution Error
//

Status Comparison

You can use the strict comparison StatusCode objects, but if the objects are different, the result will be a false although technically both objects implement an identical HTTP status code.

use Boson\Component\Http\Component\StatusCode;

StatusCode::NotFound === new StatusCode(404); // false

To compare status codes by meaning, even if the implementations may differ, there is the equals() method, which guarantees true if the HTTP status codes are identical, even if they implement different objects.

use Boson\Component\Http\Component\StatusCode;

new StatusCode(404)->equals(StatusCode::NotFound);  // true

new StatusCode(500)->equals(StatusCode::NotFound); // false

JSON Response

The JsonResponse class extends Response to provide JSON-specific functionality:

use Boson\Component\Http\JsonResponse;

// Create a JSON response with default values
$response = new JsonResponse();

// Create a custom JSON response
$response = new JsonResponse(
    data: ['name' => 'John', 'age' => 30],
    headers: ['x-custom-header' => 'value'],
    status: 200
);

// Create a JSON response with custom encoding flags
$response = new JsonResponse(
    data: ['name' => 'John', 'age' => 30],
    jsonEncodingFlags: JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE
);
github discord telegram Get started Documentation Contribution Guide License Release Notes BOSON PHP © 2025. All Rights Reversed.