{"id":14965399,"url":"https://github.com/nette/http","last_synced_at":"2025-05-14T00:08:47.981Z","repository":{"id":14969103,"uuid":"17694028","full_name":"nette/http","owner":"nette","description":"🌐 Abstraction for HTTP request, response and session. Provides careful data sanitization and utility for URL and cookies manipulation.","archived":false,"fork":false,"pushed_at":"2025-03-31T00:31:34.000Z","size":1311,"stargazers_count":465,"open_issues_count":32,"forks_count":88,"subscribers_count":35,"default_branch":"master","last_synced_at":"2025-04-10T13:11:11.441Z","etag":null,"topics":["http","nette","nette-framework","php"],"latest_commit_sha":null,"homepage":"https://doc.nette.org/http-request-response","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nette.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"license.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"dg","custom":"https://nette.org/donate"}},"created_at":"2014-03-13T03:46:16.000Z","updated_at":"2025-03-31T00:31:38.000Z","dependencies_parsed_at":"2023-02-15T02:31:03.985Z","dependency_job_id":"8db18859-04a4-427f-b5fe-75bbb0f72d52","html_url":"https://github.com/nette/http","commit_stats":{"total_commits":850,"total_committers":71,"mean_commits":"11.971830985915492","dds":0.1741176470588235,"last_synced_commit":"afdd2e1d49a445f4c528ddb96167e3865a99b27b"},"previous_names":[],"tags_count":58,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nette%2Fhttp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nette%2Fhttp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nette%2Fhttp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nette%2Fhttp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nette","download_url":"https://codeload.github.com/nette/http/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254044031,"owners_count":22005063,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["http","nette","nette-framework","php"],"created_at":"2024-09-24T13:34:41.805Z","updated_at":"2025-05-14T00:08:42.972Z","avatar_url":"https://github.com/nette.png","language":"PHP","readme":"Nette HTTP Component\n====================\n\n[![Downloads this Month](https://img.shields.io/packagist/dm/nette/http.svg)](https://packagist.org/packages/nette/http)\n[![Tests](https://github.com/nette/http/workflows/Tests/badge.svg?branch=master)](https://github.com/nette/http/actions)\n[![Build Status Windows](https://ci.appveyor.com/api/projects/status/github/nette/http?branch=master\u0026svg=true)](https://ci.appveyor.com/project/dg/http/branch/master)\n[![Coverage Status](https://coveralls.io/repos/github/nette/http/badge.svg?branch=master)](https://coveralls.io/github/nette/http?branch=master)\n[![Latest Stable Version](https://poser.pugx.org/nette/http/v/stable)](https://github.com/nette/http/releases)\n[![License](https://img.shields.io/badge/license-New%20BSD-blue.svg)](https://github.com/nette/http/blob/master/license.md)\n\n\nIntroduction\n------------\n\nHTTP request and response are encapsulated in `Nette\\Http\\Request` and `Nette\\Http\\Response` objects which offer comfortable API and also act as\nsanitization filter.\n\nDocumentation can be found on the [website](https://doc.nette.org/http-request-response).\n\n\n[Support Me](https://github.com/sponsors/dg)\n--------------------------------------------\n\nDo you like Nette DI? Are you looking forward to the new features?\n\n[![Buy me a coffee](https://files.nette.org/icons/donation-3.svg)](https://github.com/sponsors/dg)\n\nThank you!\n\n\nInstallation\n------------\n\n```shell\ncomposer require nette/http\n```\n\nIt requires PHP version 8.1 and supports PHP up to 8.4.\n\n\nHTTP Request\n============\n\nAn HTTP request is an [Nette\\Http\\Request](https://api.nette.org/3.0/Nette/Http/Request.html) object. What is important is that Nette when [creating](#RequestFactory) this object, it clears all GET, POST and COOKIE input parameters as well as URLs of control characters and invalid UTF-8 sequences. So you can safely continue working with the data. The cleaned data is then used in presenters and forms.\n\nClass `Request` is immutable. It has no setters, it has only one so-called wither `withUrl()`, which does not change the object, but returns a new instance with a modified value.\n\n\nwithUrl(Nette\\Http\\UrlScript $url): Nette\\Http\\Request\n------------------------------------------------------\nReturns a clone with a different URL.\n\ngetUrl(): Nette\\Http\\UrlScript\n------------------------------\nReturns the URL of the request as object [UrlScript|urls#UrlScript].\n\n```php\n$url = $httpRequest-\u003egetUrl();\necho $url; // https://nette.org/en/documentation?action=edit\necho $url-\u003egetHost(); // nette.org\n```\n\nBrowsers do not send a fragment to the server, so `$url-\u003egetFragment()` will return an empty string.\n\ngetQuery(string $key = null): string|array|null\n-----------------------------------------------\nReturns GET request parameters:\n\n```php\n$all = $httpRequest-\u003egetQuery();    // array of all URL parameters\n$id = $httpRequest-\u003egetQuery('id'); // returns GET parameter 'id' (or null)\n```\n\ngetPost(string $key = null): string|array|null\n----------------------------------------------\nReturns POST request parameters:\n\n```php\n$all = $httpRequest-\u003egetPost();     // array of all POST parameters\n$id = $httpRequest-\u003egetPost('id');  // returns POST parameter 'id' (or null)\n```\n\ngetFile(string $key): Nette\\Http\\FileUpload|array|null\n------------------------------------------------------\nReturns [upload](#Uploaded-Files) as object [Nette\\Http\\FileUpload](https://api.nette.org/3.0/Nette/Http/FileUpload.html):\n\n```php\n$file = $httpRequest-\u003egetFile('avatar');\nif ($file-\u003ehasFile()) { // was any file uploaded?\n\t$file-\u003egetName(); // name of the file sent by user\n\t$file-\u003egetSanitizedName(); // the name without dangerous characters\n}\n```\n\ngetFiles(): array\n-----------------\nReturns tree of [upload files](#Uploaded-Files) in a normalized structure, with each leaf an instance of [Nette\\Http\\FileUpload](https://api.nette.org/3.0/Nette/Http/FileUpload.html):\n\n```php\n$files = $httpRequest-\u003egetFiles();\n```\n\ngetCookie(string $key): string|array|null\n-----------------------------------------\nReturns a cookie or `null` if it does not exist.\n\n```php\n$sessId = $httpRequest-\u003egetCookie('sess_id');\n```\n\ngetCookies(): array\n-------------------\nReturns all cookies:\n\n```php\n$cookies = $httpRequest-\u003egetCookies();\n```\n\ngetMethod(): string\n-------------------\nReturns the HTTP method with which the request was made.\n\n```php\necho $httpRequest-\u003egetMethod(); // GET, POST, HEAD, PUT\n```\n\nisMethod(string $method): bool\n------------------------------\nChecks the HTTP method with which the request was made. The parameter is case-insensitive.\n\n```php\nif ($httpRequest-\u003eisMethod('GET')) ...\n```\n\ngetHeader(string $header): ?string\n----------------------------------\nReturns an HTTP header or `null` if it does not exist. The parameter is case-insensitive:\n\n```php\n$userAgent = $httpRequest-\u003egetHeader('User-Agent');\n```\n\ngetHeaders(): array\n-------------------\nReturns all HTTP headers as associative array:\n\n```php\n$headers = $httpRequest-\u003egetHeaders();\necho $headers['Content-Type'];\n```\n\ngetReferer(): ?Nette\\Http\\UrlImmutable\n--------------------------------------\nWhat URL did the user come from? Beware, it is not reliable at all.\n\nisSecured(): bool\n-----------------\nIs the connection encrypted (HTTPS)? You may need to [set up a proxy|configuring#HTTP proxy] for proper functionality.\n\nisSameSite(): bool\n------------------\nIs the request coming from the same (sub) domain and is initiated by clicking on a link?\n\nisAjax(): bool\n--------------\nIs it an AJAX request?\n\ngetRemoteAddress(): ?string\n---------------------------\nReturns the user's IP address. You may need to [set up a proxy|configuring#HTTP proxy] for proper functionality.\n\ngetRemoteHost(): ?string\n------------------------\nReturns DNS translation of the user's IP address. You may need to [set up a proxy|configuring#HTTP proxy] for proper functionality.\n\ngetRawBody(): ?string\n---------------------\nReturns the body of the HTTP request:\n\n```php\n$body = $httpRequest-\u003egetRawBody();\n```\n\ndetectLanguage(array $langs): ?string\n-------------------------------------\nDetects language. As a parameter `$lang`, we pass an array of languages ​​that the application supports, and it returns the one preferred by browser. It is not magic, the method just uses the `Accept-Language` header. If no match is reached, it returns `null`.\n\n```php\n// Header sent by browser: Accept-Language: cs,en-us;q=0.8,en;q=0.5,sl;q=0.3\n\n$langs = ['hu', 'pl', 'en']; // languages supported in application\necho $httpRequest-\u003edetectLanguage($langs); // en\n```\n\n\n\nRequestFactory\n--------------\n\nThe object of the current HTTP request is created by [Nette\\Http\\RequestFactory](https://api.nette.org/3.0/Nette/Http/RequestFactory.html). If you are writing an application that does not use a DI container, you create a request as follows:\n\n```php\n$factory = new Nette\\Http\\RequestFactory;\n$httpRequest = $factory-\u003efromGlobals();\n```\n\nRequestFactory can be configured before calling `fromGlobals()`. We can disable all sanitization of input parameters from invalid UTF-8 sequences using `$factory-\u003esetBinary()`. And also set up a proxy server, which is important for the correct detection of the user's IP address using `$factory-\u003esetProxy(...)`.\n\nIt's possible to clean up URLs from characters that can get into them because of poorly implemented comment systems on various other websites by using filters:\n\n```php\n// remove spaces from path\n$requestFactory-\u003eurlFilters['path']['%20'] = '';\n\n// remove dot, comma or right parenthesis form the end of the URL\n$requestFactory-\u003eurlFilters['url']['[.,)]$'] = '';\n\n// clean the path from duplicated slashes (default filter)\n$requestFactory-\u003eurlFilters['path']['/{2,}'] = '/';\n```\n\n\n\nHTTP Response\n=============\n\nAn HTTP response is an [Nette\\Http\\Response](https://api.nette.org/3.0/Nette/Http/Response.html) object. Unlike the [Request](#HTTP-Request), the object is mutable, so you can use setters to change the state, ie to send headers. Remember that all setters **must be called before any actual output is sent.** The `isSent()` method tells if output have been sent. If it returns `true`, each attempt to send a header throws an `Nette\\InvalidStateException` exception.\n\n\nsetCode(int $code, string $reason = null)\n-----------------------------------------\nChanges a status [response code](https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10). For better source code readability it is recommended to use [predefined constants](https://api.nette.org/3.0/Nette/Http/IResponse.html) instead of actual numbers.\n\n```php\n$httpResponse-\u003esetCode(Nette\\Http\\Response::S404_NotFound);\n```\n\ngetCode(): int\n--------------\nReturns the status code of the response.\n\nisSent(): bool\n--------------\nReturns whether headers have already been sent from the server to the browser, so it is no longer possible to send headers or change the status code.\n\nsetHeader(string $name, string $value)\n--------------------------------------\nSends an HTTP header and **overwrites** previously sent header of the same name.\n\n```php\n$httpResponse-\u003esetHeader('Pragma', 'no-cache');\n```\n\naddHeader(string $name, string $value)\n--------------------------------------\nSends an HTTP header and **doesn't overwrite** previously sent header of the same name.\n\n```php\n$httpResponse-\u003eaddHeader('Accept', 'application/json');\n$httpResponse-\u003eaddHeader('Accept', 'application/xml');\n```\n\ndeleteHeader(string $name)\n--------------------------\nDeletes a previously sent HTTP header.\n\ngetHeader(string $header): ?string\n----------------------------------\nReturns the sent HTTP header, or `null` if it does not exist. The parameter is case-insensitive.\n\n```php\n$pragma = $httpResponse-\u003egetHeader('Pragma');\n```\n\ngetHeaders(): array\n-------------------\nReturns all sent HTTP headers as associative array.\n\n```php\n$headers = $httpResponse-\u003egetHeaders();\necho $headers['Pragma'];\n```\n\nsetContentType(string $type, string $charset = null)\n----------------------------------------------------\nSends the header `Content-Type`.\n\n```php\n$httpResponse-\u003esetContentType('text/plain', 'UTF-8');\n```\n\nredirect(string $url, int $code = self::S302_FOUND): void\n---------------------------------------------------------\nRedirects to another URL. Don't forget to quit the script then.\n\n```php\n$httpResponse-\u003eredirect('http://example.com');\nexit;\n```\n\nsetExpiration(?string $time)\n----------------------------\nSets the expiration of the HTTP document using the `Cache-Control` and `Expires` headers. The parameter is either a time interval (as text) or `null`, which disables caching.\n\n```php\n// browser cache expires in one hour\n$httpResponse-\u003esetExpiration('1 hour');\n```\n\nsetCookie(string $name, string $value, string|int|\\DateTimeInterface|null $expire, string $path = null, string $domain = null, bool $secure = null, bool $httpOnly = null, string $sameSite = null)\n--------------------------------------------------------------------------------------------------------------------------------------------------------------\nSends a cookie. The default values ​​of the parameters are:\n- `$path` with scope to all directories (`'/'`)\n- `$domain` with scope of the current (sub)domain, but not its subdomains\n- `$secure` defaults to false\n- `$httpOnly` is true, so the cookie is inaccessible to JavaScript\n- `$sameSite` is null, so the flag is not specified\n\nThe `$expire` parameter can be specified as a string, an object implementing `DateTimeInterface`, or the number of seconds.\n\n```php\n$httpResponse-\u003esetCookie('lang', 'en', '100 days');\n```\n\ndeleteCookie(string $name, string $path = null, string $domain = null, bool $secure = null): void\n-------------------------------------------------------------------------------------------------\nDeletes a cookie. The default values ​​of the parameters are:\n- `$path` with scope to all directories (`'/'`)\n- `$domain` with scope of the current (sub)domain, but not its subdomains\n- `$secure` defaults to false\n\n```php\n$httpResponse-\u003edeleteCookie('lang');\n```\n\n\nUploaded Files\n==============\n\nMethod `Nette\\Http\\Request::getFiles()` return a tree of upload files in a normalized structure, with each leaf an instance of `Nette\\Http\\FileUpload`. These objects encapsulate the data submitted by the `\u003cinput type=file\u003e` form element.\n\nThe structure reflects the naming of elements in HTML. In the simplest example, this might be a single named form element submitted as:\n\n```html\n\u003cinput type=\"file\" name=\"avatar\"\u003e\n```\n\nIn this case, the `$request-\u003egetFiles()` returns array:\n\n```php\n[\n\t'avatar' =\u003e /* FileUpload instance */\n]\n```\n\nThe `FileUpload` object is created even if the user did not upload any file or the upload failed. Method `hasFile()` returns true if a file has been sent:\n\n```php\n$request-\u003egetFile('avatar')-\u003ehasFile();\n```\n\nIn the case of an input using array notation for the name:\n\n```html\n\u003cinput type=\"file\" name=\"my-form[details][avatar]\"\u003e\n```\n\nreturned tree ends up looking like this:\n\n```php\n[\n\t'my-form' =\u003e [\n\t\t'details' =\u003e [\n\t\t\t'avatar' =\u003e /* FileUpload instance */\n\t\t],\n\t],\n]\n```\n\nYou can also create arrays of files:\n\n```html\n\u003cinput type=\"file\" name=\"my-form[details][avatars][] multiple\"\u003e\n```\n\nIn such a case structure looks like:\n\n```php\n[\n\t'my-form' =\u003e [\n\t\t'details' =\u003e [\n\t\t\t'avatars' =\u003e [\n\t\t\t\t0 =\u003e /* FileUpload instance */,\n\t\t\t\t1 =\u003e /* FileUpload instance */,\n\t\t\t\t2 =\u003e /* FileUpload instance */,\n\t\t\t],\n\t\t],\n\t],\n]\n```\n\nThe best way to access index 1 of a nested array is as follows:\n\n```php\n$file = Nette\\Utils\\Arrays::get(\n\t$request-\u003egetFiles(),\n\t['my-form', 'details', 'avatars', 1],\n\tnull\n);\nif ($file instanceof FileUpload) {\n\t...\n}\n```\n\nBecause you can't trust data from the outside and therefore don't rely on the form of the file structure, it's safer to use the `Arrays::get()` than the `$request-\u003egetFiles()['my-form']['details']['avatars'][1]`, which may fail.\n\n\nOverview of `FileUpload` Methods .{toc: FileUpload}\n---------------------------------------------------\n\nhasFile(): bool\n---------------\nReturns `true` if the user has uploaded a file.\n\nisOk(): bool\n------------\nReturns `true` if the file was uploaded successfully.\n\ngetError(): int\n---------------\nReturns the error code associated with the uploaded file. It is be one of [UPLOAD_ERR_XXX](http://php.net/manual/en/features.file-upload.errors.php) constants. If the file was uploaded successfully, it returns `UPLOAD_ERR_OK`.\n\nmove(string $dest)\n------------------\nMoves an uploaded file to a new location. If the destination file already exists, it will be overwritten.\n\n```php\n$file-\u003emove('/path/to/files/name.ext');\n```\n\ngetContents(): ?string\n----------------------\nReturns the contents of the uploaded file. If the upload was not successful, it returns `null`.\n\ngetContentType(): ?string\n-------------------------\nDetects the MIME content type of the uploaded file based on its signature. If the upload was not successful or the detection failed, it returns `null`.\n\nRequires PHP extension `fileinfo`.\n\ngetName(): string\n-----------------\nReturns the original file name as submitted by the browser.\n\nDo not trust the value returned by this method. A client could send a malicious filename with the intention to corrupt or hack your application.\n\ngetSanitizedName(): string\n--------------------------\nReturns the sanitized file name. It contains only ASCII characters `[a-zA-Z0-9.-]`. If the name does not contain such characters, it returns 'unknown'. If the file is JPEG, PNG, GIF, or WebP image, it returns the correct file extension.\n\ngetSize(): int\n--------------\nReturns the size of the uploaded file. If the upload was not successful, it returns `0`.\n\ngetTemporaryFile(): string\n--------------------------\nReturns the path of the temporary location of the uploaded file. If the upload was not successful, it returns `''`.\n\nisImage(): bool\n---------------\nReturns `true` if the uploaded file is a JPEG, PNG, GIF, or WebP image. Detection is based on its signature. The integrity of the entire file is not checked. You can find out if an image is not corrupted for example by trying to [load it](#toImage).\n\nRequires PHP extension `fileinfo`.\n\ngetImageSize(): ?array\n----------------------\nReturns a pair of `[width, height]` with dimensions of the uploaded image. If the upload was not successful or is not a valid image, it returns `null`.\n\ntoImage(): Nette\\Utils\\Image\n----------------------------\nLoads an image as an `Image` object. If the upload was not successful or is not a valid image, it throws an `Nette\\Utils\\ImageException` exception.\n\n\n\nSessions\n========\n\nWhen using sessions, each user receives a unique identifier called session ID, which is passed in a cookie. This serves as the key to the session data. Unlike cookies, which are stored on the browser side, session data is stored on the server side.\n\nThe session is managed by the [Nette\\Http\\Session](https://api.nette.org/3.0/Nette/Http/Session.html) object.\n\n\nStarting Session\n----------------\n\nBy default, Nette automatically starts a session if the HTTP request contains a cookie with a session ID. It also starts automatically when we start reading from or writing data to it. Manually is session started by `$session-\u003estart()`.\n\nPHP sends HTTP headers affecting caching when starting the session, see `session_cache_limiter`, and possibly a cookie with the session ID. Therefore, it is always necessary to start the session before sending any output to the browser, otherwise an exception will be thrown. So if you know that a session will be used during page rendering, start it manually before, for example in the presenter.\n\nIn developer mode, Tracy starts the session because it uses it to display redirection and AJAX requests bars in the Tracy Bar.\n\n\nSection\n-------\n\nIn pure PHP, the session data store is implemented as an array accessible via a global variable `$_SESSION`. The problem is that applications normally consist of a number of independent parts, and if all have only one same array available, sooner or later a name collision will occur.\n\nNette Framework solves the problem by dividing the entire space into sections (objects [Nette\\Http\\SessionSection](https://api.nette.org/3.0/Nette/Http/SessionSection.html)). Each unit then uses its own section with a unique name and no collisions can occur.\n\nWe get the section from the session manager:\n\n```php\n$section = $session-\u003egetSession('unique name');\n```\n\nIn the presenter it is enough to call `getSession()` with the parameter:\n\n```php\n// $this is Presenter\n$section = $this-\u003egetSession('unique name');\n```\n\nThe existence of the section can be checked by the method `$session-\u003ehasSection('unique name')`.\n\nAnd then it's really simple to work with that section:\n\n```php\n// variable writing\n$section-\u003euserName = 'john'; // nebo $section['userName'] = 'john';\n\n// variable reading\necho $section-\u003euserName; // nebo echo $section['userName'];\n\n// variable removing\nunset($section-\u003euserName);  // unset($section['userName']);\n```\n\nIt's possible to use `foreach` cycle to obtain all variables from section:\n\n```php\nforeach ($section as $key =\u003e $val) {\n\techo \"$key = $val\";\n}\n```\n\nAccessing a non-existent variable does not generate any error (the returned value is null). It could be undesirable behavior in some cases and that's why there is a possibility to change it:\n\n```php\n$section-\u003ewarnOnUndefined = true;\n```\n\n\nHow to Set Expiration\n---------------------\n\nExpiration can be set for individual sections or even individual variables. We can let the user's login expire in 20 minutes, but still remember the contents of a shopping cart.\n\n```php\n// section will expire after 20 minutes\n$section-\u003esetExpiration('20 minutes');\n\n// variable $section-\u003eflash will expire after 30 seconds\n$section-\u003esetExpiration('30 seconds', 'flash');\n```\n\nThe cancellation of the previously set expiration can be achieved by the method `removeExpiration()`. Immediate deletion of the whole section will be ensured by the method `remove()`.\n\n\n\nSession Management\n------------------\n\nOverview of methods of the `Nette\\Http\\Session` class for session management:\n\nstart(): void\n-------------\nStarts a session.\n\nisStarted(): bool\n-----------------\nIs the session started?\n\nclose(): void\n-------------\nEnds the session. The session ends automatically at the end of the script.\n\ndestroy(): void\n---------------\nEnds and deletes the session.\n\nexists(): bool\n--------------\nDoes the HTTP request contain a cookie with a session ID?\n\nregenerateId(): void\n--------------------\nGenerates a new random session ID. Data remain unchanged.\n\ngetId(): string\n---------------\nReturns the session ID.\n\n\nConfiguration\n-------------\n\nMethods must be called before starting a session.\n\nsetName(string $name): static\n-----------------------------\nChanges the session name. It is possible to run several different sessions at the same time within one website, each under a different name.\n\ngetName(): string\n-----------------\nReturns the session name.\n\nsetOptions(array $options): static\n----------------------------------\nConfigures the session. It is possible to set all PHP [session directives](https://www.php.net/manual/en/session.configuration.php) (in camelCase format, eg write `savePath` instead of `session.save_path`) and also [readAndClose](https://www.php.net/manual/en/function.session-start.php#refsect1-function.session-start-parameters).\n\nsetExpiration(?string $time): static\n------------------------------------\nSets the time of inactivity after which the session expires.\n\nsetCookieParameters(string $path, string $domain = null, bool $secure = null, string $samesite = null): static\n--------------------------------------------------------------------------------------------------------------\nSets parameters for cookies.\n\nsetSavePath(string $path): static\n---------------------------------\nSets the directory where session files are stored.\n\nsetHandler(\\SessionHandlerInterface $handler): static\n-----------------------------------------------------\nSets custom handler, see [PHP documentation](https://www.php.net/manual/en/class.sessionhandlerinterface.php).\n\n\nSafety First\n------------\n\nThe server assumes that it communicates with the same user as long as requests contain the same session ID. The task of security mechanisms is to ensure that this behavior really works and that there is no possibility to substitute or steal an identifier.\n\nThat's why Nette Framework properly configures PHP directives to transfer session ID only in cookies, to avoid access from JavaScript and to ignore the identifiers in the URL. Moreover in critical moments, such as user login, it generates a new Session ID.\n\nFunction ini_set is used for configuring PHP, but unfortunately, its use is prohibited at some web hosting services. If it's your case, try to ask your hosting provider to allow this function for you, or at least to configure his server properly.  .[note]\n\n\n\nUrl\n===\n\nThe [Nette\\Http\\Url](https://api.nette.org/3.0/Nette/Http/Url.html) class makes it easy to work with the URL and its individual components, which are outlined in this diagram:\n\n```\n scheme  user  password  host   port    path        query  fragment\n   |      |      |        |      |       |            |       |\n /--\\   /--\\ /------\\ /-------\\ /--\\/----------\\ /--------\\ /----\\\n http://john:xyz%2A12@nette.org:8080/en/download?name=param#footer\n \\______\\__________________________/\n     |               |\n  hostUrl        authority\n```\n\nURL generation is intuitive:\n\n```php\nuse Nette\\Http\\Url;\n\n$url = new Url;\n$url-\u003esetScheme('https')\n\t-\u003esetHost('localhost')\n\t-\u003esetPath('/edit')\n\t-\u003esetQueryParameter('foo', 'bar');\n\necho $url; // 'https://localhost/edit?foo=bar'\n```\n\nYou can also parse the URL and then manipulate it:\n\n```php\n$url = new Url(\n\t'http://john:xyz%2A12@nette.org:8080/en/download?name=param#footer'\n);\n```\n\nThe following methods are available to get or change individual URL components:\n\nSetter\t\t\t\t\t\t\t\t\t| Getter\t\t\t\t\t\t| Returned value\n----------------------------------------|-------------------------------|------------------\n`setScheme(string $scheme)`\t\t\t\t| `getScheme(): string`\t\t\t| `'http'`\n`setUser(string $user)`\t\t\t\t\t| `getUser(): string`\t\t\t| `'john'`\n`setPassword(string $password)`\t\t\t| `getPassword(): string`\t\t| `'xyz*12'`\n`setHost(string $host)`\t\t\t\t\t| `getHost(): string`\t\t\t| `'nette.org'`\n`setPort(int $port)`\t\t\t\t\t\t| `getPort(): ?int`\t\t\t\t| `8080`\n`setPath(string $path)`\t\t\t\t\t| `getPath(): string`\t\t\t| `'/en/download'`\n`setQuery(string\\|array $query)`\t\t\t| `getQuery(): string`\t\t\t| `'name=param'`\n`setFragment(string $fragment)`\t\t\t| `getFragment(): string`\t\t| `'footer'`\n--\t\t\t\t\t\t\t\t\t\t\t| `getAuthority(): string`\t\t| `'nette.org:8080'`\n--\t\t\t\t\t\t\t\t\t\t\t| `getHostUrl(): string`\t\t| `'http://nette.org:8080'`\n--\t\t\t\t\t\t\t\t\t\t\t| `getAbsoluteUrl(): string` \t| full URL\n\nWe can also operate with individual query parameters using:\n\nSetter\t\t\t\t\t\t\t\t\t| Getter\n----------------------------------------|---------\n`setQuery(string\\|array $query)`  \t\t| `getQueryParameters(): array`\n`setQueryParameter(string $name, $val)`\t| `getQueryParameter(string $name)`\n\nMethod `getDomain(int $level = 2)` returns the right or left part of the host. This is how it works if the host is `www.nette.org`:\n\nUsage\t\t\t\t\t\t\t\t\t| Result\n----------------------------------------|---------\n`getDomain(1)`  |  `'org'`\n`getDomain(2)`  |  `'nette.org'`\n`getDomain(3)`  |  `'www.nette.org'`\n`getDomain(0)`  |  `'www.nette.org'`\n`getDomain(-1)` |  `'www.nette'`\n`getDomain(-2)` |  `'www'`\n`getDomain(-3)` |  `''`\n\n\nThe `Url` class implements the `JsonSerializable` interface and has a `__toString()` method so that the object can be printed or used in data passed to `json_encode()`.\n\n```php\necho $url;\necho json_encode([$url]);\n```\n\nMethod `isEqual(string|Url $anotherUrl): bool` tests whether the two URLs are identical.\n\n```php\n$url-\u003eisEqual('https://nette.org');\n```\n\n\nUrlImmutable\n============\n\nThe class [Nette\\Http\\UrlImmutable](https://api.nette.org/3.0/Nette/Http/UrlImmutable.html) is an immutable alternative to class `Url` (just as in PHP `DateTimeImmutable` is immutable alternative to `DateTime`). Instead of setters, it has so-called withers, which do not change the object, but return new instances with a modified value:\n\n```php\nuse Nette\\Http\\UrlImmutable;\n\n$url = new UrlImmutable(\n\t'http://john:xyz%2A12@nette.org:8080/en/download?name=param#footer'\n);\n\n$newUrl = $url\n\t-\u003ewithUser('')\n\t-\u003ewithPassword('')\n\t-\u003ewithPath('/cs/');\n\necho $newUrl; // 'http://nette.org:8080/cs/?name=param#footer'\n```\n\nThe following methods are available to get or change individual URL components:\n\nWither\t\t\t\t\t\t\t\t\t| Getter\t\t\t\t\t\t| Returned value\n----------------------------------------|-------------------------------|------------------\n`withScheme(string $scheme)`\t\t\t\t| `getScheme(): string`\t\t\t| `'http'`\n`withUser(string $user)`\t\t\t\t\t| `getUser(): string`\t\t\t| `'john'`\n`withPassword(string $password)`\t\t\t| `getPassword(): string`\t\t| `'xyz*12'`\n`withHost(string $host)`\t\t\t\t\t| `getHost(): string`\t\t\t| `'nette.org'`\n`withPort(int $port)`\t\t\t\t\t\t| `getPort(): ?int`\t\t\t\t| `8080`\n`withPath(string $path)`\t\t\t\t\t| `getPath(): string`\t\t\t| `'/en/download'`\n`withQuery(string\\|array $query)`\t\t\t| `getQuery(): string`\t\t\t| `'name=param'`\n`withFragment(string $fragment)`\t\t\t| `getFragment(): string`\t\t| `'footer'`\n--\t\t\t\t\t\t\t\t\t\t\t| `getAuthority(): string`\t\t| `'nette.org:8080'`\n--\t\t\t\t\t\t\t\t\t\t\t| `getHostUrl(): string`\t\t| `'http://nette.org:8080'`\n--\t\t\t\t\t\t\t\t\t\t\t| `getAbsoluteUrl(): string` \t| full URL\n\nWe can also operate with individual query parameters using:\n\nWither\t\t\t\t\t\t\t\t| Getter\n------------------------------------|---------\n`withQuery(string\\|array $query)` \t| `getQueryParameters(): array`\n--\t\t\t\t\t\t\t\t\t\t| `getQueryParameter(string $name)`\n\nThe `getDomain(int $level = 2)` method works the same as the method in `Url`. Method `withoutUserInfo()` removes `user` and `password`.\n\nThe `UrlImmutable` class implements the `JsonSerializable` interface and has a `__toString()` method so that the object can be printed or used in data passed to `json_encode()`.\n\n```php\necho $url;\necho json_encode([$url]);\n```\n\nMethod `isEqual(string|Url $anotherUrl): bool` tests whether the two URLs are identical.\n\n\nIf you like Nette, **[please make a donation now](https://github.com/sponsors/dg)**. Thank you!\n","funding_links":["https://github.com/sponsors/dg","https://nette.org/donate","https://github.com/sponsors/dg)*"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnette%2Fhttp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnette%2Fhttp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnette%2Fhttp/lists"}