Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F5952590
Message.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
Message.php
View Options
<?php
declare
(
strict_types
=
1
);
namespace
GuzzleHttp\Psr7
;
use
Psr\Http\Message\MessageInterface
;
use
Psr\Http\Message\RequestInterface
;
use
Psr\Http\Message\ResponseInterface
;
final
class
Message
{
/**
* Returns the string representation of an HTTP message.
*
* @param MessageInterface $message Message to convert to a string.
*/
public
static
function
toString
(
MessageInterface
$message
):
string
{
if
(
$message
instanceof
RequestInterface
)
{
$msg
=
trim
(
$message
->
getMethod
().
' '
.
$message
->
getRequestTarget
())
.
' HTTP/'
.
$message
->
getProtocolVersion
();
if
(!
$message
->
hasHeader
(
'host'
))
{
$msg
.=
"
\r\n
Host: "
.
$message
->
getUri
()->
getHost
();
}
}
elseif
(
$message
instanceof
ResponseInterface
)
{
$msg
=
'HTTP/'
.
$message
->
getProtocolVersion
().
' '
.
$message
->
getStatusCode
().
' '
.
$message
->
getReasonPhrase
();
}
else
{
throw
new
\InvalidArgumentException
(
'Unknown message type'
);
}
foreach
(
$message
->
getHeaders
()
as
$name
=>
$values
)
{
if
(
is_string
(
$name
)
&&
strtolower
(
$name
)
===
'set-cookie'
)
{
foreach
(
$values
as
$value
)
{
$msg
.=
"
\r\n
{$name}: "
.
$value
;
}
}
else
{
$msg
.=
"
\r\n
{$name}: "
.
implode
(
', '
,
$values
);
}
}
return
"{$msg}
\r\n\r\n
"
.
$message
->
getBody
();
}
/**
* Get a short summary of the message body.
*
* Will return `null` if the response is not printable.
*
* @param MessageInterface $message The message to get the body summary
* @param int $truncateAt The maximum allowed size of the summary
*/
public
static
function
bodySummary
(
MessageInterface
$message
,
int
$truncateAt
=
120
):
?
string
{
$body
=
$message
->
getBody
();
if
(!
$body
->
isSeekable
()
||
!
$body
->
isReadable
())
{
return
null
;
}
$size
=
$body
->
getSize
();
if
(
$size
===
0
)
{
return
null
;
}
$body
->
rewind
();
$summary
=
$body
->
read
(
$truncateAt
);
$body
->
rewind
();
if
(
$size
>
$truncateAt
)
{
$summary
.=
' (truncated...)'
;
}
// Matches any printable character, including unicode characters:
// letters, marks, numbers, punctuation, spacing, and separators.
if
(
preg_match
(
'/[^
\p
L
\p
M
\p
N
\p
P
\p
S
\p
Z
\n\r\t
]/u'
,
$summary
)
!==
0
)
{
return
null
;
}
return
$summary
;
}
/**
* Attempts to rewind a message body and throws an exception on failure.
*
* The body of the message will only be rewound if a call to `tell()`
* returns a value other than `0`.
*
* @param MessageInterface $message Message to rewind
*
* @throws \RuntimeException
*/
public
static
function
rewindBody
(
MessageInterface
$message
):
void
{
$body
=
$message
->
getBody
();
if
(
$body
->
tell
())
{
$body
->
rewind
();
}
}
/**
* Parses an HTTP message into an associative array.
*
* The array contains the "start-line" key containing the start line of
* the message, "headers" key containing an associative array of header
* array values, and a "body" key containing the body of the message.
*
* @param string $message HTTP request or response to parse.
*/
public
static
function
parseMessage
(
string
$message
):
array
{
if
(!
$message
)
{
throw
new
\InvalidArgumentException
(
'Invalid message'
);
}
$message
=
ltrim
(
$message
,
"
\r\n
"
);
$messageParts
=
preg_split
(
"/
\r
?
\n\r
?
\n
/"
,
$message
,
2
);
if
(
$messageParts
===
false
||
count
(
$messageParts
)
!==
2
)
{
throw
new
\InvalidArgumentException
(
'Invalid message: Missing header delimiter'
);
}
[
$rawHeaders
,
$body
]
=
$messageParts
;
$rawHeaders
.=
"
\r\n
"
;
// Put back the delimiter we split previously
$headerParts
=
preg_split
(
"/
\r
?
\n
/"
,
$rawHeaders
,
2
);
if
(
$headerParts
===
false
||
count
(
$headerParts
)
!==
2
)
{
throw
new
\InvalidArgumentException
(
'Invalid message: Missing status line'
);
}
[
$startLine
,
$rawHeaders
]
=
$headerParts
;
if
(
preg_match
(
"/(?:^HTTP
\/
|^[A-Z]+
\S
+ HTTP
\/
)(
\d
+(?:
\.\d
+)?)/i"
,
$startLine
,
$matches
)
&&
$matches
[
1
]
===
'1.0'
)
{
// Header folding is deprecated for HTTP/1.1, but allowed in HTTP/1.0
$rawHeaders
=
preg_replace
(
Rfc7230
::
HEADER_FOLD_REGEX
,
' '
,
$rawHeaders
);
}
/** @var array[] $headerLines */
$count
=
preg_match_all
(
Rfc7230
::
HEADER_REGEX
,
$rawHeaders
,
$headerLines
,
PREG_SET_ORDER
);
// If these aren't the same, then one line didn't match and there's an invalid header.
if
(
$count
!==
substr_count
(
$rawHeaders
,
"
\n
"
))
{
// Folding is deprecated, see https://datatracker.ietf.org/doc/html/rfc7230#section-3.2.4
if
(
preg_match
(
Rfc7230
::
HEADER_FOLD_REGEX
,
$rawHeaders
))
{
throw
new
\InvalidArgumentException
(
'Invalid header syntax: Obsolete line folding'
);
}
throw
new
\InvalidArgumentException
(
'Invalid header syntax'
);
}
$headers
=
[];
foreach
(
$headerLines
as
$headerLine
)
{
$headers
[
$headerLine
[
1
]][]
=
$headerLine
[
2
];
}
return
[
'start-line'
=>
$startLine
,
'headers'
=>
$headers
,
'body'
=>
$body
,
];
}
/**
* Constructs a URI for an HTTP request message.
*
* @param string $path Path from the start-line
* @param array $headers Array of headers (each value an array).
*/
public
static
function
parseRequestUri
(
string
$path
,
array
$headers
):
string
{
$hostKey
=
array_filter
(
array_keys
(
$headers
),
function
(
$k
)
{
// Numeric array keys are converted to int by PHP.
$k
=
(
string
)
$k
;
return
strtolower
(
$k
)
===
'host'
;
});
// If no host is found, then a full URI cannot be constructed.
if
(!
$hostKey
)
{
return
$path
;
}
$host
=
$headers
[
reset
(
$hostKey
)][
0
];
$scheme
=
substr
(
$host
,
-
4
)
===
':443'
?
'https'
:
'http'
;
return
$scheme
.
'://'
.
$host
.
'/'
.
ltrim
(
$path
,
'/'
);
}
/**
* Parses a request message string into a request object.
*
* @param string $message Request message string.
*/
public
static
function
parseRequest
(
string
$message
):
RequestInterface
{
$data
=
self
::
parseMessage
(
$message
);
$matches
=
[];
if
(!
preg_match
(
'/^[
\S
]+
\s
+([a-zA-Z]+:
\/\/
|
\/
).*/'
,
$data
[
'start-line'
],
$matches
))
{
throw
new
\InvalidArgumentException
(
'Invalid request string'
);
}
$parts
=
explode
(
' '
,
$data
[
'start-line'
],
3
);
$version
=
isset
(
$parts
[
2
])
?
explode
(
'/'
,
$parts
[
2
])[
1
]
:
'1.1'
;
$request
=
new
Request
(
$parts
[
0
],
$matches
[
1
]
===
'/'
?
self
::
parseRequestUri
(
$parts
[
1
],
$data
[
'headers'
])
:
$parts
[
1
],
$data
[
'headers'
],
$data
[
'body'
],
$version
);
return
$matches
[
1
]
===
'/'
?
$request
:
$request
->
withRequestTarget
(
$parts
[
1
]);
}
/**
* Parses a response message string into a response object.
*
* @param string $message Response message string.
*/
public
static
function
parseResponse
(
string
$message
):
ResponseInterface
{
$data
=
self
::
parseMessage
(
$message
);
// According to https://datatracker.ietf.org/doc/html/rfc7230#section-3.1.2
// the space between status-code and reason-phrase is required. But
// browsers accept responses without space and reason as well.
if
(!
preg_match
(
'/^HTTP
\/
.* [0-9]{3}( .*|$)/'
,
$data
[
'start-line'
]))
{
throw
new
\InvalidArgumentException
(
'Invalid response string: '
.
$data
[
'start-line'
]);
}
$parts
=
explode
(
' '
,
$data
[
'start-line'
],
3
);
return
new
Response
(
(
int
)
$parts
[
1
],
$data
[
'headers'
],
$data
[
'body'
],
explode
(
'/'
,
$parts
[
0
])[
1
],
$parts
[
2
]
??
null
);
}
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Oct 3 2026, 01:35 (4 w, 4 d ago)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
ea/74/c47d53f54c2b31945cce173d6e5e
Default Alt Text
Message.php (8 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment