Compare commits
15 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
ca3bb2cb0a | |
|
|
c5f49214b5 | |
|
|
c153bc0028 | |
|
|
e22d5889b0 | |
|
|
fb2b2ab527 | |
|
|
00ea49ded6 | |
|
|
4c4b6104e4 | |
|
|
6b31620314 | |
|
|
e6bb814a76 | |
|
|
19c03b9b8b | |
|
|
b94b01453a | |
|
|
9db267c427 | |
|
|
8379dd69a0 | |
|
|
9a4b78b84a | |
|
|
2c80da2f79 |
59
.php_cs.dist
59
.php_cs.dist
|
|
@ -1,59 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
$finder = PhpCsFixer\Finder::create()
|
|
||||||
->files()
|
|
||||||
->in(__DIR__ . '/src')
|
|
||||||
->in(__DIR__ . '/tests');
|
|
||||||
|
|
||||||
return PhpCsFixer\Config::create()
|
|
||||||
->setFinder($finder)
|
|
||||||
->setRiskyAllowed(true)
|
|
||||||
->setRules([
|
|
||||||
'@PSR2' => true,
|
|
||||||
'align_multiline_comment' => true,
|
|
||||||
'array_syntax' => ['syntax' => 'short'],
|
|
||||||
'blank_line_after_opening_tag' => true,
|
|
||||||
'cast_spaces' => true,
|
|
||||||
'class_attributes_separation' => ['elements' => ['method']],
|
|
||||||
'global_namespace_import' => [
|
|
||||||
'import_classes' => true,
|
|
||||||
'import_constants' => true,
|
|
||||||
'import_functions' => true,
|
|
||||||
],
|
|
||||||
'linebreak_after_opening_tag' => true,
|
|
||||||
'lowercase_cast' => true,
|
|
||||||
'lowercase_static_reference' => true,
|
|
||||||
'method_chaining_indentation' => true,
|
|
||||||
'modernize_types_casting' => true,
|
|
||||||
'multiline_comment_opening_closing' => true,
|
|
||||||
'multiline_whitespace_before_semicolons' => true,
|
|
||||||
'native_function_casing' => true,
|
|
||||||
'no_alternative_syntax' => true,
|
|
||||||
'no_extra_blank_lines' => true,
|
|
||||||
'no_leading_import_slash' => true,
|
|
||||||
'no_mixed_echo_print' => ['use' => 'print'],
|
|
||||||
'no_short_bool_cast' => true,
|
|
||||||
'no_singleline_whitespace_before_semicolons' => true,
|
|
||||||
'no_spaces_around_offset' => true,
|
|
||||||
'no_trailing_comma_in_list_call' => true,
|
|
||||||
'no_trailing_comma_in_singleline_array' => true,
|
|
||||||
'no_unneeded_control_parentheses' => true,
|
|
||||||
'no_unused_imports' => true,
|
|
||||||
'no_useless_return' => true,
|
|
||||||
'no_whitespace_before_comma_in_array' => true,
|
|
||||||
'no_whitespace_in_blank_line' => true,
|
|
||||||
'normalize_index_brace' => true,
|
|
||||||
'nullable_type_declaration_for_default_null_value' => true,
|
|
||||||
'ordered_imports' => [
|
|
||||||
'sort_algorithm' => 'alpha'
|
|
||||||
],
|
|
||||||
'ordered_interfaces' => [
|
|
||||||
'direction' => 'ascend',
|
|
||||||
'order' => 'alpha',
|
|
||||||
],
|
|
||||||
'single_quote' => true,
|
|
||||||
'space_after_semicolon' => true,
|
|
||||||
'standardize_not_equals' => true,
|
|
||||||
'ternary_operator_spaces' => true,
|
|
||||||
'ternary_to_null_coalescing' => true
|
|
||||||
]);
|
|
||||||
11
.travis.yml
11
.travis.yml
|
|
@ -1,11 +0,0 @@
|
||||||
language: php
|
|
||||||
php:
|
|
||||||
- "7.3"
|
|
||||||
- "7.4"
|
|
||||||
|
|
||||||
before_script:
|
|
||||||
- composer selfupdate
|
|
||||||
- composer install --prefer-source
|
|
||||||
|
|
||||||
script:
|
|
||||||
- vendor/bin/phpunit
|
|
||||||
|
|
@ -1,12 +1,13 @@
|
||||||
WellRESTed
|
WellRESTed
|
||||||
==========
|
==========
|
||||||
|
|
||||||
[](https://php.net/)
|
[](https://php.net/)
|
||||||
[](https://travis-ci.org/wellrestedphp/wellrested)
|
|
||||||
[](http://wellrested.readthedocs.org/en/latest/)
|
[](http://wellrested.readthedocs.org/en/latest/)
|
||||||
|
|
||||||
WellRESTed is a library for creating RESTful APIs and websites in PHP that provides abstraction for HTTP messages, a powerful handler and middleware system, and a flexible router.
|
WellRESTed is a library for creating RESTful APIs and websites in PHP that provides abstraction for HTTP messages, a powerful handler and middleware system, and a flexible router.
|
||||||
|
|
||||||
|
This fork (basemaster/wellrested) is back to php 7.2 release.
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
- Uses [PSR-7](https://www.php-fig.org/psr/psr-7/) interfaces for requests, responses, and streams. This lets you use other PSR-7 compatable libraries seamlessly with WellRESTed.
|
- Uses [PSR-7](https://www.php-fig.org/psr/psr-7/) interfaces for requests, responses, and streams. This lets you use other PSR-7 compatable libraries seamlessly with WellRESTed.
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "wellrested/wellrested",
|
"name": "basemaster/wellrested",
|
||||||
"description": "Simple PHP Library for RESTful APIs",
|
"description": "Clone for Simple PHP Library for RESTful APIs (wellrested.org)",
|
||||||
"keywords": ["rest", "restful", "api", "http", "psr7", "psr-7", "psr15", "psr-15", "psr17", "psr-17"],
|
"keywords": ["rest", "restful", "api", "http", "psr7", "psr-7", "psr15", "psr-15", "psr17", "psr-17"],
|
||||||
"homepage": "https://www.wellrested.org",
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"authors": [
|
"authors": [
|
||||||
|
|
@ -12,27 +11,19 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=7.3",
|
"php": ">=7.2",
|
||||||
"psr/http-factory": "~1.0",
|
"psr/http-factory": "~1.0",
|
||||||
"psr/http-message": "~1.0",
|
"psr/http-message": "~1.0",
|
||||||
"psr/http-server-handler": "~1.0",
|
"psr/http-server-handler": "~1.0",
|
||||||
"psr/http-server-middleware": "~1.0"
|
"psr/http-server-middleware": "~1.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"provide": {
|
||||||
"friendsofphp/php-cs-fixer": "^2",
|
"psr/http-message-implementation": "1.0",
|
||||||
"phpspec/prophecy-phpunit": "^2.0",
|
"psr/http-factory-implementation": "1.0"
|
||||||
"phpunit/phpunit": "^9",
|
|
||||||
"vimeo/psalm": "^3.4"
|
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"WellRESTed\\": "src/"
|
"WellRESTed\\": "src/"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"autoload-dev": {
|
|
||||||
"psr-4": {
|
|
||||||
"WellRESTed\\": "tests",
|
|
||||||
"WellRESTed\\Test\\": "tests"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,27 +0,0 @@
|
||||||
version: '3.7'
|
|
||||||
services:
|
|
||||||
|
|
||||||
# PHPUnit and Composer
|
|
||||||
php:
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
dockerfile: ./docker/php/Dockerfile
|
|
||||||
volumes:
|
|
||||||
- .:/usr/local/src/wellrested
|
|
||||||
|
|
||||||
# Documentation generator
|
|
||||||
docs:
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
dockerfile: ./docker/docs/Dockerfile
|
|
||||||
volumes:
|
|
||||||
- .:/usr/local/src/wellrested
|
|
||||||
|
|
||||||
# Local development site
|
|
||||||
nginx:
|
|
||||||
image: nginx:1.15
|
|
||||||
ports:
|
|
||||||
- ${PORT:-8080}:80
|
|
||||||
volumes:
|
|
||||||
- .:/usr/local/src/wellrested
|
|
||||||
- ./docker/nginx/site.conf:/etc/nginx/conf.d/default.conf
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
FROM python:3-jessie
|
|
||||||
|
|
||||||
RUN pip install sphinx sphinx_rtd_theme
|
|
||||||
|
|
||||||
WORKDIR /usr/local/src/wellrested
|
|
||||||
|
|
||||||
CMD ["make", "html", "-C", "docs"]
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
server {
|
|
||||||
listen 80;
|
|
||||||
|
|
||||||
root /usr/local/src/wellrested/public;
|
|
||||||
index index.php index.html;
|
|
||||||
charset utf-8;
|
|
||||||
|
|
||||||
access_log /var/log/nginx/access.log;
|
|
||||||
error_log /var/log/nginx/error.log;
|
|
||||||
|
|
||||||
# Front Controller
|
|
||||||
location / {
|
|
||||||
try_files $uri $uri/ /index.php?$args;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Generated Code Coverage Report
|
|
||||||
location /coverage {
|
|
||||||
alias /usr/local/src/wellrested/coverage;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Generated Documentation
|
|
||||||
location /docs {
|
|
||||||
alias /usr/local/src/wellrested/docs/build/html;
|
|
||||||
}
|
|
||||||
|
|
||||||
# PHP
|
|
||||||
location ~ \.php$ {
|
|
||||||
include fastcgi_params;
|
|
||||||
fastcgi_pass php:9000;
|
|
||||||
fastcgi_index index.php;
|
|
||||||
fastcgi_buffers 8 8k;
|
|
||||||
fastcgi_buffer_size 16k;
|
|
||||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
|
||||||
fastcgi_param SCRIPT_NAME index.php;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,44 +0,0 @@
|
||||||
FROM php:7.3-fpm
|
|
||||||
|
|
||||||
RUN DEBIAN_FRONTEND=noninteractive \
|
|
||||||
apt-get update && \
|
|
||||||
apt-get -y install \
|
|
||||||
gettext \
|
|
||||||
libssl-dev \
|
|
||||||
unzip \
|
|
||||||
wget \
|
|
||||||
zip \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
# Install Xdebug
|
|
||||||
RUN yes | pecl install xdebug \
|
|
||||||
&& echo "zend_extension=$(find /usr/local/lib/php/extensions/ -name xdebug.so)" > /usr/local/etc/php/conf.d/xdebug.ini
|
|
||||||
|
|
||||||
# Install Composer.
|
|
||||||
RUN curl -sS https://getcomposer.org/installer | php -- \
|
|
||||||
--filename=composer --install-dir=/usr/local/bin
|
|
||||||
|
|
||||||
# Install dumb-init.
|
|
||||||
RUN wget -O /usr/local/bin/dumb-init https://github.com/Yelp/dumb-init/releases/download/v1.2.1/dumb-init_1.2.1_amd64
|
|
||||||
RUN chmod +x /usr/local/bin/dumb-init
|
|
||||||
|
|
||||||
# Create a directory for project sources and user's home directory
|
|
||||||
RUN mkdir /usr/local/src/wellrested && \
|
|
||||||
chown -R www-data:www-data /usr/local/src/wellrested && \
|
|
||||||
chown -R www-data:www-data /var/www
|
|
||||||
|
|
||||||
# Copy entrypoint script
|
|
||||||
COPY docker/php/entrypoint /usr/local/bin
|
|
||||||
|
|
||||||
# Add symlinks for php-cs-fixer, phpunit, and psalm for easier running
|
|
||||||
RUN ln -s /usr/local/src/wellrested/vendor/bin/php-cs-fixer /usr/local/bin/php-cs-fixer
|
|
||||||
RUN ln -s /usr/local/src/wellrested/vendor/bin/phpunit /usr/local/bin/phpunit
|
|
||||||
RUN ln -s /usr/local/src/wellrested/vendor/bin/psalm /usr/local/bin/psalm
|
|
||||||
|
|
||||||
ENTRYPOINT ["entrypoint"]
|
|
||||||
|
|
||||||
CMD ["php-fpm"]
|
|
||||||
|
|
||||||
WORKDIR /usr/local/src/wellrested
|
|
||||||
|
|
||||||
USER www-data
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# Run CLI commands with dumb-init to allow better signal handling.
|
|
||||||
# Run PHP-FPM as PID 1.
|
|
||||||
# https://engineeringblog.yelp.com/2016/01/dumb-init-an-init-for-docker.html
|
|
||||||
if [ "$1" == 'php-fpm' ] ; then
|
|
||||||
exec php-fpm
|
|
||||||
else
|
|
||||||
exec dumb-init -- "$@"
|
|
||||||
fi
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
EXPECTED_SIGNATURE=$(wget https://composer.github.io/installer.sig -O - -q)
|
|
||||||
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
|
|
||||||
ACTUAL_SIGNATURE=$(php -r "echo hash_file('SHA384', 'composer-setup.php');")
|
|
||||||
|
|
||||||
if [ "$EXPECTED_SIGNATURE" != "$ACTUAL_SIGNATURE" ]; then
|
|
||||||
>&2 echo 'ERROR: Invalid installer signature'
|
|
||||||
rm composer-setup.php
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
php composer-setup.php --quiet --filename=composer --install-dir=/usr/local/bin
|
|
||||||
RESULT=$?
|
|
||||||
rm composer-setup.php
|
|
||||||
exit $RESULT
|
|
||||||
|
|
@ -25,7 +25,7 @@ master_doc = 'index'
|
||||||
|
|
||||||
# General information about the project.
|
# General information about the project.
|
||||||
project = u'WellRESTed'
|
project = u'WellRESTed'
|
||||||
copyright = u'202, PJ Dietz'
|
copyright = u'2021, PJ Dietz'
|
||||||
version = '5.0.0'
|
version = '5.0.0'
|
||||||
release = '5.0.0'
|
release = '5.0.0'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ Licensed using the `MIT license <http://opensource.org/licenses/MIT>`_.
|
||||||
|
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2018 PJ Dietz
|
Copyright (c) 2021 PJ Dietz
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd"
|
|
||||||
colors="true"
|
|
||||||
convertErrorsToExceptions="true"
|
|
||||||
convertNoticesToExceptions="true"
|
|
||||||
convertWarningsToExceptions="true"
|
|
||||||
processIsolation="false"
|
|
||||||
stopOnFailure="false"
|
|
||||||
verbose="true"
|
|
||||||
>
|
|
||||||
<testsuites>
|
|
||||||
<testsuite name="unit">
|
|
||||||
<directory>./tests</directory>
|
|
||||||
</testsuite>
|
|
||||||
</testsuites>
|
|
||||||
<filter>
|
|
||||||
<whitelist>
|
|
||||||
<directory suffix=".php">./src</directory>
|
|
||||||
</whitelist>
|
|
||||||
</filter>
|
|
||||||
<logging>
|
|
||||||
<log type="coverage-html" target="./coverage" />
|
|
||||||
</logging>
|
|
||||||
</phpunit>
|
|
||||||
29
psalm.xml
29
psalm.xml
|
|
@ -1,29 +0,0 @@
|
||||||
<?xml version="1.0"?>
|
|
||||||
<psalm
|
|
||||||
errorLevel="2"
|
|
||||||
resolveFromConfigFile="true"
|
|
||||||
allowStringToStandInForClass="true"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xmlns="https://getpsalm.org/schema/config"
|
|
||||||
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
|
|
||||||
>
|
|
||||||
<projectFiles>
|
|
||||||
<directory name="src" />
|
|
||||||
<ignoreFiles>
|
|
||||||
<directory name="vendor" />
|
|
||||||
</ignoreFiles>
|
|
||||||
</projectFiles>
|
|
||||||
<issueHandlers>
|
|
||||||
<DocblockTypeContradiction>
|
|
||||||
<errorLevel type="suppress">
|
|
||||||
<file name="src/Message/ServerRequest.php" />
|
|
||||||
<file name="src/Message/Uri.php" />
|
|
||||||
</errorLevel>
|
|
||||||
</DocblockTypeContradiction>
|
|
||||||
<MissingClosureParamType>
|
|
||||||
<errorLevel type="suppress">
|
|
||||||
<file name="src/Message/Message.php" />
|
|
||||||
</errorLevel>
|
|
||||||
</MissingClosureParamType>
|
|
||||||
</issueHandlers>
|
|
||||||
</psalm>
|
|
||||||
|
|
@ -7,7 +7,7 @@ use Iterator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HeaderCollection provides case-insensitive access to lists of header values.
|
* HeaderCollection provides case-insensitive access to lists of header values.
|
||||||
**
|
*
|
||||||
* HeaderCollection preserves the cases of keys as they are set, but treats key
|
* HeaderCollection preserves the cases of keys as they are set, but treats key
|
||||||
* access case insensitively.
|
* access case insensitively.
|
||||||
*
|
*
|
||||||
|
|
@ -51,7 +51,7 @@ class HeaderCollection implements ArrayAccess, Iterator
|
||||||
* @param string $offset
|
* @param string $offset
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function offsetExists($offset)
|
public function offsetExists($offset): bool
|
||||||
{
|
{
|
||||||
return isset($this->values[strtolower($offset)]);
|
return isset($this->values[strtolower($offset)]);
|
||||||
}
|
}
|
||||||
|
|
@ -60,7 +60,7 @@ class HeaderCollection implements ArrayAccess, Iterator
|
||||||
* @param mixed $offset
|
* @param mixed $offset
|
||||||
* @return string[]
|
* @return string[]
|
||||||
*/
|
*/
|
||||||
public function offsetGet($offset)
|
public function offsetGet($offset): array
|
||||||
{
|
{
|
||||||
return $this->values[strtolower($offset)];
|
return $this->values[strtolower($offset)];
|
||||||
}
|
}
|
||||||
|
|
@ -69,7 +69,7 @@ class HeaderCollection implements ArrayAccess, Iterator
|
||||||
* @param string $offset
|
* @param string $offset
|
||||||
* @param string $value
|
* @param string $value
|
||||||
*/
|
*/
|
||||||
public function offsetSet($offset, $value)
|
public function offsetSet($offset, $value): void
|
||||||
{
|
{
|
||||||
$normalized = strtolower($offset);
|
$normalized = strtolower($offset);
|
||||||
|
|
||||||
|
|
@ -92,7 +92,7 @@ class HeaderCollection implements ArrayAccess, Iterator
|
||||||
/**
|
/**
|
||||||
* @param string $offset
|
* @param string $offset
|
||||||
*/
|
*/
|
||||||
public function offsetUnset($offset)
|
public function offsetUnset($offset): void
|
||||||
{
|
{
|
||||||
$normalized = strtolower($offset);
|
$normalized = strtolower($offset);
|
||||||
unset($this->fields[$normalized]);
|
unset($this->fields[$normalized]);
|
||||||
|
|
@ -107,27 +107,30 @@ class HeaderCollection implements ArrayAccess, Iterator
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
// Iterator
|
// Iterator
|
||||||
|
|
||||||
public function current()
|
/**
|
||||||
|
* @return string[]
|
||||||
|
*/
|
||||||
|
public function current(): array
|
||||||
{
|
{
|
||||||
return $this->values[$this->keys[$this->position]];
|
return $this->values[$this->keys[$this->position]];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function next()
|
public function next(): void
|
||||||
{
|
{
|
||||||
++$this->position;
|
++$this->position;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function key()
|
public function key(): string
|
||||||
{
|
{
|
||||||
return $this->fields[$this->keys[$this->position]];
|
return $this->fields[$this->keys[$this->position]];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function valid()
|
public function valid(): bool
|
||||||
{
|
{
|
||||||
return isset($this->keys[$this->position]);
|
return isset($this->keys[$this->position]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function rewind()
|
public function rewind(): void
|
||||||
{
|
{
|
||||||
$this->position = 0;
|
$this->position = 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -195,7 +195,7 @@ class Request extends Message implements RequestInterface
|
||||||
$request = clone $this;
|
$request = clone $this;
|
||||||
|
|
||||||
$newHost = $uri->getHost();
|
$newHost = $uri->getHost();
|
||||||
$oldHost = isset($request->headers['Host']) ? $request->headers['Host'] : '';
|
$oldHost = $request->headers['Host'] ?? '';
|
||||||
|
|
||||||
if ($preserveHost === false) {
|
if ($preserveHost === false) {
|
||||||
// Update Host
|
// Update Host
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace WellRESTed\Message;
|
||||||
|
|
||||||
|
use Psr\Http\Message\RequestFactoryInterface;
|
||||||
|
use Psr\Http\Message\RequestInterface;
|
||||||
|
use Psr\Http\Message\UriInterface;
|
||||||
|
|
||||||
|
class RequestFactory implements RequestFactoryInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Create a new request.
|
||||||
|
*
|
||||||
|
* @param string $method The HTTP method associated with the request.
|
||||||
|
* @param UriInterface|string $uri The URI associated with the request. If
|
||||||
|
* the value is a string, the factory MUST create a UriInterface
|
||||||
|
* instance based on it.
|
||||||
|
*
|
||||||
|
* @return RequestInterface
|
||||||
|
*/
|
||||||
|
public function createRequest(string $method, $uri): RequestInterface
|
||||||
|
{
|
||||||
|
return new Request($method, $uri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -117,21 +117,21 @@ class UploadedFile implements UploadedFileInterface
|
||||||
*
|
*
|
||||||
* @see http://php.net/is_uploaded_file
|
* @see http://php.net/is_uploaded_file
|
||||||
* @see http://php.net/move_uploaded_file
|
* @see http://php.net/move_uploaded_file
|
||||||
* @param string $path Path to which to move the uploaded file.
|
* @param string $targetPath Path to which to move the uploaded file.
|
||||||
* @return void
|
* @return void
|
||||||
* @throws InvalidArgumentException if the $path specified is invalid.
|
* @throws InvalidArgumentException if the $path specified is invalid.
|
||||||
* @throws RuntimeException on any error during the move operation, or on
|
* @throws RuntimeException on any error during the move operation, or on
|
||||||
* the second or subsequent call to the method.
|
* the second or subsequent call to the method.
|
||||||
*/
|
*/
|
||||||
public function moveTo($path)
|
public function moveTo($targetPath)
|
||||||
{
|
{
|
||||||
if ($this->tmpName === null || !file_exists($this->tmpName)) {
|
if ($this->tmpName === null || !file_exists($this->tmpName)) {
|
||||||
throw new RuntimeException("File {$this->tmpName} does not exist.");
|
throw new RuntimeException("File {$this->tmpName} does not exist.");
|
||||||
}
|
}
|
||||||
if (php_sapi_name() === 'cli') {
|
if (php_sapi_name() === 'cli') {
|
||||||
rename($this->tmpName, $path);
|
rename($this->tmpName, $targetPath);
|
||||||
} else {
|
} else {
|
||||||
move_uploaded_file($this->tmpName, $path);
|
move_uploaded_file($this->tmpName, $targetPath);
|
||||||
}
|
}
|
||||||
$this->moved = true;
|
$this->moved = true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -292,7 +292,7 @@ class Uri implements UriInterface
|
||||||
*/
|
*/
|
||||||
public function withScheme($scheme)
|
public function withScheme($scheme)
|
||||||
{
|
{
|
||||||
$scheme = $scheme ? strtolower($scheme) : '';
|
$scheme = strtolower($scheme ?? '');
|
||||||
if (!in_array($scheme, ['', 'http', 'https'])) {
|
if (!in_array($scheme, ['', 'http', 'https'])) {
|
||||||
throw new InvalidArgumentException('Scheme must be http, https, or empty.');
|
throw new InvalidArgumentException('Scheme must be http, https, or empty.');
|
||||||
}
|
}
|
||||||
|
|
@ -446,7 +446,7 @@ class Uri implements UriInterface
|
||||||
public function withFragment($fragment)
|
public function withFragment($fragment)
|
||||||
{
|
{
|
||||||
$uri = clone $this;
|
$uri = clone $this;
|
||||||
$uri->fragment = $fragment;
|
$uri->fragment = $fragment ?? '';
|
||||||
return $uri;
|
return $uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -520,7 +520,7 @@ class Uri implements UriInterface
|
||||||
* @param string $subject
|
* @param string $subject
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
private function percentEncode($subject)
|
private function percentEncode(string $subject)
|
||||||
{
|
{
|
||||||
$reserved = ':/?#[]@!$&\'()*+,;=';
|
$reserved = ':/?#[]@!$&\'()*+,;=';
|
||||||
$reserved = preg_quote($reserved);
|
$reserved = preg_quote($reserved);
|
||||||
|
|
|
||||||
|
|
@ -78,22 +78,21 @@ class Router implements MiddlewareInterface
|
||||||
ResponseInterface $response,
|
ResponseInterface $response,
|
||||||
$next
|
$next
|
||||||
): ResponseInterface {
|
): ResponseInterface {
|
||||||
// Use only the path for routing.
|
$path = $this->getPath($request->getRequestTarget());
|
||||||
$requestTarget = parse_url($request->getRequestTarget(), PHP_URL_PATH);
|
|
||||||
|
|
||||||
$route = $this->getStaticRoute($requestTarget);
|
$route = $this->getStaticRoute($path);
|
||||||
if ($route) {
|
if ($route) {
|
||||||
return $this->dispatch($route, $request, $response, $next);
|
return $this->dispatch($route, $request, $response, $next);
|
||||||
}
|
}
|
||||||
|
|
||||||
$route = $this->getPrefixRoute($requestTarget);
|
$route = $this->getPrefixRoute($path);
|
||||||
if ($route) {
|
if ($route) {
|
||||||
return $this->dispatch($route, $request, $response, $next);
|
return $this->dispatch($route, $request, $response, $next);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try each of the routes.
|
// Try each of the routes.
|
||||||
foreach ($this->patternRoutes as $route) {
|
foreach ($this->patternRoutes as $route) {
|
||||||
if ($route->matchesRequestTarget($requestTarget)) {
|
if ($route->matchesRequestTarget($path)) {
|
||||||
$pathVariables = $route->getPathVariables();
|
$pathVariables = $route->getPathVariables();
|
||||||
if ($this->pathVariablesAttributeName) {
|
if ($this->pathVariablesAttributeName) {
|
||||||
$request = $request->withAttribute($this->pathVariablesAttributeName, $pathVariables);
|
$request = $request->withAttribute($this->pathVariablesAttributeName, $pathVariables);
|
||||||
|
|
@ -113,6 +112,15 @@ class Router implements MiddlewareInterface
|
||||||
return $next($request, $response);
|
return $next($request, $response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getPath(string $requestTarget): string
|
||||||
|
{
|
||||||
|
$queryStart = strpos($requestTarget, '?');
|
||||||
|
if ($queryStart === false) {
|
||||||
|
return $requestTarget;
|
||||||
|
}
|
||||||
|
return substr($requestTarget, 0, $queryStart);
|
||||||
|
}
|
||||||
|
|
||||||
private function dispatch(
|
private function dispatch(
|
||||||
callable $route,
|
callable $route,
|
||||||
ServerRequestInterface $request,
|
ServerRequestInterface $request,
|
||||||
|
|
@ -270,7 +278,7 @@ class Router implements MiddlewareInterface
|
||||||
usort($matches, $compareByLength);
|
usort($matches, $compareByLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
$bestMatch = $matches[0];
|
$bestMatch = array_values($matches)[0];
|
||||||
return $this->prefixRoutes[$bestMatch];
|
return $this->prefixRoutes[$bestMatch];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -291,7 +291,8 @@ class RouterTest extends TestCase
|
||||||
|
|
||||||
public function testMatchesPathAgainstRouteWithoutQuery(): void
|
public function testMatchesPathAgainstRouteWithoutQuery(): void
|
||||||
{
|
{
|
||||||
$target = '/my/path?cat=molly&dog=bear';
|
$path = '/my/path';
|
||||||
|
$target = $path . '?cat=molly&dog=bear';
|
||||||
|
|
||||||
$this->request = $this->request->withRequestTarget($target);
|
$this->request = $this->request->withRequestTarget($target);
|
||||||
|
|
||||||
|
|
@ -299,11 +300,28 @@ class RouterTest extends TestCase
|
||||||
$this->route->getType()->willReturn(Route::TYPE_PATTERN);
|
$this->route->getType()->willReturn(Route::TYPE_PATTERN);
|
||||||
$this->route->matchesRequestTarget(Argument::cetera())->willReturn(true);
|
$this->route->matchesRequestTarget(Argument::cetera())->willReturn(true);
|
||||||
|
|
||||||
$this->router->register('GET', $target, 'middleware');
|
$this->router->register('GET', $path, 'middleware');
|
||||||
|
|
||||||
$this->dispatch();
|
$this->dispatch();
|
||||||
|
|
||||||
$this->route->matchesRequestTarget('/my/path')->shouldHaveBeenCalled();
|
$this->route->matchesRequestTarget($path)->shouldHaveBeenCalled();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMatchesPathWithDuplicateLeadingSlashes(): void
|
||||||
|
{
|
||||||
|
$path = '//my/path';
|
||||||
|
|
||||||
|
$this->request = $this->request->withRequestTarget($path);
|
||||||
|
|
||||||
|
$this->route->getTarget()->willReturn($path);
|
||||||
|
$this->route->getType()->willReturn(Route::TYPE_PATTERN);
|
||||||
|
$this->route->matchesRequestTarget(Argument::cetera())->willReturn(true);
|
||||||
|
|
||||||
|
$this->router->register('GET', $path, 'middleware');
|
||||||
|
|
||||||
|
$this->dispatch();
|
||||||
|
|
||||||
|
$this->route->matchesRequestTarget($path)->shouldHaveBeenCalled();
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue