Skip to content

Commit

Permalink
Expose connection info in responses (addresses and TLS)
Browse files Browse the repository at this point in the history
  • Loading branch information
kelunik committed Jun 24, 2017
1 parent 130e7ee commit a11c002
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 4 deletions.
14 changes: 11 additions & 3 deletions lib/BasicClient.php
Expand Up @@ -202,14 +202,21 @@ private function doRead(Request $request, Uri $uri, ClientSocket $socket, array
Parser::OP_MAX_BODY_BYTES => $options[self::OP_MAX_BODY_BYTES],
]);

$crypto = \stream_get_meta_data($socket->getResource())["crypto"] ?? null;
$connectionInfo = new ConnectionInfo(
$socket->getLocalAddress(),
$socket->getRemoteAddress(),
$crypto ? TlsInfo::fromMetaData($crypto) : null
);

while (($chunk = yield $socket->read()) !== null) {
try {
$parseResult = $parser->parse($chunk);

if ($parseResult) {
$parseResult["headers"] = \array_change_key_case($parseResult["headers"], \CASE_LOWER);

$response = $this->finalizeResponse($request, $parseResult, new IteratorStream($bodyEmitter->iterate()), $previousResponse);
$response = $this->finalizeResponse($request, $parseResult, new IteratorStream($bodyEmitter->iterate()), $previousResponse, $connectionInfo);

if ($deferred) {
$deferred->resolve($response);
Expand Down Expand Up @@ -491,7 +498,7 @@ private function generateAuthorityFromUri(Uri $uri): string {
return "{$host}:{$port}";
}

private function finalizeResponse(Request $request, array $parserResult, InputStream $body, Response $previousResponse = null) {
private function finalizeResponse(Request $request, array $parserResult, InputStream $body, Response $previousResponse = null, ConnectionInfo $connectionInfo) {
if ($encoding = $this->determineCompressionEncoding($parserResult["headers"])) {
$body = new ZlibInputStream($body, $encoding);
}
Expand All @@ -503,7 +510,8 @@ private function finalizeResponse(Request $request, array $parserResult, InputSt
$parserResult["headers"],
$body,
$request,
$previousResponse
$previousResponse,
$connectionInfo
);

if ($response->hasHeader('Set-Cookie')) {
Expand Down
36 changes: 36 additions & 0 deletions lib/ConnectionInfo.php
@@ -0,0 +1,36 @@
<?php

namespace Amp\Artax;

final class ConnectionInfo {
private $localAddress;
private $remoteAddress;
private $tlsInfo;

public function __construct(string $localAddress, string $remoteAddress, TlsInfo $tlsInfo = null) {
$this->localAddress = $localAddress;
$this->remoteAddress = $remoteAddress;
$this->tlsInfo = $tlsInfo;
}

/**
* @return string
*/
public function getLocalAddress(): string {
return $this->localAddress;
}

/**
* @return string
*/
public function getRemoteAddress(): string {
return $this->remoteAddress;
}

/**
* @return TlsInfo|null
*/
public function getTlsInfo() {
return $this->tlsInfo;
}
}
14 changes: 13 additions & 1 deletion lib/Response.php
Expand Up @@ -30,14 +30,18 @@ final class Response {
/** @var Message */
private $body;

/** @var ConnectionInfo */
private $connectionInfo;

public function __construct(
string $protocolVersion,
int $status,
string $reason,
array $headers,
InputStream $body,
Request $request,
Response $previousResponse = null
Response $previousResponse = null,
ConnectionInfo $connectionInfo
) {
$this->protocolVersion = $protocolVersion;
$this->status = $status;
Expand All @@ -46,6 +50,7 @@ public function __construct(
$this->body = new Message($body);
$this->request = $request;
$this->previousResponse = $previousResponse;
$this->connectionInfo = $connectionInfo;
}

/**
Expand Down Expand Up @@ -168,4 +173,11 @@ public function getAllHeaders(): array {
public function getBody(): Message {
return $this->body;
}

/**
* @return ConnectionInfo
*/
public function getConnectionInfo(): ConnectionInfo {
return $this->connectionInfo;
}
}
37 changes: 37 additions & 0 deletions lib/TlsInfo.php
@@ -0,0 +1,37 @@
<?php

namespace Amp\Artax;

final class TlsInfo {
private $protocol;
private $cipherName;
private $cipherBits;
private $cipherVersion;

private function __construct(string $protocol, string $cipherName, int $cipherBits, string $cipherVersion) {
$this->protocol = $protocol;
$this->cipherName = $cipherName;
$this->cipherBits = $cipherBits;
$this->cipherVersion = $cipherVersion;
}

public static function fromMetaData(array $crypto): TlsInfo {
return new self($crypto["protocol"], $crypto["cipher_name"], $crypto["cipher_bits"], $crypto["cipher_version"]);
}

public function getProtocol(): string {
return $this->protocol;
}

public function getCipherName(): string {
return $this->cipherName;
}

public function getCipherBits(): int {
return $this->cipherBits;
}

public function getCipherVersion(): string {
return $this->cipherVersion;
}
}
9 changes: 9 additions & 0 deletions test/ClientHttpBinIntegrationTest.php
Expand Up @@ -235,4 +235,13 @@ public function testInfiniteRedirect() {

wait((new BasicClient)->request("http://httpbin.org/redirect/11"));
}

public function testConnectionInfo() {
/** @var Response $response */
$response = wait((new BasicClient)->request("https://httpbin.org/get"));
$this->assertContains(":", $response->getConnectionInfo()->getLocalAddress());
$this->assertContains(":", $response->getConnectionInfo()->getRemoteAddress());
$this->assertNotNull($response->getConnectionInfo()->getTlsInfo());
$this->assertSame("TLSv1.2", $response->getConnectionInfo()->getTlsInfo()->getProtocol());
}
}

0 comments on commit a11c002

Please sign in to comment.