Pāriet uz saturu

Viedais HTTP

Pitmaster sazinās ar git serveriem, izmantojot HTTPS un viedo HTTP protokolu. Tas ir galvenais tīkla transports. Tiek izmantotas PHP iebūvētās plūsmas funkcijas (fopen ar plūsmas kontekstu) HTTP pieprasījumiem, tāpēc jābūt iespējotam allow_url_fopen.

SmartHttpClient

PHP
use Pitmaster\Protocol\SmartHttpClient;

$http = new SmartHttpClient();
// Or with custom timeout:
$http = new SmartHttpClient(timeout: 60);

Noildzes noklusējuma vērtība ir konstante PITMASTER_HTTP_TIMEOUT (vesels skaitlis) vai 30 sekundes, ja tā nav definēta.

Refu atklāšana

PHP
$discovery = $http->discoverRefs('https://github.com/user/repo.git');

foreach ($discovery->refs() as $name => $id) {
    echo "{$id->hex} {$name}\n";
}

// HEAD symref (e.g., 'refs/heads/main')
$defaultBranch = $discovery->headSymref();

// Specific ref
$mainId = $discovery->ref('refs/heads/main');

// Server capabilities (a Capability object, or null)
$caps = $discovery->capabilities();

discoverReceivePackRefs() dara to pašu attiecībā uz git-receive-pack. Refa atklāšanas pieprasījums tiek nosūtīts uz:

Kods
GET <url>/info/refs?service=git-upload-pack

Atbilde ir pkt-line kodēts refu saraksts, kura pirmajā rindā ir iespējas.

Upload pack (izgūšana)

PHP
$response = $http->uploadPack($url, $requestBody);

Nosūta POST pieprasījumu uz <url>/git-upload-pack ar vajadzīgo un esošo objektu saskaņošanas pamatdaļu. Atgriež neapstrādāto atbildes pamatdaļu (pkt-line, NAK un side-band datus). UploadPackClient izveido pieprasījumu un iegūst pack:

PHP
use Pitmaster\Protocol\UploadPackClient;

$client = new UploadPackClient($http);
$packData = $client->fetch($url, $wants, $haves);   // ObjectId[] wants and haves

Receive pack (nosūtīšana)

PHP
$response = $http->receivePack($url, $requestBody);

Nosūta POST pieprasījumu uz <url>/git-receive-pack ar refu atjaunināšanas komandām un pack datiem.

PktLine kodējums

git protokolā visai saziņai izmanto pkt-line ietvaru. Katras rindas sākumā ir tās kopējais garums, ieskaitot 4 baitu garuma prefiksu, kas kodēts kā 4 heksadecimālcipari.

PHP
use Pitmaster\Protocol\PktLine;

// Encode a single line
$encoded = PktLine::encode("want abc123def456\n");
// "0016want abc123def456\n"

// Flush packet (end of section)
$flush = PktLine::flush();
// "0000"

// Delimiter packet (protocol v2)
$delim = PktLine::delimiter();
// "0001"

// Decode a stream
$lines = PktLine::decode($rawData);
// Each element is: string (data), null (flush), or false (delimiter)

Garuma noteikumi

  • Minimālā datu rinda: 0005 (1 baita saturs)
  • Maksimālā datu rinda: fff0 (65516 baitu saturs)
  • Iztukšošanas pakete: 0000
  • Atdalītāja pakete: 0001
  • Atbildes beigu pakete: 0002 (protokolā v2; to apstrādā ProtocolV2::decode(), bet PktLine::decode() to noraida)
PHP
PktLine::MAX_PAYLOAD;  // 65516 (65520 - 4)

Refa atklāšana

Klase RefDiscovery parsē servera refu paziņojumu.

PHP
use Pitmaster\Protocol\RefDiscovery;

$discovery = RefDiscovery::parse($pktLines);

// All refs
$refs = $discovery->refs();
// ['refs/heads/main' => ObjectId, 'refs/tags/v1.0' => ObjectId, ...]

// Single ref
$id = $discovery->ref('refs/heads/main');

// HEAD symbolic ref (from capabilities)
$symref = $discovery->headSymref();
// 'refs/heads/main' or null

// Server capabilities
$caps = $discovery->capabilities();
// Capability object (see below), or null

Refa paziņojuma formāts

Paziņojuma pirmajā rindā ir iekļautas iespējas:

Kods
<hash> HEAD\0<capability list>\n
<hash> refs/heads/main\n
<hash> refs/tags/v1.0\n
0000

Iespējas

Klase Capability parsē un pārvalda protokola iespējas.

PHP
use Pitmaster\Protocol\Capability;

$caps = Capability::parse('thin-pack side-band-64k ofs-delta symref=HEAD:refs/heads/main');

$caps->has('thin-pack');           // true
$caps->get('symref');              // 'HEAD:refs/heads/main'
$caps->all();                      // ['thin-pack' => null, ..., 'symref' => 'HEAD:refs/heads/main']

Biežākās iespējas

Iespēja Nozīme
multi_ack Serveris atbalsta vairāku apstiprinājumu saskaņošanu
thin-pack Serveris nosūta plānus pack failus (bāzes objekti var nebūt iekļauti). Pitmaster to pieprasa, bet pagaidām nevar indeksēt plānus pack failus (#16)
side-band Serveris pack datiem izmanto side-band (ierobežots līdz 1000 baitu)
side-band-64k Serveris pack datiem izmanto 64K side-band
ofs-delta Pack failā var būt OFS_DELTA objekti
shallow Serveris atbalsta seklus klonus
no-done Serverim nav nepieciešama rinda "done"
symref=HEAD:refs/heads/main HEAD simboliskais mērķis
agent=git/2.45.0 Servera git versija

Side-band kanālu atdalīšana

Kad serveris izmanto side-band, pack dati tiek multipleksēti ar progresa un kļūdu ziņojumiem. Katras pkt-line lietderīgās slodzes pirmais baits norāda kanālu:

Kanāls Nozīme
1 Pack dati
2 Progresa ziņojumi (stderr)
3 Kritiski kļūdu ziņojumi

Pitmaster UploadPackClient noņem kanālu baitus un atkal apvieno pack datus.

Protokola versijas

v1 (noklusējuma)

Tradicionālais protokols. Refa atklāšanā visi refi tiek nosūtīti uzreiz. Pitmaster veic saskaņošanu vienā kārtā: nosūta nepieciešamos refus, katra lokālā refa galapunkta komitu kā have, kā arī done.

v2

Vienkāršāks protokols ar labāku veiktspēju.

Galvenās atšķirības no v1:

  • Refa atklāšana ir atsevišķa ls-refs komanda (var filtrēt refus)
  • Izgūšanai izmanto vienu fetch komandu ar strukturētiem parametriem
  • Sadaļu atdalīšanai izmanto atdalītāja paketes (0001)

clone() un fetch() vienmēr izmanto v1. v2 ir pieejams, ja to izsaucat tieši:

PHP
$discovery = $http->discoverRefsV2($url);       // ls-refs
$packData = (new UploadPackClient($http))->fetchV2($url, $wants, $haves);

HTTP pieprasījuma darbplūsma

Klonēšana/Iegūšana

Kods
1. GET  /info/refs?service=git-upload-pack
   Response: pkt-line encoded ref list

2. POST /git-upload-pack
   Request:  want <hash>\n ... have <hash>\n ... done\n
   Response: NAK\n + pack data (possibly side-band wrapped)

Nosūtīšana

Kods
1. GET  /info/refs?service=git-receive-pack
   Response: pkt-line encoded ref list

2. POST /git-receive-pack
   Request:  <old-hash> <new-hash> refs/heads/main\0<capabilities>\n
             0000
             PACK<pack data>
   Response: unpack ok\n + ref status lines

Kļūdu apstrāde

Tīkla kļūdas izmet ProtocolException. Ja viedā HTTP apmaiņa ar clone() vai fetch() neizdodas, Pitmaster atkārto mēģinājumu, izmantojot vienkāršo HTTP, un, ja arī tas neizdodas, izmet sākotnējo kļūdu. Citas kļūmes (nezināms attālais repozitorijs, rokturis bez procesa, indeksēt neiespējama pakotne) izmet cita veida izņēmumus:

PHP
use Pitmaster\Exceptions\ProtocolException;

try {
    $repo->fetch();
} catch (ProtocolException $e) {
    echo "Network error: {$e->getMessage()}\n";
}

Biežākās kļūdas:

  • Serveris nav sasniedzams (iestājies taimauts)
  • Nepieciešama autentifikācija vai repozitorijs nav atrasts (ziņots kā Unexpected HTTP status 401, 403 vai 404)
  • Negaidīts Content-Type atbildē
  • Nederīgi pkt-line dati
  • Sānu joslas kļūdu kanāla ziņojums