Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
7
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Switch to GitLab Next
Sign in / Register
Toggle navigation
Open sidebar
1of0
php
curly
Commits
1b82381e
Commit
1b82381e
authored
Mar 18, 2020
by
TheBigB
Browse files
Consistency fixes
parent
75266b18
Pipeline
#127580020
passed with stage
in 2 minutes and 21 seconds
Changes
10
Pipelines
3
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
168 additions
and
129 deletions
+168
-129
.gitignore
.gitignore
+1
-0
README.md
README.md
+20
-5
src/BinarySafe.php
src/BinarySafe.php
+2
-0
src/Curly.php
src/Curly.php
+6
-10
src/CurlyOptions.php
src/CurlyOptions.php
+6
-14
src/Exceptions/NotSupportedException.php
src/Exceptions/NotSupportedException.php
+0
-9
src/ExtendedServerRequest.php
src/ExtendedServerRequest.php
+4
-2
src/Handlers/AbstractHandler.php
src/Handlers/AbstractHandler.php
+6
-81
src/Handlers/HandlerInterface.php
src/Handlers/HandlerInterface.php
+114
-0
tests/HandlerTest.php
tests/HandlerTest.php
+9
-8
No files found.
.gitignore
View file @
1b82381e
.idea
vendor
ci/.phpunit*
README.md
View file @
1b82381e
...
...
@@ -12,21 +12,32 @@ To execute requests you may provide a URL and HTTP method, but you may also prov
```
php
<?php
use
OneOfZero\Curly\Curly
;
$curly
=
new
Curly
();
// Using PSR-7 RequestInterface implementation
$request
=
(
new
Request
)
->
withMethod
(
Curly
::
HTTP_
POST
)
->
withUri
(
new
Uri
(
'http://example.com'
))
$request
=
(
new
Laminas\Diactoros\
Request
)
->
withMethod
(
'
POST
'
)
->
withUri
(
new
Laminas\Diactoros\
Uri
(
'http
s
://example.com'
))
->
withHeader
(
'Accepts'
,
'application/json'
);
$response
=
$curly
->
request
(
$request
);
// Using plain URL and method
$response
=
$curly
->
requestByUrl
(
'http://example.com'
,
Curly
::
HTTP_DELETE
);
$response
=
$curly
->
requestByUrl
(
'https://example.com'
,
'DELETE'
);
// Using ExtendedServerRequest
$request
=
(
new
\
OneOfZero\Curly\ExtendedServerRequest
)
->
withUriString
(
'https://example.com'
,
'resource'
,
'1337'
)
->
withMethod
(
'POST'
)
->
withUrlEncodedForm
([
'foo'
=>
'bar'
])
->
withHeader
(
'Accepts'
,
'application/json'
);
$response
=
$curly
->
request
(
$request
);
```
By default the
`requestByUrl()`
and
`request()`
methods will return a
`ResponseInterface`
. To process the response
By default
,
the
`requestByUrl()`
and
`request()`
methods will return a
`ResponseInterface`
. To process the response
manually, you may configure callbacks or configure a custom handler (which under water will configure callbacks, but
provides a cleaner programming interface).
...
...
@@ -47,3 +58,7 @@ routed to the handler, which in turn invokes the callback to determine whether t
The
`StreamHandler`
decorates the
`CancellableHandler`
and is an example of a handler that hooks into cURL's read and
write callbacks. It probably isn't very useful since setting the
`inputStream`
and
`outputStream`
options in the
`CurlyOptions`
object would achieve more or less the same, but helps demonstrate the usage of the callbacks.
The power of the streams is that it allows you to read/write downloads and
uploads in chunks. Combined with streams you can prevent memory exhaustion
when handling large amounts of data.
src/BinarySafe.php
View file @
1b82381e
<?php
/** @noinspection PhpComposerExtensionStubsInspection */
namespace
OneOfZero\Curly
;
use
Psr\Http\Message\StreamInterface
;
...
...
src/Curly.php
View file @
1b82381e
...
...
@@ -3,7 +3,7 @@
namespace
OneOfZero\Curly
;
use
OneOfZero\Curly\Exceptions\CurlException
;
use
OneOfZero\Curly\Handlers\
AbstractHandler
;
use
OneOfZero\Curly\Handlers\
HandlerInterface
;
use
OneOfZero\Streams\SharedStreamInterface
;
use
Psr\Http\Message\RequestInterface
;
use
Psr\Http\Message\ResponseInterface
;
...
...
@@ -29,7 +29,7 @@ class Curly implements HttpClientInterface
/**
* Holds the configured handler (if any).
*
* @var
AbstractHandler
;
* @var
HandlerInterface
;
*/
private
$customHandler
;
...
...
@@ -236,8 +236,6 @@ class Curly implements HttpClientInterface
return
$headers
;
}
#region // Generic getters and setters
/**
* Gets the CurlyOptions for this instance.
*
...
...
@@ -264,9 +262,9 @@ class Curly implements HttpClientInterface
/**
* Gets the custom handler for this instance (if any).
*
* @return
AbstractHandler
* @return
HandlerInterface
*/
public
function
getCustomHandler
():
?
AbstractHandler
public
function
getCustomHandler
():
?
HandlerInterface
{
return
$this
->
customHandler
;
}
...
...
@@ -274,12 +272,10 @@ class Curly implements HttpClientInterface
/**
* Sets the custom handler for this instance.
*
* @param
AbstractHandler
$customHandler
* @param
HandlerInterface
$customHandler
*/
public
function
setCustomHandler
(
AbstractHandler
$customHandler
):
void
public
function
setCustomHandler
(
HandlerInterface
$customHandler
):
void
{
$this
->
customHandler
=
$customHandler
;
}
#endregion
}
src/CurlyOptions.php
View file @
1b82381e
<?php
/** @noinspection PhpUnused */
namespace
OneOfZero\Curly
;
use
ReflectionClass
;
...
...
@@ -408,7 +410,7 @@ class CurlyOptions
/**
* CURLOPT_STDERR (resource)
* @link http://curl.haxx.se/libcurl/c/CURLOPT_STDERR.html
* @var
R
esource $errorStream
* @var
r
esource $errorStream
*/
public
$errorStream
;
...
...
@@ -539,21 +541,21 @@ class CurlyOptions
/**
* CURLOPT_FILE (resource)
* @link http://curl.haxx.se/libcurl/c/CURLOPT_FILE.html
* @var
R
esource $outputStream
* @var
r
esource $outputStream
*/
public
$outputStream
;
/**
* CURLOPT_INFILE (resource)
* @link http://curl.haxx.se/libcurl/c/CURLOPT_INFILE.html
* @var
R
esource $inputStream
* @var
r
esource $inputStream
*/
public
$inputStream
;
/**
* CURLOPT_WRITEHEADER (resource)
* @link http://curl.haxx.se/libcurl/c/CURLOPT_WRITEHEADER.html
* @var
R
esource $outputHeaderStream
* @var
r
esource $outputHeaderStream
*/
public
$outputHeaderStream
;
...
...
@@ -682,16 +684,6 @@ class CurlyOptions
}
}
/**
* Creates and returns a clone of this object.
*
* @return CurlyOptions
*/
public
function
__clone
()
{
return
new
CurlyOptions
(
$this
->
toArray
(
false
));
}
/**
* Converts the options configured in this object to an array that is compatible with curl_setopt_array().
*
...
...
src/Exceptions/NotSupportedException.php
deleted
100644 → 0
View file @
75266b18
<?php
namespace
OneOfZero\Curly\Exceptions
;
use
Exception
;
class
NotSupportedException
extends
Exception
{
}
src/ExtendedServerRequest.php
View file @
1b82381e
...
...
@@ -21,9 +21,11 @@ class ExtendedServerRequest extends ServerRequest
public
function
withUriString
(...
$pieces
):
self
{
// TODO: Fix this properly - https://tools.ietf.org/html/rfc3986#section-5.2
$pieces
=
array_map
(
function
(
$item
)
{
return
trim
(
$item
,
'/'
);
},
$pieces
);
$pieces
=
array_map
(
static
function
(
$item
)
{
return
trim
(
$item
,
'/'
);
},
$pieces
);
return
$this
->
withUri
(
new
Uri
(
implode
(
'/'
,
$pieces
)));
/** @var self $request */
$request
=
$this
->
withUri
(
new
Uri
(
implode
(
'/'
,
$pieces
)));
return
$request
;
}
/**
...
...
src/Handlers/AbstractHandler.php
View file @
1b82381e
...
...
@@ -10,35 +10,10 @@ use OneOfZero\Curly\CurlyOptions;
*
* Defines an abstract handler for cURL callback functions.
*/
abstract
class
AbstractHandler
abstract
class
AbstractHandler
implements
HandlerInterface
{
public
const
ON_HEADER
=
'onHeader'
;
public
const
ON_PROGRESS
=
'onProgress'
;
public
const
ON_READ
=
'onRead'
;
public
const
ON_WRITE
=
'onWrite'
;
protected
const
VALID_EVENTS
=
[
self
::
ON_HEADER
,
self
::
ON_PROGRESS
,
self
::
ON_READ
,
self
::
ON_WRITE
];
/**
* Should return an array with the function names of the events that are implemented. The only supported events are:
* 'onHeader', 'onProgress', 'onRead', and 'onWrite'.
*
* @return string[]
*/
abstract
public
function
getImplemented
():
array
;
/**
* Registers the functions specified by getImplemented() as callback functions in the provided CurlyOptions
* instance.
*
* This method is for internal use only and should never be used.
*
* @param CurlyOptions $options
* {@inheritDoc}
*/
public
function
registerCallbacks
(
CurlyOptions
$options
):
void
{
...
...
@@ -56,19 +31,7 @@ abstract class AbstractHandler
}
/**
* Fired when a header is received from the server.
*
* The provided header data yields a single line of the received header each time that it is called.
*
* The return value must be the size of the header data in bytes. To return this be sure to call the parent, or
* manually return the size (it's advisable to use BinarySafe::strlen).
*
* @see http://curl.haxx.se/libcurl/c/CURLOPT_HEADERFUNCTION.html
*
* @param resource $channel
* @param string $headerData
*
* @return int
* {@inheritDoc}
*/
public
function
onHeader
(
$channel
,
string
$headerData
):
int
{
...
...
@@ -76,20 +39,7 @@ abstract class AbstractHandler
}
/**
* Fired frequently during transfer.
*
* Provides upload and download statistics from the request.
*
* Returning non-zero from this method will abort the transfer.
*
* @see http://curl.haxx.se/libcurl/c/CURLOPT_PROGRESSFUNCTION.html
*
* @param resource $channel
* @param int $downloadBytesTotal
* @param int $downloadedBytes
* @param int $uploadBytesTotal
* @param int $uploadedBytes
* @return int
* {@inheritDoc}
*/
public
function
onProgress
(
$channel
,
...
...
@@ -102,21 +52,7 @@ abstract class AbstractHandler
}
/**
* Fired when the library is ready to transfer data to the server.
*
* Provides the configured stream, and the size of the buffer.
*
* The return value must yield the data to be transferred. Note that the size of the return value may not exceed
* the provided buffer size. Returning 0 will abort the transfer, but note that sending less than the server is
* expecting, may cause the connection to hang.
*
* @see http://curl.haxx.se/libcurl/c/CURLOPT_READFUNCTION.html
*
* @param resource $channel
* @param resource $stream
* @param int $bufferSize
*
* @return string
* {@inheritDoc}
*/
public
function
onRead
(
$channel
,
$stream
,
int
$bufferSize
):
string
{
...
...
@@ -124,18 +60,7 @@ abstract class AbstractHandler
}
/**
* Fired when data is received from the server.
*
* Provides the received data.
*
* The return value must be the size of the received data in bytes. To return this be sure to call the parent, or
* manually return the size (it's advisable to use BinarySafe::strlen)
*
* @see http://curl.haxx.se/libcurl/c/CURLOPT_WRITEFUNCTION.html
*
* @param resource $channel
* @param string $data
* @return int
* {@inheritDoc}
*/
public
function
onWrite
(
$channel
,
string
$data
):
int
{
...
...
src/Handlers/HandlerInterface.php
0 → 100644
View file @
1b82381e
<?php
namespace
OneOfZero\Curly\Handlers
;
use
OneOfZero\Curly\CurlyOptions
;
interface
HandlerInterface
{
public
const
ON_HEADER
=
'onHeader'
;
public
const
ON_PROGRESS
=
'onProgress'
;
public
const
ON_READ
=
'onRead'
;
public
const
ON_WRITE
=
'onWrite'
;
public
const
VALID_EVENTS
=
[
self
::
ON_HEADER
,
self
::
ON_PROGRESS
,
self
::
ON_READ
,
self
::
ON_WRITE
];
/**
* Should return an array with the function names of the events that are implemented. The only supported events are:
* 'onHeader', 'onProgress', 'onRead', and 'onWrite'.
*
* @return string[]
*/
public
function
getImplemented
():
array
;
/**
* Registers the functions specified by getImplemented() as callback functions in the provided CurlyOptions
* instance.
*
* This method is for internal use only and should never be used.
*
* @param CurlyOptions $options
*/
public
function
registerCallbacks
(
CurlyOptions
$options
):
void
;
/**
* Fired when a header is received from the server.
*
* The provided header data yields a single line of the received header each time that it is called.
*
* The return value must be the size of the header data in bytes. To return this be sure to call the parent, or
* manually return the size (it's advisable to use BinarySafe::strlen).
*
* @see http://curl.haxx.se/libcurl/c/CURLOPT_HEADERFUNCTION.html
*
* @param resource $channel
* @param string $headerData
*
* @return int
*/
public
function
onHeader
(
$channel
,
string
$headerData
):
int
;
/**
* Fired frequently during transfer.
*
* Provides upload and download statistics from the request.
*
* Returning non-zero from this method will abort the transfer.
*
* @see http://curl.haxx.se/libcurl/c/CURLOPT_PROGRESSFUNCTION.html
*
* @param resource $channel
* @param int $downloadBytesTotal
* @param int $downloadedBytes
* @param int $uploadBytesTotal
* @param int $uploadedBytes
* @return int
*/
public
function
onProgress
(
$channel
,
int
$downloadBytesTotal
,
int
$downloadedBytes
,
int
$uploadBytesTotal
,
int
$uploadedBytes
):
int
;
/**
* Fired when the library is ready to transfer data to the server.
*
* Provides the configured stream, and the size of the buffer.
*
* The return value must yield the data to be transferred. Note that the size of the return value may not exceed
* the provided buffer size. Returning 0 will abort the transfer, but note that sending less than the server is
* expecting, may cause the connection to hang.
*
* @see http://curl.haxx.se/libcurl/c/CURLOPT_READFUNCTION.html
*
* @param resource $channel
* @param resource $stream
* @param int $bufferSize
*
* @return string
*/
public
function
onRead
(
$channel
,
$stream
,
int
$bufferSize
):
string
;
/**
* Fired when data is received from the server.
*
* Provides the received data.
*
* The return value must be the size of the received data in bytes. To return this be sure to call the parent, or
* manually return the size (it's advisable to use BinarySafe::strlen)
*
* @see http://curl.haxx.se/libcurl/c/CURLOPT_WRITEFUNCTION.html
*
* @param resource $channel
* @param string $data
* @return int
*/
public
function
onWrite
(
$channel
,
string
$data
):
int
;
}
tests/HandlerTest.php
View file @
1b82381e
...
...
@@ -4,6 +4,7 @@ namespace OneOfZero\Curly\Tests;
use
OneOfZero\Curly\Curly
;
use
OneOfZero\Curly\Handlers\AbstractHandler
;
use
OneOfZero\Curly\Handlers\HandlerInterface
;
use
OneOfZero\Curly\SharedStream
;
use
OneOfZero\Curly\Tests\Fixtures\LoggingHandler
;
...
...
@@ -32,12 +33,12 @@ class HandlerTest extends AbstractTestCase
$this
->
assertNotEmpty
(
$log
,
'The handler did not process any data'
);
$events
=
array_map
(
function
(
$entry
)
{
return
$entry
[
'event'
];
},
$log
);
$events
=
array_map
(
static
function
(
$entry
)
{
return
$entry
[
'event'
];
},
$log
);
$this
->
assertContains
(
AbstractHandler
::
ON_PROGRESS
,
$events
,
'The handler did not handle any progress events'
);
$this
->
assertContains
(
AbstractHandler
::
ON_HEADER
,
$events
,
'The handler did not handle any header events'
);
$this
->
assertContains
(
AbstractHandler
::
ON_READ
,
$events
,
'The handler did not handle any read events'
);
$this
->
assertContains
(
AbstractHandler
::
ON_WRITE
,
$events
,
'The handler did not handle any write events'
);
$this
->
assertContains
(
HandlerInterface
::
ON_PROGRESS
,
$events
,
'The handler did not handle any progress events'
);
$this
->
assertContains
(
HandlerInterface
::
ON_HEADER
,
$events
,
'The handler did not handle any header events'
);
$this
->
assertContains
(
HandlerInterface
::
ON_READ
,
$events
,
'The handler did not handle any read events'
);
$this
->
assertContains
(
HandlerInterface
::
ON_WRITE
,
$events
,
'The handler did not handle any write events'
);
$headersCounted
=
0
;
$writesCounted
=
0
;
...
...
@@ -45,7 +46,7 @@ class HandlerTest extends AbstractTestCase
foreach
(
$events
as
$event
)
{
switch
(
$event
)
{
case
AbstractHandler
::
ON_HEADER
:
case
HandlerInterface
::
ON_HEADER
:
$headersCounted
++
;
if
(
$writesCounted
)
{
...
...
@@ -54,11 +55,11 @@ class HandlerTest extends AbstractTestCase
}
break
;
case
AbstractHandler
::
ON_WRITE
:
case
HandlerInterface
::
ON_WRITE
:
$writesCounted
++
;
break
;
case
AbstractHandler
::
ON_READ
:
case
HandlerInterface
::
ON_READ
:
$readsCounted
++
;
if
(
$headersCounted
!==
2
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment