Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F101147142
PhutilHTTPResponseParser.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Thu, Feb 6, 05:08
Size
4 KB
Mime Type
text/x-php
Expires
Sat, Feb 8, 05:08 (1 d, 23 h)
Engine
blob
Format
Raw Data
Handle
24103927
Attached To
rPHU libphutil
PhutilHTTPResponseParser.php
View Options
<?php
final
class
PhutilHTTPResponseParser
extends
Phobject
{
private
$followLocationHeaders
;
private
$responses
=
array
();
private
$response
;
private
$buffer
;
private
$state
=
'headers'
;
public
function
setFollowLocationHeaders
(
$follow_location_headers
)
{
$this
->
followLocationHeaders
=
$follow_location_headers
;
return
$this
;
}
public
function
getFollowLocationHeaders
()
{
return
$this
->
followLocationHeaders
;
}
public
function
readBytes
(
$bytes
)
{
if
(
$this
->
state
==
'discard'
)
{
return
$this
;
}
$this
->
buffer
.=
$bytes
;
while
(
true
)
{
if
(
$this
->
state
==
'headers'
)
{
$matches
=
null
;
$ok
=
preg_match
(
"/(
\r
?
\n\r
?
\n
)/"
,
$this
->
buffer
,
$matches
,
PREG_OFFSET_CAPTURE
);
if
(!
$ok
)
{
break
;
}
$headers_len
=
$matches
[
1
][
1
];
$boundary_len
=
strlen
(
$matches
[
1
][
0
]);
$raw_headers
=
substr
(
$this
->
buffer
,
0
,
$headers_len
);
$this
->
buffer
=
substr
(
$this
->
buffer
,
$headers_len
+
$boundary_len
);
$header_lines
=
phutil_split_lines
(
$raw_headers
);
$first_line
=
array_shift
(
$header_lines
);
$response_valid
=
true
;
$matches
=
null
;
$ok
=
preg_match
(
'(^HTTP/
\S
+
\s
+(
\d
+)(?:
\s
+(.*))?$)i'
,
$first_line
,
$matches
);
if
(
$ok
)
{
$http_code
=
(
int
)
$matches
[
1
];
$http_status
=
phutil_utf8_strtolower
(
$matches
[
2
]);
}
else
{
$response_valid
=
false
;
}
$header_list
=
array
();
$saw_location
=
false
;
foreach
(
$header_lines
as
$header_line
)
{
$pos
=
strpos
(
$header_line
,
':'
);
if
(
$pos
===
false
)
{
$response_valid
=
false
;
break
;
}
$name
=
substr
(
$header_line
,
0
,
$pos
);
$value
=
ltrim
(
substr
(
$header_line
,
$pos
+
1
),
' '
);
if
(
phutil_utf8_strtolower
(
$name
)
==
'location'
)
{
$saw_location
=
true
;
}
$header_list
[]
=
array
(
$name
,
$value
,
);
}
// If the response didn't start with a properly formatted "HTTP/..."
// line, or any of the header lines were not formatted correctly, add
// a malformed response to the response list and discard anything else
// we're given.
if
(!
$response_valid
)
{
$malformed
=
new
HTTPFutureParseResponseStatus
(
HTTPFutureParseResponseStatus
::
ERROR_MALFORMED_RESPONSE
,
$raw_headers
);
$this
->
newHTTPRepsonse
()
->
setStatus
(
$malformed
);
$this
->
buffer
=
''
;
$this
->
state
=
'discard'
;
break
;
}
// Otherwise, we have a valid set of response headers.
$response_status
=
new
HTTPFutureHTTPResponseStatus
(
$http_code
,
null
,
$header_list
);
$this
->
newHTTPResponse
()
->
setStatus
(
$response_status
)
->
setHeaders
(
$header_list
);
$is_https_proxy
=
(
$http_code
===
200
)
&&
(
$http_status
===
'connection established'
);
if
(
$http_code
===
100
)
{
// If this is "HTTP/1.1 100 Continue", this is just the server
// telling us that everything is okay. This response won't have
// a body associated with it.
$more_headers
=
true
;
}
else
if
(
$is_https_proxy
)
{
// If this is "HTTP/1.1 200 Connection Established", this is a
// response to a CONNECT request made automatically by cURL to
// an HTTPS proxy. This response won't have a body associated
// with it, and the real body will follow later.
$more_headers
=
true
;
}
else
if
(
$saw_location
&&
$this
->
followLocationHeaders
)
{
// If we're following location headers and this response had
// a location header, cURL will automatically follow it. This
// response shouldn't have a body.
$more_headers
=
true
;
}
else
{
$more_headers
=
false
;
}
// If we're expecting more headers, we're going to stay in the
// "headers" state and parse another set of headers. Otherwise,
// we transition to the "body" state and look for a body.
if
(!
$more_headers
)
{
$this
->
state
=
'body'
;
}
continue
;
}
if
(
$this
->
state
==
'body'
)
{
if
(
strlen
(
$this
->
buffer
))
{
$this
->
response
->
appendBody
(
$this
->
buffer
);
$this
->
buffer
=
''
;
}
break
;
}
}
return
$this
;
}
public
function
getResponses
()
{
if
(
$this
->
state
!==
'body'
)
{
throw
new
HTTPFutureParseResponseStatus
(
HTTPFutureParseResponseStatus
::
ERROR_MALFORMED_RESPONSE
,
$this
->
buffer
);
}
return
$this
->
responses
;
}
private
function
newHTTPResponse
()
{
$response
=
new
PhutilHTTPResponse
();
$this
->
responses
[]
=
$response
;
$this
->
response
=
$response
;
return
$response
;
}
}
Event Timeline
Log In to Comment