Giter VIP home page Giter VIP logo

ext-request's Introduction

ext/request

This extension provides server-side request and response objects for PHP.

These are not HTTP message objects proper. They are more like wrappers for existing global PHP variables and functions.

This extension defines four classes and one interface in the global namespace:

  • SapiRequest, composed of read-only copies of PHP superglobals and some other commonly-used values.

  • SapiUpload, a value-object style descriptor of each uploaded file.

  • SapiResponse and SapiResponseInterface, essentially a wrapper around (and buffer for) response-related PHP functions.

  • SapiResponseSender, for sending a SapiResponse.

Installing

Via PECL

In most cases, it is easiest to install via PECL:

# pecl install request

Alternatively, clone or otherwise download this repository; then, in the repository directory, issue these commands to compile and install the extension:

$ phpize
$ ./configure
$ make
# make install

Finally, enable the request.so extension in your php.ini file, and restart your web server.

SapiRequest

An object of public read-only properties representing the PHP request received by the server. Use it in place of the $_GET, $_POST, etc. superglobals. It provides:

  • non-session superglobals as public, immutable, read-only properties;

  • other public, immutable, read-only properties calculated from the superglobals ($method, $headers, $accept, $uploads, etc.);

Note that SapiRequest can be extended to provide other userland functionality; however, the public properties cannot be modified or overridden.

Instantiation

Instantiation of SapiRequest is straightforward:

$request = new SapiRequest($GLOBALS);

If you want to provide custom superglobal values to the object, pass an array that mimics $GLOBALS to the constructor:

$request = new SapiRequest([
    '_SERVER' => [
        'foo' => 'bar',
    ],
]);

By default, the $content property will read from php://input on-the-fly. If you want to provide a custom $content string instead, pass it as the second constructor argument:

$request = new SapiRequest(
  $GLOBALS,
  'custom-php-input-string'
);

N.b.: It is up to you to make sure the various content-related header values in $GLOBALS match the custom $content string.

Properties

SapiRequest has these public properties.

Superglobal-related

These properties are public, immutable, read-only, and cannot be modified or overridden.

  • ?array $cookie: A copy of $_COOKIE.
  • ?array $files: A copy of $_FILES.
  • ?array $input: A copy of $_POST.
  • ?array $query: A copy of $_GET.
  • ?array $server: A copy of $_SERVER.
  • ?array $uploads: A copy of $_FILES, restructured to look more like $_POST; instead of array descriptors, the elements are instances of SapiUpload.
The $uploads array

The SapiRequest $files property is an identical copy of $_FILES. Normally, $_FILES looks like this with multi-file uploads:

// $_FILES ...
[
    'images' => [
        'name' => [
            0 => 'image1.png',
            1 => 'image2.gif',
            2 => 'image3.jpg',
        ],
        'type' => [
            0 => 'image/png',
            1 => 'image/gif',
            2 => 'image/jpeg',
        ],
        'tmp_name' [
            0 => '/tmp/path/phpABCDEF',
            1 => '/tmp/path/phpGHIJKL',
            2 => '/tmp/path/phpMNOPQR',
        ],
        'error' => [
            0 => 0,
            1 => 0,
            2 => 0,
        ],
        'size' =>[
            0 => 123456,
            1 => 234567,
            2 => 345678,
        ],
    ],
];

However, that structure is not at all what we expect when we are used to working with $_POST. Therefore, the SapiRequest $uploads property restructures the data in $_FILES to look more like $_POST does ...

// $request->uploads ...
[
    'images' => [
        0 => [
            'name' => 'image1.png',
            'type' => 'image/png',
            'tmp_name' => '/tmp/path/phpABCDEF',
            'error' => 0,
            'size' => 123456,
        ],
        1 => [
            'name' => 'image2.gif',
            'type' => 'image/gif',
            'tmp_name' => '/tmp/path/phpGHIJKL',
            'error' => 0,
            'size' => 234567,
        ],
        2 => [
            'name' => 'image3.jpg',
            'type' => 'image/jpeg',
            'tmp_name' => '/tmp/path/phpMNOPQR',
            'error' => 0,
            'size' => 345678,
        ],
    ],
];

... and then replaces each array-based descriptor with a SapiUpload instance.

HTTP-related

These properties are public, immutable, read-only, and cannot be modified or overridden.

  • ?array $accept: An array of arrays computed from $_SERVER['HTTP_ACCEPT'].
  • ?array $acceptCharset: An array of arrays computed from $_SERVER['HTTP_ACCEPT_CHARSET'].
  • ?array $acceptEncoding: An array of arrays computed from $_SERVER['HTTP_ACCEPT_ENCODING'].
  • ?array $acceptLanguage: An array of arrays computed from $_SERVER['HTTP_ACCEPT_LANGUAGE'].
  • ?array $forwarded: An array of arrays computed from $_SERVER['HTTP_FORWARDED'].
  • ?array $forwardedFor: An array computed from treating $_SERVER['HTTP_X_FORWARDED_FOR'] as comma-separated values.
  • ?string $forwardedHost: The $_SERVER['HTTP_X_FORWARDED_HOST'] value.
  • ?string $forwardedProto: The $_SERVER['HTTP_X_FORWARDED_PROTO'] value.
  • ?array $headers: An array of key/value pairs computed from $_SERVER using all HTTP_* header keys, plus RFC 3875 headers not prefixed with HTTP_. Note that the header keys are retained in lower-case. This is to comply with HTTP/2 requirements; while HTTP/1.x has no such requirement, lower-case is also recognized as valid.
  • ?string $method: The $_SERVER['REQUEST_METHOD'] value, or the $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'] value when appropriate.
  • ?array $url: The result from applying parse_url() to a a URL string constructed from various $_SERVER elements.
The $accept* Arrays

Each element of the $accept* arrays is an array with these keys:

'value' => The "main" value of the accept specifier
'quality' => The 'q=' parameter value
'params' => A key-value array of all other parameters

In addition, each $acceptLanguage array element has two additional keys: 'type' and 'subtype'.

The $accept* array elements are sorted by highest q value to lowest.

The $forwarded Array

Cf. the Forwarded HTTP Extension

Each element of the $forwarded array is an array composed of one or more of the following keys:

'by' => The interface where the request came in to the proxy server.
'for' => Discloses information about the client that initiated the request.
'host' =>  The original value of the Host header field.
'proto' => The value of the used protocol type.
The $url Array

SapiRequest attempts to build a string of the full request URL of the using the following:

  • If $_SERVER['HTTPS'] === 'on', the scheme is 'https'; otherwise, it is 'http'.
  • If $_SERVER['HTTP_HOST'] is present, it is used as the host name; otherwise, $_SERVER['SERVER_NAME'] is used.
  • If a port number is present on the host name, it is used as the port; otherwise, $_SERVER['SERVER_PORT'] is used.
  • $_SERVER['REQUEST_URI'] is used for the path and query string.

SapiRequest then passes that string through parse_url() and retains the resulting array as $url.

You can then retrieve the array elements using the PHP_URL_* constants:

$scheme = $request->url[PHP_URL_SCHEME];
$host = $request->url[PHP_URL_HOST];
$port = $request->url[PHP_URL_PORT];
$path = $request->url[PHP_URL_PATH];
$queryString = $request->url[PHP_URL_QUERY];

If parse_url() fails, the $url property will remain null.

Content-related

These properties are public, immutable, read-only, and cannot be modified or overridden.

  • string $content: The value of file_get_contents('php://input'), or the custom content string provided at construction time.
  • ?string $contentCharset: The charset parameter value of $_SERVER['CONTENT_TYPE'].
  • ?int $contentLength: The value of $_SERVER['CONTENT_LENGTH'].
  • ?string $contentMd5: The value of $_SERVER['HTTP_CONTENT_MD5'].
  • ?string $contentType: The value of $_SERVER['CONTENT_TYPE'], minus any parameters.

Authentication-related

These properties are public, immutable, read-only, and cannot be modified or overridden.

  • ?array $authDigest: An array of digest values computed from $_SERVER['PHP_AUTH_DIGEST'].
  • ?string $authPw: The value of $_SERVER['PHP_AUTH_PW'].
  • ?string $authType: The value of $_SERVER['PHP_AUTH_TYPE'].
  • ?string $authUser: The value of $_SERVER['PHP_AUTH_USER'].

Methods

The SapiRequest object has no public methods other than its constructor:

  • __construct(array $globals, [?string $content = null])

Extending and Overriding

Although it is easy and convenient to extend this class, the authors recommend decoration and composition over extension in all but the most trivial of cases.

SapiRequest has a constructor. Child classes overriding __construct() should be sure to call parent::__construct(), or else the public read-only properties will not be set (defaulting to null in all cases).

The public read-only properties cannot be overridden; however, child classes may add new properties as desired.

SapiRequest has no methods; child classes may add methods as desired, and SapiRequest does not anticipate adding new methods of its own.

SapiUpload

A read-only object describing an individual file upload.

Properties

SapiUpload has these public properties; they are immutable, read-only, and cannot be modified or overridden:

  • ?string $name: The original name of the file on the client machine.

  • ?string $type: The mime type of the file, if the client provided this information.

  • ?int $size: The size, in bytes, of the uploaded file.

  • ?string $tmpName: The temporary filename of the file in which the uploaded file was stored on the server.

  • ?int $error: The error code associated with this file upload.

Methods

SapiUpload has these public methods:

  • __construct(?string $name, ?string $type, ?int $size, ?string $tmpName, ?int $error): The constructor; once constructed, it cannot be constructed again.

  • move(string $destination) : bool: The equivalent of move_uploaded_file.

SapiResponse

A mutable object representing the PHP response to be sent from the server; use it in place of the header(), setcookie(), setrawcookie(), etc. functions. It provides a retention space for the HTTP response version, code, headers, cookies, and content, so they can be inspected before sending.

Note that SapiResponse can be extended to provide other userland functionality. However, its public methods are final; they cannot be modified or overridden.

Instantiation

Instantation is straightforward:

$response = new SapiResponse();

Properties

SapiResponse has no public properties.

Methods

SapiResponse implements SapiResponseInterface, which has these public methods; all of them are declared final and so may not be overridden.

Protocol Version

  • setVersion(?string $version) : SapiResponseInterface: Sets the protocol version for the response (typically '1.0', '1.1', or '2').

  • getVersion() : ?string: Returns the protocol version for the response.

Status Code

  • setCode(?int $code) : SapiResponseInterface: Sets the status code for the response; a buffered equivalent of http_response_code($code).

  • getCode() : ?int: Gets the status code for the response.

Headers

  • setHeader(string $label, string $value) : SapiResponseInterface: Overwrites an HTTP header; a buffered equivalent of header("$label: $value", true).

  • addHeader(string $label, string $value) : SapiResponseInterface: Appends to an HTTP header, comma-separating it from the existing value; a buffered equivalent of header("$label: $value", false).

  • unsetHeader(string $label) : SapiResponseInterface: Removes a header from the buffer.

  • unsetHeaders() : SapiResponseInterface: Removes all headers from the buffer.

  • getHeaders() : ?array: Returns the array of headers to be sent.

  • getHeader(string $label) : ?string: Returns a header from the buffer.

  • hasHeader(string $label) : bool: Returns true if a header exists in buffer.

The header field labels are retained internally in lower-case, and are sent as lower-case. This is to comply with HTTP/2 requirements; while HTTP/1.x has no such requirement, lower-case is also recognized as valid.

Cookies

  • setCookie(...) : SapiResponseInterface: A buffered equivalent of setcookie() with identical arguments.

  • setRawCookie(...) : SapiResponseInterface: A buffered equivalent of setrawcookie() with identical arguments.

  • unsetCookie(string $name) : SapiResponseInterface: Removes a cookie from the buffer.

  • unsetCookies() : SapiResponseInterface: Removes all cookies from the buffer.

  • getCookies() : ?array: Returns the array of cookies to be sent.

  • getCookie(string $name) : ?array: Returns a cookie from the buffer.

  • hasCookie(string $name) : bool: Returns true if a cookie exists in buffer.

Header Callbacks

  • setHeaderCallbacks(array $callbacks) : SapiResponseInterface: Sets an array of callbacks to be invoked just before headers are sent. It replaces any existing callbacks. This is similar to header_register_callback(), except that multiple callbacks may be registered with the Response.

  • addHeaderCallback(callable $callback) : SapiResponseInterface: Appends one callback to the current array of header callbacks.

  • getHeaderCallbacks() : ?array: Returns the array of header callbacks.

The header callback signature should be function (SapiResponseInterface $response); any return value is ignored.

Content

  • setContent(mixed $content) : SapiResponseInterface: Sets the content of the response. This may be null, a string, resource, object, or anything else.

  • getContent() : mixed: Returns the content of the response. This may be null, a string, resource, object, or anything else.

Extending and Overriding

Although it is easy and convenient to extend this class, the authors recommend decoration and composition over extension in all but the most trivial of cases.

SapiResponse is constructorless, which means you can add any constructor you like and not have to call a parent constructor.

The properties on SapiResponse are private, which means you may not access them, except through the existing SapiResponse methods.

The methods on SapiResponse are public and final, which means you cannot extend or override them in child classes. This keeps their behavior consistent.

However, the class itself is not final, which means you can add any other properties and methods you like.

The combination of a non-final class with private properties and public final methods keeps SapiResponse open for extension, but closed for modification.

SapiResponseSender

An object to send a SapiResponse.

Note that SapiResponseSender methods can be extended and overridden.

Instantiation

Instantiation is straightforward:

$sender = new SapiResponseSender();

Properties

This class has no properties of any kind.

Methods

SapiResponseSender has these public methods:

  • send(SapiResponseInterface $response) : void: Calls the following methods in order; that is: runHeaderCallbacks(), sendStatus(), sendHeaders(), sendCookies(), and sendContent().

  • runHeaderCallbacks(SapiResponseInterface $response) : void: Invokes each callback returned by SapiResponse::getHeaderCallbacks().

  • sendStatus(SapiResponseInterface $response) : void: Sends the HTTP status line using header(). The line is composed of SapiResponse::getVersion() and SapiResponse::getCode(). If the version is null it defaults to 1.1; if the code is null is defaults to 200.

  • sendHeaders(SapiResponseInterface $response) : void: Sends each header returned by SapiResponse::getHeaders() using header().

  • sendCookies(SapiResponseInterface $response) : void: Sends each cookie returned by SapiResponse::getCookies() using setcookie() or setrawcookie().

  • sendContent(SapiResponseInterface $response) : void: Sends the content returned by SapiResponse::getContent().

    • If the content is a resource, it is sent using rewind() and then fpassthru(); there is no further handling thereafter.

    • If the content is a callable object or closure, it is invoked, and its return value (if any) is passed along to be handled by the next step.

    • If the content or returned value is iterable, it is foreach()-ed through, and each value is echoed as a string; note that object values will be cast to string at this point, invoking their __toString() method if present.

    • Otherwise, the content or returned value is echoed as a string; note that an object will be cast to string at this point, invoking its __toString() method if present.

Extending and Overriding

Although it is easy and convenient to extend this class, the authors recommend decoration and composition over extension in all but the most trivial of cases.

SapiResponseSender is constructorless, which means you can add any constructor you like and not have to call a parent constructor.

The SapiResponseSender methods are public but not final, which means you can extend and override them as you see fit. Doing so for any method other than sendContent() might not make sense. There is pretty much only one way to send headers, cookies, etc., but different kinds of content might well deserve sending logic that differs from the default sendContent() logic.

ext-request's People

Contributors

jan-e avatar jbboehr avatar pmjones avatar remicollet avatar sergeyklay avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

ext-request's Issues

Add ServerResponseInterface fluency

I have been told that adding fluency to these ServerResponseInterface methods may ease adoption by existing vendors and consumers:

  • setVersion(string $version) : void
  • setHeader(string $label, string $value) : void
  • addHeader(string $label, string $value) : void
  • unsetHeader(string $label) : void
  • unsetHeaders() : void
  • unsetCookie(string $name) : void
  • unsetCookies() : void
  • setHeaderCallbacks(array $callbacks) : void
  • addHeaderCallback(callable $callback) : void
  • setContent(mixed $content) : void
  • setCookie(...) : bool
  • setRawCookie(...) : bool

The methods should have a return typehint of ServerResponseInterface; the ServerResponse implementation should return $this.

ServerResponseSender is tightly coupled to ServerResponse

Sorry this slipped my mind. I almost made a barebones user-land implementation of ServerResponseInterface for the test suite but I figured "what could possibly go wrong."

Well... ServerResponseSender sends the response by reading the properties (not using the methods) of the ServerResponse class, so ServerResponseSender needs to be refactored.

Não consigo fazer funcionar a extensão

Consegui instalar a extensão, mas quando executo :
$request = new SapiRequest($_POST); var_dump($request);
para testar, diz que não existe essa classe.

A versão do meu PHP é a 7.2 .

Captura de tela de 2020-04-16 10-37-03

make warnings and test fails php 7.2

here my compile log :

/bin/bash /tmp/request-1.0.0b2/libtool --mode=compile cc  -I. -I/tmp/request-1.0.0b2 -DPHP_ATOM_INC -I/tmp/request-1.0.0b2/include -I/tmp/request-1.0.0b2/main -I/tmp/request-1.0.0b2 -I/usr/include/php/20170718 -I/usr/include/php/20170718/main -I/usr/include/php/20170718/TSRM -I/usr/include/php/20170718/Zend -I/usr/include/php/20170718/ext -I/usr/include/php/20170718/ext/date/lib  -DHAVE_CONFIG_H  -g -O2   -c /tmp/request-1.0.0b2/php_request.c -o php_request.lo 
libtool: compile:  cc -I. -I/tmp/request-1.0.0b2 -DPHP_ATOM_INC -I/tmp/request-1.0.0b2/include -I/tmp/request-1.0.0b2/main -I/tmp/request-1.0.0b2 -I/usr/include/php/20170718 -I/usr/include/php/20170718/main -I/usr/include/php/20170718/TSRM -I/usr/include/php/20170718/Zend -I/usr/include/php/20170718/ext -I/usr/include/php/20170718/ext/date/lib -DHAVE_CONFIG_H -g -O2 -c /tmp/request-1.0.0b2/php_request.c  -fPIC -DPIC -o .libs/php_request.o
/bin/bash /tmp/request-1.0.0b2/libtool --mode=compile cc  -I. -I/tmp/request-1.0.0b2 -DPHP_ATOM_INC -I/tmp/request-1.0.0b2/include -I/tmp/request-1.0.0b2/main -I/tmp/request-1.0.0b2 -I/usr/include/php/20170718 -I/usr/include/php/20170718/main -I/usr/include/php/20170718/TSRM -I/usr/include/php/20170718/Zend -I/usr/include/php/20170718/ext -I/usr/include/php/20170718/ext/date/lib  -DHAVE_CONFIG_H  -g -O2   -c /tmp/request-1.0.0b2/parsers.c -o parsers.lo 
libtool: compile:  cc -I. -I/tmp/request-1.0.0b2 -DPHP_ATOM_INC -I/tmp/request-1.0.0b2/include -I/tmp/request-1.0.0b2/main -I/tmp/request-1.0.0b2 -I/usr/include/php/20170718 -I/usr/include/php/20170718/main -I/usr/include/php/20170718/TSRM -I/usr/include/php/20170718/Zend -I/usr/include/php/20170718/ext -I/usr/include/php/20170718/ext/date/lib -DHAVE_CONFIG_H -g -O2 -c /tmp/request-1.0.0b2/parsers.c  -fPIC -DPIC -o .libs/parsers.o
parsers.re: In function 'server_request_parser_forwarded_assignment':
parsers.re:508:24: warning: passing argument 1 of 'php_strtolower' discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers]
         php_strtolower(left.yytext, left.yyleng);
                        ^~~~
In file included from parsers.re:10:0:
/usr/include/php/20170718/ext/standard/php_string.h:124:14: note: expected 'char *' but argument is of type 'const YYCTYPE * {aka const unsigned char *}'
 PHPAPI char *php_strtolower(char *s, size_t len);
              ^~~~~~~~~~~~~~
/bin/bash /tmp/request-1.0.0b2/libtool --mode=compile cc  -I. -I/tmp/request-1.0.0b2 -DPHP_ATOM_INC -I/tmp/request-1.0.0b2/include -I/tmp/request-1.0.0b2/main -I/tmp/request-1.0.0b2 -I/usr/include/php/20170718 -I/usr/include/php/20170718/main -I/usr/include/php/20170718/TSRM -I/usr/include/php/20170718/Zend -I/usr/include/php/20170718/ext -I/usr/include/php/20170718/ext/date/lib  -DHAVE_CONFIG_H  -g -O2   -c /tmp/request-1.0.0b2/serverresponse.c -o serverresponse.lo 
libtool: compile:  cc -I. -I/tmp/request-1.0.0b2 -DPHP_ATOM_INC -I/tmp/request-1.0.0b2/include -I/tmp/request-1.0.0b2/main -I/tmp/request-1.0.0b2 -I/usr/include/php/20170718 -I/usr/include/php/20170718/main -I/usr/include/php/20170718/TSRM -I/usr/include/php/20170718/Zend -I/usr/include/php/20170718/ext -I/usr/include/php/20170718/ext/date/lib -DHAVE_CONFIG_H -g -O2 -c /tmp/request-1.0.0b2/serverresponse.c  -fPIC -DPIC -o .libs/serverresponse.o
/tmp/request-1.0.0b2/serverresponse.c: In function 'zim_ServerResponse_runHeaderCallbacks':
/tmp/request-1.0.0b2/serverresponse.c:882:24: warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]
             fci.params = &params;
                        ^
In file included from /usr/include/php/20170718/main/php.h:40:0,
                 from /tmp/request-1.0.0b2/serverresponse.c:6:
/tmp/request-1.0.0b2/serverresponse.c: In function 'zim_ServerResponse_sendContent':
/tmp/request-1.0.0b2/serverresponse.c:1086:86: warning: passing argument 5 of '_call_user_function_ex' from incompatible pointer type [-Wincompatible-pointer-types]
         call_user_function(&Z_OBJCE_P(tmp)->function_table, tmp, &func_name, &rv, 1, &params);
                                                                                      ^
/usr/include/php/20170718/Zend/zend_API.h:492:73: note: in definition of macro 'call_user_function'
  _call_user_function_ex(object, function_name, retval_ptr, param_count, params, 1)
                                                                         ^~~~~~
/usr/include/php/20170718/Zend/zend_API.h:489:14: note: expected 'zval * {aka struct _zval_struct *}' but argument is of type 'zval (*)[1] {aka struct _zval_struct (*)[1]}'
 ZEND_API int _call_user_function_ex(zval *object, zval *function_name, zval *retval_ptr, uint32_t param_count, zval params[], int no_separation);
              ^~~~~~~~~~~~~~~~~~~~~~
/bin/bash /tmp/request-1.0.0b2/libtool --mode=compile cc  -I. -I/tmp/request-1.0.0b2 -DPHP_ATOM_INC -I/tmp/request-1.0.0b2/include -I/tmp/request-1.0.0b2/main -I/tmp/request-1.0.0b2 -I/usr/include/php/20170718 -I/usr/include/php/20170718/main -I/usr/include/php/20170718/TSRM -I/usr/include/php/20170718/Zend -I/usr/include/php/20170718/ext -I/usr/include/php/20170718/ext/date/lib  -DHAVE_CONFIG_H  -g -O2   -c /tmp/request-1.0.0b2/serverrequest.c -o serverrequest.lo 
libtool: compile:  cc -I. -I/tmp/request-1.0.0b2 -DPHP_ATOM_INC -I/tmp/request-1.0.0b2/include -I/tmp/request-1.0.0b2/main -I/tmp/request-1.0.0b2 -I/usr/include/php/20170718 -I/usr/include/php/20170718/main -I/usr/include/php/20170718/TSRM -I/usr/include/php/20170718/Zend -I/usr/include/php/20170718/ext -I/usr/include/php/20170718/ext/date/lib -DHAVE_CONFIG_H -g -O2 -c /tmp/request-1.0.0b2/serverrequest.c  -fPIC -DPIC -o .libs/serverrequest.o
/tmp/request-1.0.0b2/serverrequest.c: In function 'server_request_copy_global':
/tmp/request-1.0.0b2/serverrequest.c:595:37: warning: passing argument 1 of 'zend_is_auto_global_str' discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers]
             zend_is_auto_global_str(glob_key, glob_key_length);
                                     ^~~~~~~~
In file included from /usr/include/php/20170718/Zend/zend_modules.h:26:0,
                 from /usr/include/php/20170718/Zend/zend_API.h:27,
                 from /usr/include/php/20170718/main/php.h:40,
                 from /tmp/request-1.0.0b2/serverrequest.c:8:
/usr/include/php/20170718/Zend/zend_compile.h:821:20: note: expected 'char *' but argument is of type 'const char *'
 ZEND_API zend_bool zend_is_auto_global_str(char *name, size_t len);
                    ^~~~~~~~~~~~~~~~~~~~~~~
/tmp/request-1.0.0b2/serverrequest.c: In function 'server_request_set_forwarded':
/tmp/request-1.0.0b2/serverrequest.c:643:9: warning: implicit declaration of function 'server_request_parse_forwarded'; did you mean 'server_request_parse_x_forwarded'? [-Wimplicit-function-declaration]
         server_request_parse_forwarded(&forwarded, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp));
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         server_request_parse_x_forwarded
/bin/bash /tmp/request-1.0.0b2/libtool --mode=link cc -DPHP_ATOM_INC -I/tmp/request-1.0.0b2/include -I/tmp/request-1.0.0b2/main -I/tmp/request-1.0.0b2 -I/usr/include/php/20170718 -I/usr/include/php/20170718/main -I/usr/include/php/20170718/TSRM -I/usr/include/php/20170718/Zend -I/usr/include/php/20170718/ext -I/usr/include/php/20170718/ext/date/lib  -DHAVE_CONFIG_H  -g -O2   -o request.la -export-dynamic -avoid-version -prefer-pic -module -rpath /tmp/request-1.0.0b2/modules  php_request.lo parsers.lo serverresponse.lo serverrequest.lo 
libtool: link: cc -shared  -fPIC -DPIC  .libs/php_request.o .libs/parsers.o .libs/serverresponse.o .libs/serverrequest.o    -g -O2   -Wl,-soname -Wl,request.so -o .libs/request.so
libtool: link: ( cd ".libs" && rm -f "request.la" && ln -s "../request.la" "request.la" )
/bin/bash /tmp/request-1.0.0b2/libtool --mode=install cp ./request.la /tmp/request-1.0.0b2/modules
libtool: install: cp ./.libs/request.so /tmp/request-1.0.0b2/modules/request.so
libtool: install: cp ./.libs/request.lai /tmp/request-1.0.0b2/modules/request.la
libtool: finish: PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/sbin" ldconfig -n /tmp/request-1.0.0b2/modules
----------------------------------------------------------------------
Libraries have been installed in:
   /tmp/request-1.0.0b2/modules

If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the '-LLIBDIR'
flag during linking and do at least one of the following:
   - add LIBDIR to the 'LD_LIBRARY_PATH' environment variable
     during execution
   - add LIBDIR to the 'LD_RUN_PATH' environment variable
     during linking
   - use the '-Wl,-rpath -Wl,LIBDIR' linker flag
   - have your system administrator add LIBDIR to '/etc/ld.so.conf'

See any operating system documentation about shared libraries for
more information, such as the ld(1) and ld.so(8) manual pages.
----------------------------------------------------------------------

Build complete.
Don't forget to run 'make test'.

Installing shared extensions:     /usr/lib/php/20170718/
root@746209f08f68:/tmp/request-1.0.0b2# make test
/bin/bash /tmp/request-1.0.0b2/libtool --mode=install cp ./request.la /tmp/request-1.0.0b2/modules
libtool: install: cp ./.libs/request.so /tmp/request-1.0.0b2/modules/request.so
libtool: install: cp ./.libs/request.lai /tmp/request-1.0.0b2/modules/request.la
libtool: finish: PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/sbin" ldconfig -n /tmp/request-1.0.0b2/modules
----------------------------------------------------------------------
Libraries have been installed in:
   /tmp/request-1.0.0b2/modules

If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the '-LLIBDIR'
flag during linking and do at least one of the following:
   - add LIBDIR to the 'LD_LIBRARY_PATH' environment variable
     during execution
   - add LIBDIR to the 'LD_RUN_PATH' environment variable
     during linking
   - use the '-Wl,-rpath -Wl,LIBDIR' linker flag
   - have your system administrator add LIBDIR to '/etc/ld.so.conf'

See any operating system documentation about shared libraries for
more information, such as the ld(1) and ld.so(8) manual pages.
----------------------------------------------------------------------

Build complete.
Don't forget to run 'make test'.


=====================================================================
PHP         : /usr/bin/php7.2 
PHP_SAPI    : cli
PHP_VERSION : 7.2.3-1ubuntu1
ZEND_VERSION: 3.2.0
PHP_OS      : Linux - Linux 746209f08f68 4.15.0-13-generic #14-Ubuntu SMP Sat Mar 17 13:44:27 UTC 2018 x86_64
INI actual  : /tmp/request-1.0.0b2/tmp-php.ini
More .INIs  :   
---------------------------------------------------------------------
PHP         : /usr/bin/phpdbg7.2 
PHP_SAPI    : phpdbg
PHP_VERSION : 7.2.3-1ubuntu1
ZEND_VERSION: 3.2.0
PHP_OS      : Linux - Linux 746209f08f68 4.15.0-13-generic #14-Ubuntu SMP Sat Mar 17 13:44:27 UTC 2018 x86_64
INI actual  : /tmp/request-1.0.0b2/tmp-php.ini
More .INIs  : 
---------------------------------------------------------------------
CWD         : /tmp/request-1.0.0b2
Extra dirs  : 
VALGRIND    : Not used
=====================================================================
TIME START 2018-04-07 09:30:51
=====================================================================
PASS request phpinfo [tests/phpinfo.phpt] 
PASS ServerRequest::__clone [tests/request/__clone.phpt] 
PASS ServerRequest::__construct [tests/request/__construct.phpt] 
PASS ServerRequest::__get extension indirect modification [tests/request/__get-extension.phpt] 
SKIP ServerRequest::__get userland indirect modification [tests/request/__get-userland.phpt] reason:  
PASS ServerRequest::__get [tests/request/__get.phpt] 
PASS ServerRequest::__isset [tests/request/__isset.phpt] 
PASS ServerRequest::__set [tests/request/__set.phpt] 
PASS ServerRequest::__unset [tests/request/__unset.phpt] 
PASS ServerRequest::$accept [tests/request/accept.phpt] 
PASS ServerRequest::$acceptCharset [tests/request/acceptCharset.phpt] 
PASS ServerRequest::$acceptEncoding [tests/request/acceptEncoding.phpt] 
PASS ServerRequest::$acceptLanguage [tests/request/acceptLanguage.phpt] 
PASS ServerRequest - basic auth [tests/request/auth_basic.phpt] 
PASS ServerRequest - digest auth [tests/request/auth_digest.phpt] 
PASS ServerRequest - auto_globals_jit [tests/request/auto_globals_jit.phpt] 
PASS ServerRequest::$content (cgi) [tests/request/content1.phpt] 
PASS ServerRequest::$content (cli) [tests/request/content2.phpt] 
PASS ServerRequest::$contentLength [tests/request/contentLength.phpt] 
PASS ServerRequest::$contentMd5 [tests/request/contentMd5.phpt] 
PASS ServerRequest::$contentType [tests/request/contentType.phpt] 
PASS ServerRequest::$cookie [tests/request/cookie.phpt] 
PASS ServerRequest::$env [tests/request/env.phpt] 
PASS ServerRequest::$files [tests/request/files.phpt] 
PASS ServerRequest::$forwarded (etc.) [tests/request/forward.phpt] 
PASS ServerRequest::$get [tests/request/get.phpt] 
PASS ServerRequest::$headers [tests/request/headers.phpt] 
PASS ServerRequest - inheritance [tests/request/inheritance.phpt] 
PASS ServerRequest::$method [tests/request/method.phpt] 
PASS ServerRequest::parseAccept [tests/request/parseAccept.phpt] 
PASS ServerRequest::parseContentType [tests/request/parseContentType.phpt] 
PASS ServerRequest::parseDigestAuth [tests/request/parseDigestAuth.phpt] 
PASS ServerRequest::$post [tests/request/post.phpt] 
PASS ServerRequest - superglobals are copied [tests/request/superglobals-are-copied.phpt] 
PASS ServerRequest::$uploads (complex) [tests/request/uploads-complex.phpt] 
PASS ServerRequest::$uploads (real) [tests/request/uploads-real.phpt] 
PASS ServerRequest::$uploads (trivial) [tests/request/uploads-trivial.phpt] 
PASS ServerRequest::$url [tests/request/url.phpt] 
PASS ServerRequest - variables_order [tests/request/variables_order.phpt] 
PASS ServerRequest::withInput [tests/request/withInput.phpt] 
PASS ServerRequest::withParam [tests/request/withParam.phpt] 
PASS ServerRequest::withParams [tests/request/withParams.phpt] 
PASS ServerRequest::withUrl [tests/request/withUrl.phpt] 
PASS ServerRequest::withoutParam [tests/request/withoutParam.phpt] 
PASS ServerRequest::withoutParams [tests/request/withoutParams.phpt] 
PASS ServerRequest::$xhr [tests/request/xhr.phpt] 
PASS ServerResponse::addHeader [tests/response/addHeader.phpt] 
PASS ServerResponse::addHeaderCallback [tests/response/addHeaderCallback.phpt] 
PASS ServerResponse::addHeader (array) [tests/response/addHeader_array.phpt] 
PASS ServerResponse::date [tests/response/date.phpt] 
PASS ServerResponse::date (invalid) [tests/response/date_invalid.phpt] 
PASS ServerResponse::getHeaderCallbacks [tests/response/getHeaderCallbacks.phpt] 
PASS ServerResponse::getStatus [tests/response/getStatus.phpt] 
PASS ServerResponse::getVersion [tests/response/getVersion.phpt] 
PASS ServerResponse::runHeaderCallback [tests/response/runHeaderCallbacks.phpt] 
PASS ServerResponse::sendContent (callable) [tests/response/sendContent_callable.phpt] 
PASS ServerResponse::sendContent (callable return value) [tests/response/sendContent_callableRV.phpt] 
PASS ServerResponse::sendContent (resource) [tests/response/sendContent_resource.phpt] 
PASS ServerResponse::sendContent (string) [tests/response/sendContent_string.phpt] 
PASS ServerResponse::sendCookies [tests/response/sendCookies.phpt] 
PASS ServerResponse::sendHeaders [tests/response/sendHeaders.phpt] 
PASS ServerResponse::sendStatus [tests/response/sendStatus.phpt] 
PASS ServerResponse::setContent [tests/response/setContent.phpt] 
FAIL ServerResponse::setContentDownload [tests/response/setContentDownload.phpt] 
FAIL ServerResponse::setContentResource (not resource) [tests/response/setContentDownload_notResource.phpt] 
FAIL ServerResponse::setContentJson [tests/response/setContentJson.phpt] 
FAIL ServerResponse::setContentJson (failed) [tests/response/setContentJson_failed.phpt] 
PASS ServerResponse::setCookie [tests/response/setCookie.phpt] 
PASS ServerResponse::setHeader [tests/response/setHeader.phpt] 
PASS ServerResponse::setHeader (array) [tests/response/setHeader_array.phpt] 
PASS ServerResponse::setStatus [tests/response/setStatus.phpt] 
PASS ServerResponse::setVersion [tests/response/setVersion.phpt] 
=====================================================================
TIME END 2018-04-07 09:30:52

=====================================================================
TEST RESULT SUMMARY
---------------------------------------------------------------------
Exts skipped    :    0
Exts tested     :   15
---------------------------------------------------------------------

Number of tests :   72                71
Tests skipped   :    1 (  1.4%) --------
Tests warned    :    0 (  0.0%) (  0.0%)
Tests failed    :    4 (  5.6%) (  5.6%)
Expected fail   :    0 (  0.0%) (  0.0%)
Tests passed    :   67 ( 93.1%) ( 94.4%)
---------------------------------------------------------------------
Time taken      :    1 seconds
=====================================================================

=====================================================================
FAILED TEST SUMMARY
---------------------------------------------------------------------
ServerResponse::setContentDownload [tests/response/setContentDownload.phpt]
ServerResponse::setContentResource (not resource) [tests/response/setContentDownload_notResource.phpt]
ServerResponse::setContentJson [tests/response/setContentJson.phpt]
ServerResponse::setContentJson (failed) [tests/response/setContentJson_failed.phpt]
=====================================================================

Update php-request to match

First off, kudos for trying again to get this added into the core. I have my doubts if it will be accepted but hope springs eternal.

I would suggest updating your userland php-request project to match as closely as possible. The idea is that it would be easier to install and test than an actual C extension. Might help with the acceptance process.

I know that not everything can transfer easily especially immutability but as long as it is close then it would be okay. Seeing exactly what it would take to, for example, have the Symfony Request object extend from this would be interesting.

Introduce SapiUpload class

The idea would be to replace each element of SapiRequest::$uploads that uses an array descriptor, with a SapiUpload instance.

The class should look something like this:

class SapiUpload
{
    public /* readonly ?string */ $name;

    public /* readonly ?string */ $name;

    public /* readonly ?int */ $size;

    public /* readonly ?string */ $tmpName;

    public /* readonly ?int */ $error;

    public function __construct(
        ?string $name,
        ?string $type,
        ?int $size,
        ?string $tmpName,
        ?int $error
    ) {
        $this->name = $name;
        $this->type = $type;
        $this->size = $size;
        $this->tmpName = $tmpName;
        $this->error = $error;
    }

    public function move(string $destination) : bool
    {
        return move_uploaded_file($this->tmpName, $destination);
    }
}

And SapiRequest, on building the $uploads array, should retain a new instance of SapiUpload instead of the file array descriptor.

PHP8 Compatibility?

@pmjones I'm not able to install this with PHP 8 via Pecl or manually. Is this a known issue or possibly a bug in the distro I'm using (Alpine 3.13).

Output from Pecl install:

creating libtool
appending configuration tag "CXX" to libtool
configure: patching config.h.in
configure: creating ./config.status
config.status: creating config.h
running: make
/bin/sh /tmp/pear/temp/pear-build-defaultuserpaiPPL/request-2.0.0/libtool --mode=compile cc -I. -I/tmp/pear/temp/request -I/tmp/pear/temp/pear-build-defaultuserpaiPPL/request-2.0.0/include -I/tmp/pear/temp/pear-build-defaultuserpaiPPL/request-2.0.0/main -I/tmp/pear/temp/request -I/usr/include/php8 -I/usr/include/php8/main -I/usr/include/php8/TSRM -I/usr/include/php8/Zend -I/usr/include/php8/ext -I/usr/include/php8/ext/date/lib  -DHAVE_CONFIG_H  -g -O2    -c /tmp/pear/temp/request/php_request.c -o php_request.lo
mkdir .libs
 cc -I. -I/tmp/pear/temp/request -I/tmp/pear/temp/pear-build-defaultuserpaiPPL/request-2.0.0/include -I/tmp/pear/temp/pear-build-defaultuserpaiPPL/request-2.0.0/main -I/tmp/pear/temp/request -I/usr/include/php8 -I/usr/include/php8/main -I/usr/include/php8/TSRM -I/usr/include/php8/Zend -I/usr/include/php8/ext -I/usr/include/php8/ext/date/lib -DHAVE_CONFIG_H -g -O2 -c /tmp/pear/temp/request/php_request.c  -fPIC -DPIC -o .libs/php_request.o
(cd /tmp/pear/temp/request;  --no-generation-date -o request_parsers.c request_parsers.re)
/bin/sh: --no-generation-date: not found
make: *** [Makefile:209: /tmp/pear/temp/request/request_parsers.c] Error 127
ERROR: `make' failed

Full install on Alpine:

apk add autoconf automake gcc g++ libstdc++ linux-headers make musl php8 php8-dev php8-pear
pecl8 install request

Let me know if any more info will help.

ServerResponseSender: add support for generators/iterable

I noticed ServerResponseSender doesn't seem to support generators as content.

$content = new class () {
    public function __invoke(): iterable
    {
        yield 'Hello ';
        yield 'world!';
    }
};

$response = new ServerResponse();
$response->setContent($content);

$sender = new ServerResponseSender();
$sender->send($response); // error: Object of class Generator could not be converted to string

My expectation would be no error in this case and "Hello world!" as the content. Is this a deliberate omission in the specification?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.