Hướng dẫn dùng rfc 3986 trong PHP
Các thông điệp HTTP là căn bản của việc lập trình web. Trình duyệt web và các HTTP client như là cURL tạo các thông điệp HTTP với mục đích yêu câu để gửi về server, khi đó server sẽ trả về thông điệp phản hồi. Phias server sẽ nhận các yêu cầu và gửi trả phản hồi. Show
Các thông điệp HTTP thường được ẩn đi đối với người dùng cuối, nhưng với tư cách là nhà phát triển, chúng ta cần hiểu được cấu trúc và cách thức nó hoạt động và các để truy cập hoặc điều khiển các thông điệp ấy để thực hiện các nhiệm vụ, có thể là gửi yêu cầu tới 1 HTTP API hoặc là tiếp nhận 1 yêu cầu được gửi đến. Các thông điệp HTTP đều có 1 định dạng sau
Dòng đầu tiên của thông điệp là dòng "reuquest line"(dòng yêu cầu), chứa các thành phần sau theo thứ tự: phương thức request HTTP, mục tiêu của yêu cầu(thường là 1 URI hoặc là 1 đường dẫn ở web server) và phiên bản của thủ tục HTTP. Tiếp theo dòng đó sẽ là 1 hay nhiều HTTP header, dòng trống và cuối cùng là thân của thông điệp. Thông điệp phản hồi có định dạng tương tự:
Dòng đầu tiên là "trạng thái", chứa các thành phần sau theo thứ tự: phiên bản của thủ tục HTTP, mã trạng thái của HTTP, dòng "lí do", mô tả đọc được với người của mã HTTP. Tiếp theo dòng đó sẽ là 1 hay nhiều HTTP header, dòng trống và cuối cùng là thân của thông điệp y như thông điệp yêu cầu bên trên. Các interface mô tả trong document này đều về các cách trừu tượng hóa thông điệp HTTP và các phần tử chứa đựng chúng. Đặc tảThông điệp1 thông điệp HTTP có thể là yêu cầu từ client tới server hoặc phản hồi cỉa server cho client. Đây là định nghĩa cho các interface cho thông điệp HTTP là Cả Từ đây đến hết bài viết, namespace HTTP headerCác trường tên header không phân biệt chữ hoa chữ thườngCác thông điệp HTTP bao gồm các trường tên header không phân biệt chữ hoa chữ thường. Header được lấy theo tên từ các lớp thực hiện Mặc dù các tiêu đề đó có thể được truy xuất phân biệt chữ hoa chữ thường, trường hợp ban đầu PHẢI được bảo quản trong việc
triển khai, đặc biệt khi được truy xuất với Các ứng dụng HTTP không phù hợp CÓ THỂ phụ thuộc vào một trường hợp nhất định, vì vậy nó hữu ích cho người dùng để có thể ra lệnh cho trường hợp của các tiêu đề HTTP khi tạo một yêu cầu hoặc phản hồi.
Header với nhiều giá trịĐể phù hợp với các tiêu đề có nhiều giá trị vẫn cung cấp sự tiện lợi khi làm việc với các tiêu đề như các chuỗi, các tiêu đề có thể được lấy ra từ một cá thể của một
Lưu ý: Không phải tất cả các giá trị tiêu đề đều có thể được ghép bằng dấu phẩy (ví dụ: Host headerTrong các yêu cầu, tiêu đề Trong quá trình xây dựng ứng dụng, việc triển khai PHẢI cố gắng đặt tiêu đề
Bạn có thể chọn việc duy trì trạng thái ban đầu của tiêu đề Bảng này
minh họa những gì
Các dòng dữ liệuCác thông điệp HTTP bao gồm dòng bắt đầu, các tiêu đề và phần thân. Phần thân thông điệp có thể vô cùng nhỏ nhưng cũng có thể to khủng khiếp. Cố gắng để có thể đưa ra thông điệp dưới dạng 1 chuỗi sẽ dẫn tới việc tốn nhiều bộ nhớ hơn dự
tính vì phần thân cần được chứa trọn vẹn trong bộ nhớ. Cố gắng để lưu trữ phần thân của 1 yêu cầu hay phản hồi trong bộ nhớ có thể dẫn tới cản trở việc triển khai làm các thông điệp có dung lượng lớn hơn.
Các luồng thể hiện chức năng của chúng theo 3 cách: Mỗi luồng có 3 khả năng khác nhau: nó có thể là chỉ đọc, chỉ ghi, hoặc đọc-ghi. Nó cũng có thể cho phép truy cập ngẫu nhiên tùy ý (tìm kiếm chuyển tiếp hoặc quay trở lại bất kỳ vị trí nào) hoặc chỉ truy cập tuần tự (ví dụ trong trường hợp của một socket, pipe hoặc luồng dựa trên call-back). Cuối cùng, Không giống như interface yêu cầu và phản hồi, Mục tiêu yêu cầu và URITheo RFC 7230, các thông điệp yêu cầu chứa “mục tiêu yêu cầu” làm phân đoạn thứ hai của dòng yêu cầu. Mục tiêu yêu cầu có thể là một trong các dạng sau:
Ngoài các mục tiêu yêu cầu này, thường có ‘URL hiệu quả’ tách biệt với mục tiêu yêu cầu. URL hiệu quả không được truyền trong một thông báo HTTP, nhưng nó được sử dụng để xác định giao thức (http/https), cổng và tên máy chủ để thực hiện yêu cầu. Các URL có hiệu quả được biểu diễn bởi Khi truy lục mục tiêu yêu cầu với Nếu người dùng cuối mong muốn sử dụng một trong
ba biểu mẫu khác hoặc nếu người dùng muốn ghi đè rõ ràng mục tiêu yêu cầu, có thể làm như vậy với Gọi phương thức sẽ không ảnh hưởng tới URI, vì sẽ được trả lại với Ví dụ với yêu cầu asterisk-form:
Kết quả trả về
Nhưng đó là nếu máy khách HTTP sẽ có thể sử dụng URL hiệu quả (từ Một máy khách HTTP PHẢI bỏ qua các giá trị của Máy khách chọn không triển khai 1 hoặc nhiều hơn trong số 4 biểu mẫu yêu cầu-mục tiêu, PHẢI vẫn sử dụng
Yêu cầu phía server
Yêu cầu máy chủ cung cấp thêm một thuộc tính, "attributes", để cho phép người tiêu dùng có khả năng nhìn vào, phân tích và so khớp yêu cầu đối với các quy tắc cụ thể cho ứng dụng (chẳng hạn như đối sánh đường dẫn, đối sánh lược đồ, đối sánh lưu trữ, v.v.). Như vậy, yêu cầu máy chủ cũng có thể cung cấp thông điệp giữa nhiều người tiêu dùng yêu cầu. Tải file lên
Các superglobal
thay vì:
Kết quả là người tiêu dùng cần biết chi tiết triển khai ngôn ngữ này và viết mã để thu thập dữ liệu cho một lần tải lên nhất định. Ngoài ra, các tình huống tồn tại khi
Trong những trường hợp như vậy, dữ liệu phải được đưa vào cẩn thận:
Cấu trúc cây được tham chiếu nên bắt chước cấu trúc đặt tên trong đó các tệp đã được gửi. Trong ví dụ đơn giản nhất, đây có thể là một phần tử biểu mẫu được đặt tên được gửi dưới dạng:
Trong trường hợp này,
Biểu mẫu thông thường được trả về bởi
Trong trường hợp đầu vào sử dụng ký hiệu mảng cho tên:
Và cây trả về bởi
Trong vài trường hợp, bạn có thể thiết lập riêng mảng các tệp:
(Ví dụ: các điều khiển JavaScript có thể sinh ra các đầu vào tải lên tệp bổ sung để cho phép tải lên nhiều tệp cùng một lúc.) Trong trường hợp này, việc triển khai đặc tả phải tổng hợp tất cả thông tin liên quan đến tệp tại chỉ mục đã cho. Lý do là vì
Mảng
Người tiêu dùng sẽ truy cập vào index
Bởi vì dữ liệu tệp được tải lên là bắt nguồn (bắt nguồn từ Trong trường hợp các ví dụ ban đầu, mức tiêu thụ tương tự như sau:
Đề xuất này cũng nhận ra rằng việc triển khai có thể hoạt động trong môi trường không phải SAPI. Như vậy,
Như ví dụ:
Gói thư việnCác lớp và lớp giao diện được cung cấp dưới đây như 1 phần của gói psr/http-message Các InterfacePsr\Http\Message\MessageInterface
Psr\Http\Message\RequestInterface
Psr\Http\Message\ServerRequestInterface
Psr\Http\Message\ResponseInterface
Psr\Http\Message\StreamInterface
Psr\Http\Message\UriInterface
*
* If the port component is not set or is the standard port for the current
* scheme, it SHOULD NOT be included.
*
* @see https://tools.ietf.org/html/rfc3986#section-3.2
* @return string The URI authority, in "[user-info@]host[:port]" format.
*/
public function getAuthority();
/**
* Retrieve the user information component of the URI.
*
* If no user information is present, this method MUST return an empty
* string.
*
* If a user is present in the URI, this will return that value;
* additionally, if the password is also present, it will be appended to the
* user value, with a colon (":") separating the values.
*
* The trailing "@" character is not part of the user information and MUST
* NOT be added.
*
* @return string The URI user information, in "username[:password]" format.
*/
public function getUserInfo();
/**
* Retrieve the host component of the URI.
*
* If no host is present, this method MUST return an empty string.
*
* The value returned MUST be normalized to lowercase, per RFC 3986
* Section 3.2.2.
*
* @see http://tools.ietf.org/html/rfc3986#section-3.2.2
* @return string The URI host.
*/
public function getHost();
/**
* Retrieve the port component of the URI.
*
* If a port is present, and it is non-standard for the current scheme,
* this method MUST return it as an integer. If the port is the standard port
* used with the current scheme, this method SHOULD return null.
*
* If no port is present, and no scheme is present, this method MUST return
* a null value.
*
* If no port is present, but a scheme is present, this method MAY return
* the standard port for that scheme, but SHOULD return null.
*
* @return null|int The URI port.
*/
public function getPort();
/**
* Retrieve the path component of the URI.
*
* The path can either be empty or absolute (starting with a slash) or
* rootless (not starting with a slash). Implementations MUST support all
* three syntaxes.
*
* Normally, the empty path "" and absolute path "/" are considered equal as
* defined in RFC 7230 Section 2.7.3. But this method MUST NOT automatically
* do this normalization because in contexts with a trimmed base path, e.g.
* the front controller, this difference becomes significant. It's the task
* of the user to handle both "" and "/".
*
* The value returned MUST be percent-encoded, but MUST NOT double-encode
* any characters. To determine what characters to encode, please refer to
* RFC 3986, Sections 2 and 3.3.
*
* As an example, if the value should include a slash ("/") not intended as
* delimiter between path segments, that value MUST be passed in encoded
* form (e.g., "%2F") to the instance.
*
* @see https://tools.ietf.org/html/rfc3986#section-2
* @see https://tools.ietf.org/html/rfc3986#section-3.3
* @return string The URI path.
*/
public function getPath();
/**
* Retrieve the query string of the URI.
*
* If no query string is present, this method MUST return an empty string.
*
* The leading "?" character is not part of the query and MUST NOT be
* added.
*
* The value returned MUST be percent-encoded, but MUST NOT double-encode
* any characters. To determine what characters to encode, please refer to
* RFC 3986, Sections 2 and 3.4.
*
* As an example, if a value in a key/value pair of the query string should
* include an ampersand ("&") not intended as a delimiter between values,
* that value MUST be passed in encoded form (e.g., "%26") to the instance.
*
* @see https://tools.ietf.org/html/rfc3986#section-2
* @see https://tools.ietf.org/html/rfc3986#section-3.4
* @return string The URI query string.
*/
public function getQuery();
/**
* Retrieve the fragment component of the URI.
*
* If no fragment is present, this method MUST return an empty string.
*
* The leading "#" character is not part of the fragment and MUST NOT be
* added.
*
* The value returned MUST be percent-encoded, but MUST NOT double-encode
* any characters. To determine what characters to encode, please refer to
* RFC 3986, Sections 2 and 3.5.
*
* @see https://tools.ietf.org/html/rfc3986#section-2
* @see https://tools.ietf.org/html/rfc3986#section-3.5
* @return string The URI fragment.
*/
public function getFragment();
/**
* Return an instance with the specified scheme.
*
* This method MUST retain the state of the current instance, and return
* an instance that contains the specified scheme.
*
* Implementations MUST support the schemes "http" and "https" case
* insensitively, and MAY accommodate other schemes if required.
*
* An empty scheme is equivalent to removing the scheme.
*
* @param string $scheme The scheme to use with the new instance.
* @return static A new instance with the specified scheme.
* @throws \InvalidArgumentException for invalid schemes.
* @throws \InvalidArgumentException for unsupported schemes.
*/
public function withScheme($scheme);
/**
* Return an instance with the specified user information.
*
* This method MUST retain the state of the current instance, and return
* an instance that contains the specified user information.
*
* Password is optional, but the user information MUST include the
* user; an empty string for the user is equivalent to removing user
* information.
*
* @param string $user The user name to use for authority.
* @param null|string $password The password associated with $user.
* @return static A new instance with the specified user information.
*/
public function withUserInfo($user, $password = null);
/**
* Return an instance with the specified host.
*
* This method MUST retain the state of the current instance, and return
* an instance that contains the specified host.
*
* An empty host value is equivalent to removing the host.
*
* @param string $host The hostname to use with the new instance.
* @return static A new instance with the specified host.
* @throws \InvalidArgumentException for invalid hostnames.
*/
public function withHost($host);
/**
* Return an instance with the specified port.
*
* This method MUST retain the state of the current instance, and return
* an instance that contains the specified port.
*
* Implementations MUST raise an exception for ports outside the
* established TCP and UDP port ranges.
*
* A null value provided for the port is equivalent to removing the port
* information.
*
* @param null|int $port The port to use with the new instance; a null value
* removes the port information.
* @return static A new instance with the specified port.
* @throws \InvalidArgumentException for invalid ports.
*/
public function withPort($port);
/**
* Return an instance with the specified path.
*
* This method MUST retain the state of the current instance, and return
* an instance that contains the specified path.
*
* The path can either be empty or absolute (starting with a slash) or
* rootless (not starting with a slash). Implementations MUST support all
* three syntaxes.
*
* If an HTTP path is intended to be host-relative rather than path-relative
* then it must begin with a slash ("/"). HTTP paths not starting with a slash
* are assumed to be relative to some base path known to the application or
* consumer.
*
* Users can provide both encoded and decoded path characters.
* Implementations ensure the correct encoding as outlined in getPath().
*
* @param string $path The path to use with the new instance.
* @return static A new instance with the specified path.
* @throws \InvalidArgumentException for invalid paths.
*/
public function withPath($path);
/**
* Return an instance with the specified query string.
*
* This method MUST retain the state of the current instance, and return
* an instance that contains the specified query string.
*
* Users can provide both encoded and decoded query characters.
* Implementations ensure the correct encoding as outlined in getQuery().
*
* An empty query string value is equivalent to removing the query string.
*
* @param string $query The query string to use with the new instance.
* @return static A new instance with the specified query string.
* @throws \InvalidArgumentException for invalid query strings.
*/
public function withQuery($query);
/**
* Return an instance with the specified URI fragment.
*
* This method MUST retain the state of the current instance, and return
* an instance that contains the specified URI fragment.
*
* Users can provide both encoded and decoded fragment characters.
* Implementations ensure the correct encoding as outlined in getFragment().
*
* An empty fragment value is equivalent to removing the fragment.
*
* @param string $fragment The fragment to use with the new instance.
* @return static A new instance with the specified fragment.
*/
public function withFragment($fragment);
/**
* Return the string representation as a URI reference.
*
* Depending on which components of the URI are present, the resulting
* string is either a full URI or relative reference according to RFC 3986,
* Section 4.1. The method concatenates the various components of the URI,
* using the appropriate delimiters:
*
* - If a scheme is present, it MUST be suffixed by ":".
* - If an authority is present, it MUST be prefixed by "//".
* - The path can be concatenated without delimiters. But there are two
* cases where the path has to be adjusted to make the URI reference
* valid as PHP does not allow to throw an exception in __toString():
* - If the path is rootless and an authority is present, the path MUST
* be prefixed by "/".
* - If the path is starting with more than one "/" and no authority is
* present, the starting slashes MUST be reduced to one.
* - If a query is present, it MUST be prefixed by "?".
* - If a fragment is present, it MUST be prefixed by "#".
*
* @see http://tools.ietf.org/html/rfc3986#section-4.1
* @return string
*/
public function __toString();
}
Psr\Http\Message\UploadedFileInterface
Tham khảohttps://www.php-fig.org/psr/psr-7/ |