From: Shawn O. Pearce <hidden> Date: 2016-06-15 22:45:13
I spent some time on Friday kicking around how the fetch part of
an HTTP protocol could be implemented. What I seem to have settled
on at this point in time is a more condensed version of the native
git protocol, batched into 256 commit blocks.
--8<--
Smart HTTP transfer protocols
=============================
Git supports two HTTP based transfer protocols. A "dumb" protocol
which requires only a standard HTTP server on the server end of the
connection, and a "smart" protocol which requires a Git aware CGI
(or server module). This document describes the "smart" protocol.
As a design feature smart clients can automatically translate and
upgrade "dumb" protocol URLs. This permits all users to have the
same published URL, with the peers automatically choosing to use
the most efficient transport available to them.
Authentication
--------------
Standard HTTP authentication is used if authentication is required
to access a repository, and must be configured and enforced by the
HTTP server software itself.
Stateless
---------
The protocol, much like its underlying HTTP, is stateless, from the
perspective of the HTTP server side. All state must be retained and
managed by the client. This permits round-robin load-balancing on
the server side, among many other implementation details.
HTTP/1.1 Preference
-------------------
For performance reasons the HTTP/1.1 chunked transfer encoding
is used whenever possible to transfer variable length objects.
This avoids needing to produce large results in memory to compute
the proper content-length.
Detecting Smart Servers
-----------------------
HTTP clients can detect a smart Git-aware server by HEADing
$repo/backend.git-http and looking for a 302 redirect to the
repository's smart service URL:
C: HEAD /path/to/repository.git/backend.git-http HTTP/1.1
S: HTTP/1.1 302 Found
S: Location: /git/path/to/repository.git
A dumb server would respond with a 304 Not Found (or 200 OK).
Smart servers may send a redirect to any URL that does not
contain query args (e.g. "foo?repo=path.git" is invalid).
The URL must be sufficient to provide the location of the
repository to the smart service code.
A valid redirect can be to yourself, for example:
C: HEAD /path/to/repository.git/backend.git-http HTTP/1.1
S: HTTP/1.1 302 Found
S: Location: /path/to/repository.git/backend.git-http/.
All subsequent communcation for this transaction is done through
the smart service URL ($ssurl), not the original URL.
GET $ssurl/refs
---------------
Obtains the available refs from the remote repository. The response
is a sequence of refs, one per Git packet line. The final packet
line has a length of 0 to indicate the end. This is basically
the same protocol that is used by the git-upload-pack service to
advertise the available refs.
C: GET $ssurl/refs HTTP/1.1
S: HTTP/1.1 200 OK
S: Content-Type: application/x-git-refs
S:
S: 003295dcfa3633004da0049d3d0fa03f80589cbcaf31 HEAD
S: 003e95dcfa3633004da0049d3d0fa03f80589cbcaf31 refs/heads/maint
S: 003fd049f6c27a2244e12041955e262a404c7faba355 refs/heads/master
S: 003b2cb58b79488a98d2721cea644875a8dd0026b115 refs/heads/pu
S: 0000
POST $ssurl/upload-pack
-----------------------
Prepares an estimated minimal pack to transfer new objects to the
client.
The computation to select the minimal pack proceeds as follows
(c = client, s = server):
init step:
(c) Use /refs to obtain the advertised refs.
(c) Place any object seen in /refs into set ADVERTISED.
(c) Build a set, WANT, of the objects from ADVERTISED the client
wants to fetch, based on what it saw from /refs.
(c) Start a queue, C_PENDING, ordered by commit time (popping newest
first). Add all client refs. When a commit is popped from the
queue its parents should be automatically inserted back. Commits
should only enter the queue once.
one compute step:
(c) Send a /upload-pack request:
C: POST $ssurl/upload-pack HTTP/1.1
C: Content-Type: application/x-git-uploadpack
C: Content-Length: ...
C:
C: 0009want
C: 0xxx<WANT list>
C: 000bcommon
C: 0xxx<COMMON list>
C: 0009have
C: 0xxx<HAVE list>
C: 0000
The stream is organized into "sections", where each section is
composed of two git pkt-lines. The first pkt-line provides the
name of the section ("want", "have", "common"). The second
pkt-line has the binary SHA-1 ids which compose that section.
The "want" section is required. The other sections ("have",
"common") are optional. A missing "want" section should be
answered with a "400 Bad Request".
Sections must appear in the following order, if they appear
at all in the request stream:
* want
* common
* have
Each section may appear multiple times. Client implementions
are encouraged to use as few sections as possible, however the
limit of 64k per pkt-line limits the number of ids to 3,276 per
section entry.
The stream is terminated by a pkt-line flush ("0000").
The HAVE list is created by popping the first 256 commits
from C_PENDING. Less can be supplied if C_PENDING empties.
(s) Parse the /upload-pack request.
Verify all objects in WANT are reachable from refs. As
this may require walking backwards through history to
the very beginning on invalid requests the server may
use a reasonable limit of commits (e.g. 1000) walked
beyond any ref tip before giving up.
If any WANT object is not reachable, send a 409 error:
S: HTTP/1.1 409 Conflict
S: Content-Type: application/x-git-error
S:
S: %s not reachable
Create an empty list, S_COMMON.
If 'common' was sent:
Load all objects into S_COMMON.
If 'have' was sent:
Loop through the objects in the order supplied by the client.
For each object, if the server has the object reachable from
a ref, add it to S_COMMON. If a commit is added to S_COMMON,
do not add any ancestors, even if they also appear in HAVE.
(s) Send the /upload-pack response:
S: HTTP/1.1 200 OK
S: Content-Type: application/x-git-uploadpack
S: 000bcommon
S: 0xxx<S_COMMON list>
S: 0000
The stream formatting rules are the same as the request.
The section "common" details the contents of S_COMMON,
that is all objects from HAVE that the server also has.
If the server has found a closed set of objects to pack,
it replies with the pack and not x-git-uploadpack response.
S: HTTP/1.1 200 OK
S: Content-Type: application/x-git-pack
S: 000c.PACK...
The returned stream is the side-band-64k protocol supported
by the git-upload-pack service, and the pack is embedded into
stream 1. Progress messages from the server side may appear
in stream 2.
(c) Parse the /upload-pack response:
If the Content-Type is application/x-git-uploadpack:
Reset COMMON to the items in S_COMMON. The new S_COMMON
should be a superset of the existing COMMON set.
Remove all items in S_COMMON, and all of their ancestors,
from PENDING.
Do another /compute-common step.
If the Content-Type is application/x-git-pack:
Process the pack stream and update the local refs.
POST $ssurl/receive-pack
------------------------
TBD: Still a work in progress.
Uploads a pack and updates refs. The start of the stream is the
commands to update the refs and the remainder of the stream is the
pack file itself. See git-receive-pack and its network protocol
in pack-protocol.txt, as this is essentially the same.
C: POST /path/to/repository.git/receive-pack HTTP/1.0
C: Content-Type: application/x-git-receivepack
C: Transfer-Encoding: chunked
C:
C: 103
C: 006395dcfa3633004da0049d3d0fa03f80589cbcaf31 d049f6c27a2244e12041955e262a404c7faba355 refs/heads/maint
C: 4
C: 0000
C: 12
C: PACK
...
C: 0
S: HTTP/1.0 200 OK
S: Content-type: application/x-git-receive-pack-status
S: Transfer-Encoding: chunked
S:
S: ...<output of receive-pack>...
--
Shawn.
From: "H. Peter Anvin" <hpa@zytor.com> Date: 2016-06-15 22:45:13
This is a bit more detailed review than I have done in the past (I'm actually in town...) so please pardon me for commenting on things that has been dealt with in the past.
Overall, I really keeping in mind that you're doing a layer on top of HTTP, and resist the temptation to delve into details how things are to be implemented at the HTTP level.
The HTTP layer, furthermore, has a couple of important properties:
- GET requests may be cached, even if you tell it not to.
(Some proxies, transparent or not, ignore caching directives.)
- POST requests generally will not.
So don't implement things as GET requests unless you genuinely can deal with the request being cached. Using POST requests throughout seems like a safer bet to me; on the other hand, since the only use of GET is obtaining a list of refs the worst thing that can happen, I presume, is additional latency for the user behind the proxy.
Again, please don't take this as anything other than technical review type criticism. I'm obviously really happy about the project and want to see it happen.
I do have one, very specific question: would the load on the server be lower if it was using a stateful protocol (like the standard git protocol)? If there is value in the server maintaining state, then I would like to suggest a slightly different protocol.
-hpa
Shawn O. Pearce wrote:
HTTP/1.1 Preference
-------------------
For performance reasons the HTTP/1.1 chunked transfer encoding
is used whenever possible to transfer variable length objects.
This avoids needing to produce large results in memory to compute
the proper content-length.
This piece is unnecessary; it's a detail of the underlying HTTP layer.
Detecting Smart Servers
-----------------------
HTTP clients can detect a smart Git-aware server by HEADing
$repo/backend.git-http and looking for a 302 redirect to the
repository's smart service URL:
C: HEAD /path/to/repository.git/backend.git-http HTTP/1.1
S: HTTP/1.1 302 Found
S: Location: /git/path/to/repository.git
A dumb server would respond with a 304 Not Found (or 200 OK).
Smart servers may send a redirect to any URL that does not
contain query args (e.g. "foo?repo=path.git" is invalid).
The URL must be sufficient to provide the location of the
repository to the smart service code.
A valid redirect can be to yourself, for example:
C: HEAD /path/to/repository.git/backend.git-http HTTP/1.1
S: HTTP/1.1 302 Found
S: Location: /path/to/repository.git/backend.git-http/.
All subsequent communcation for this transaction is done through
the smart service URL ($ssurl), not the original URL.
I actually suggest embedding the forwarding URL into an ordinary payload. Instead of a HEAD request here, then do a GET (or, even better, POST) and get the redirected URL in return.
Why? Because it's common enough to redirect entire trees, and use of HTTP-layer redirections here is an unnecessary layering violation.
If you insist on using a HTTP status code, I would claim that 303 is a better status code.
GET $ssurl/refs
---------------
Obtains the available refs from the remote repository. The response
is a sequence of refs, one per Git packet line. The final packet
line has a length of 0 to indicate the end. This is basically
the same protocol that is used by the git-upload-pack service to
advertise the available refs.
C: GET $ssurl/refs HTTP/1.1
S: HTTP/1.1 200 OK
S: Content-Type: application/x-git-refs
S:
S: 003295dcfa3633004da0049d3d0fa03f80589cbcaf31 HEAD
S: 003e95dcfa3633004da0049d3d0fa03f80589cbcaf31 refs/heads/maint
S: 003fd049f6c27a2244e12041955e262a404c7faba355 refs/heads/master
S: 003b2cb58b79488a98d2721cea644875a8dd0026b115 refs/heads/pu
S: 0000
POST $ssurl/upload-pack
-----------------------
Prepares an estimated minimal pack to transfer new objects to the
client.
The computation to select the minimal pack proceeds as follows
(c = client, s = server):
init step:
(c) Use /refs to obtain the advertised refs.
(c) Place any object seen in /refs into set ADVERTISED.
(c) Build a set, WANT, of the objects from ADVERTISED the client
wants to fetch, based on what it saw from /refs.
(c) Start a queue, C_PENDING, ordered by commit time (popping newest
first). Add all client refs. When a commit is popped from the
queue its parents should be automatically inserted back. Commits
should only enter the queue once.
one compute step:
(c) Send a /upload-pack request:
C: POST $ssurl/upload-pack HTTP/1.1
C: Content-Type: application/x-git-uploadpack
Instead of "application/x-git-blah" I would suggest using "application/x-git; action=blah"; that way we can probably even register application/git with IANA.
C: Content-Length: ...
C:
C: 0009want
C: 0xxx<WANT list>
C: 000bcommon
C: 0xxx<COMMON list>
C: 0009have
C: 0xxx<HAVE list>
C: 0000
The stream is organized into "sections", where each section is
composed of two git pkt-lines. The first pkt-line provides the
name of the section ("want", "have", "common"). The second
pkt-line has the binary SHA-1 ids which compose that section.
The "want" section is required. The other sections ("have",
"common") are optional. A missing "want" section should be
answered with a "400 Bad Request".
Sections must appear in the following order, if they appear
at all in the request stream:
* want
* common
* have
Each section may appear multiple times. Client implementions
are encouraged to use as few sections as possible, however the
limit of 64k per pkt-line limits the number of ids to 3,276 per
section entry.
The stream is terminated by a pkt-line flush ("0000").
The HAVE list is created by popping the first 256 commits
from C_PENDING. Less can be supplied if C_PENDING empties.
(s) Parse the /upload-pack request.
Verify all objects in WANT are reachable from refs. As
this may require walking backwards through history to
the very beginning on invalid requests the server may
use a reasonable limit of commits (e.g. 1000) walked
beyond any ref tip before giving up.
If any WANT object is not reachable, send a 409 error:
Again, I think the 409 error code here is an unnecessary layering violation. It's simply Yet Another Thing that an HTTP proxy can screw up. Having the HTTP server return a normal 200 reply (meaning that the *transport* succeeded) and have the error embedded in a lower layer should avoid that class of problems.
S: HTTP/1.1 409 Conflict
S: Content-Type: application/x-git-error
S:
S: %s not reachable
Create an empty list, S_COMMON.
If 'common' was sent:
Load all objects into S_COMMON.
If 'have' was sent:
Loop through the objects in the order supplied by the client.
For each object, if the server has the object reachable from
a ref, add it to S_COMMON. If a commit is added to S_COMMON,
do not add any ancestors, even if they also appear in HAVE.
(s) Send the /upload-pack response:
S: HTTP/1.1 200 OK
S: Content-Type: application/x-git-uploadpack
S: 000bcommon
S: 0xxx<S_COMMON list>
S: 0000
The stream formatting rules are the same as the request.
The section "common" details the contents of S_COMMON,
that is all objects from HAVE that the server also has.
If the server has found a closed set of objects to pack,
it replies with the pack and not x-git-uploadpack response.
S: HTTP/1.1 200 OK
S: Content-Type: application/x-git-pack
S: 000c.PACK...
The returned stream is the side-band-64k protocol supported
by the git-upload-pack service, and the pack is embedded into
stream 1. Progress messages from the server side may appear
in stream 2.
(c) Parse the /upload-pack response:
If the Content-Type is application/x-git-uploadpack:
Reset COMMON to the items in S_COMMON. The new S_COMMON
should be a superset of the existing COMMON set.
Remove all items in S_COMMON, and all of their ancestors,
from PENDING.
Do another /compute-common step.
If the Content-Type is application/x-git-pack:
Process the pack stream and update the local refs.
POST $ssurl/receive-pack
------------------------
TBD: Still a work in progress.
Uploads a pack and updates refs. The start of the stream is the
commands to update the refs and the remainder of the stream is the
pack file itself. See git-receive-pack and its network protocol
in pack-protocol.txt, as this is essentially the same.
C: POST /path/to/repository.git/receive-pack HTTP/1.0
C: Content-Type: application/x-git-receivepack
C: Transfer-Encoding: chunked
C:
C: 103
C: 006395dcfa3633004da0049d3d0fa03f80589cbcaf31 d049f6c27a2244e12041955e262a404c7faba355 refs/heads/maint
C: 4
C: 0000
C: 12
C: PACK
...
C: 0
S: HTTP/1.0 200 OK
S: Content-type: application/x-git-receive-pack-status
S: Transfer-Encoding: chunked
S:
S: ...<output of receive-pack>...
From: Shawn O. Pearce <hidden> Date: 2016-06-15 22:45:13
"H. Peter Anvin" [off-list ref] wrote:
So don't implement things as GET requests unless you genuinely can deal
with the request being cached. Using POST requests throughout seems
like a safer bet to me; on the other hand, since the only use of GET is
obtaining a list of refs the worst thing that can happen, I presume, is
additional latency for the user behind the proxy.
This is a good point. There is probably not any reason to cache the
refs content if we don't also support caching the pack files. So in
this latest draft I have moved the ref listing to also be a POST.
I do have one, very specific question: would the load on the server be
lower if it was using a stateful protocol (like the standard git
protocol)? If there is value in the server maintaining state, then I
would like to suggest a slightly different protocol.
Its possible the load would be lower, but it would complicate the
server implementation considerably. Looking at the algorithm used
to compute upload-pack the server has relatively little to do in
any request.
Validation of WANT should be just matching the requested objects
against the refs; most clients will be asking for the current tips.
A client that started the process just before a fast-forward push
may incur at most a few hundred commit walk during its last couple
of computation round-trips.
Marking commits COMMON is just a matter of looking them up in the
database and setting their flags.
Evaluation of the HAVE list avoids duplicates in a well-behaved
client. So the server sees each candidate commit from a client
only once, even if it spans multiple upload-pack requests.
So I think the cost may actually break even with a stateful protocol
if we imagine that the server is actually a farm of systems and
simple round-robin load-balancing is being done in front of the
Git-aware server.
I'd really like to keep the protocol stateless on the server side, as
this makes it easier to embed into certain commerical server farms.
Shawn O. Pearce wrote:
quoted
HTTP/1.1 Preference
This piece is unnecessary; it's a detail of the underlying HTTP layer.
Gone from the latest draft.
quoted
Detecting Smart Servers
...
I actually suggest embedding the forwarding URL into an ordinary
payload. Instead of a HEAD request here, then do a GET (or, even
better, POST) and get the redirected URL in return.
Why? Because it's common enough to redirect entire trees, and use of
HTTP-layer redirections here is an unnecessary layering violation.
This has been completely rewritten to not use URL redirection at all.
--8<--
Smart HTTP transfer protocols
=============================
Git supports two HTTP based transfer protocols. A "dumb" protocol
which requires only a standard HTTP server on the server end of the
connection, and a "smart" protocol which requires a Git aware CGI
(or server module). This document describes the "smart" protocol.
As a design feature smart clients can automatically translate and
upgrade "dumb" protocol URLs. This permits all users to have the
same published URL, with the peers automatically choosing to use
the most efficient transport available to them.
HTTP Transport
--------------
All requests are encoded as HTTP POST requests to the smart service
URL, "$url/backend.git-http/$service".
All responses are encoded as 200 Ok responses, even if the server
side has "failed" the request. Service specific success/failure
codes are embedded in the content.
Authentication
--------------
Standard HTTP authentication is used if authentication is required
to access a repository, and must be configured and enforced by the
HTTP server software itself.
Stateless
---------
The protocol, much like its underlying HTTP, is stateless, from the
perspective of the HTTP server side. All state must be retained and
managed by the client. This permits round-robin load-balancing on
the server side, among many other implementation details.
Content Type
------------
All requests/responses use "application/x-git" as the content type.
Action specific subtypes are specified by the parameter "service",
e.g. "application/x-git; service=upload-pack".
Detecting Smart Servers
-----------------------
HTTP clients can detect a smart Git-aware server by sending
a request to service "show-ref".
A Git-aware server will respond with a valid response (see below).
A dumb server should respond with an error message.
Service show-ref
----------------
Obtains the available refs from the remote repository.
URL: $url/backend.git-http/show-ref
Content-Type: application/x-git; service=show-ref
The request is an empty body.
The response is a sequence of refs, one per Git packet line.
The final packet line has a length of 0 to indicate the end.
S: 003295dcfa3633004da0049d3d0fa03f80589cbcaf31 HEAD
S: 003e95dcfa3633004da0049d3d0fa03f80589cbcaf31 refs/heads/maint
S: 003fd049f6c27a2244e12041955e262a404c7faba355 refs/heads/master
S: 003b2cb58b79488a98d2721cea644875a8dd0026b115 refs/heads/pu
S: 0000
Service upload-pack
-------------------
Prepares an estimated minimal pack to transfer new objects to the
client.
URL: $url/backend.git-http/upload-pack
Content-Type: application/x-git; service=upload-pack
The computation to select the minimal pack proceeds as follows
(c = client, s = server):
init step:
(c) Use show-ref to obtain the advertised refs.
(c) Place any object seen in show-ref into set ADVERTISED.
(c) Build a set, WANT, of the objects from ADVERTISED the client
wants to fetch, based on what it saw from show-ref.
(c) Start a queue, C_PENDING, ordered by commit time (popping newest
first). Add all client refs. When a commit is popped from the
queue its parents should be automatically inserted back. Commits
should only enter the queue once.
one compute step:
(c) Send an upload-pack request:
C: 0009want
C: 0xxx<WANT list>
C: 000bcommon
C: 0xxx<COMMON list>
C: 0009have
C: 0xxx<HAVE list>
C: 0000
The stream is organized into "sections", where each section is
composed of two git pkt-lines. The first pkt-line provides the
name of the section ("want", "have", "common"). The second
pkt-line has the binary SHA-1 ids which compose that section.
The "want" section is required. The other sections ("have",
"common") are optional. A missing "want" section should be
answered with an error.
Sections must appear in the following order, if they appear
at all in the request stream:
* want
* common
* have
Each section may appear multiple times. Client implementions
are encouraged to use as few sections as possible, however the
limit of 64k per pkt-line limits the number of ids to 3,276 per
section entry.
The stream is terminated by a pkt-line flush ("0000").
The HAVE list is created by popping the first 256 commits
from C_PENDING. Less can be supplied if C_PENDING empties.
(s) Parse the upload-pack request:
Verify all objects in WANT are reachable from refs. As
this may require walking backwards through history to
the very beginning on invalid requests the server may
use a reasonable limit of commits (e.g. 1000) walked
beyond any ref tip before giving up.
If no WANT objects are received, send an error:
S: 0019status error no want
If any WANT object is not reachable, send an error:
S: 001estatus error invalid want
Create an empty list, S_COMMON.
If 'common' was sent:
Load all objects into S_COMMON.
If 'have' was sent:
Loop through the objects in the order supplied by the client.
For each object, if the server has the object reachable from
a ref, add it to S_COMMON. If a commit is added to S_COMMON,
do not add any ancestors, even if they also appear in HAVE.
(s) Send the upload-pack response:
If the server has found a closed set of objects to pack,
it replies with the pack.
S: 0010status pack
S: 000c.PACK...
The returned stream is the side-band-64k protocol supported
by the git-upload-pack service, and the pack is embedded into
stream 1. Progress messages from the server side may appear
in stream 2.
If the server wants more information, it replies with a
status continue response:
S: 0014status continue
S: 000bcommon
S: 0xxx<S_COMMON list>
S: 0000
The stream formatting rules are the same as the request.
The section "common" details the contents of S_COMMON,
that is all objects from HAVE that the server also has.
(c) Parse the upload-pack response:
If the status pkt-line is "status pack:"
Process the pack stream and update the local refs.
If the status pkt-line is "status continue":
Reset COMMON to the items in S_COMMON. The new S_COMMON
should be a superset of the existing COMMON set.
Remove all items in S_COMMON, and all of their ancestors,
from PENDING.
Do another compute step.
Service receive-pack
--------------------
Uploads a pack and updates refs.
URL: $url/backend.git-http/receive-pack
Content-Type: application/x-git; service=receive-pack
The start of the stream is the commands to update the refs and
the remainder of the stream is the pack file itself. See
git-receive-pack and its network protocol in pack-protocol.txt,
as this is essentially the same.
C: 006395dcfa3633004da0049d3d0fa03f80589cbcaf31 d049f6c27a2244e12041955e262a404c7faba355 refs/heads/maint
C: 0000
C: PACK...
S: ...<output of receive-pack>...
--
Shawn.
So don't implement things as GET requests unless you genuinely can deal
with the request being cached. Using POST requests throughout seems
like a safer bet to me; on the other hand, since the only use of GET is
obtaining a list of refs the worst thing that can happen, I presume, is
additional latency for the user behind the proxy.
This is a good point. There is probably not any reason to cache the
refs content if we don't also support caching the pack files. So in
this latest draft I have moved the ref listing to also be a POST.
on the other hand, it would be a good thing if pack files could be cached.
in a peer-peer git environment the cache would not be used very much, but when you have a large number of people tracking a central repository (or even a pseudo-central one like the kernel) you have a lot of people upgrading from one point to the next point.
and for cloneing (and especially thing like linux-next where you essentially re-clone daily) letting the pack get cached is probably a very good thing.
I know it would be another round-trip, but how painful would it be to compute what the contents of a pack would be (what objects would be in it, not calculating the deltas nessasary for a full pack file), and return that to the client so that the client could do a GET for the pack itself.
if that exact pack happens to be in the cache, great, if not the server takes the data from the client and creates a pack file with those objects in it.
David Lang
From: "H. Peter Anvin" <hpa@zytor.com> Date: 2016-06-15 22:45:13
Shawn O. Pearce wrote:
So I think the cost may actually break even with a stateful protocol
if we imagine that the server is actually a farm of systems and
simple round-robin load-balancing is being done in front of the
Git-aware server.
I'd really like to keep the protocol stateless on the server side, as
this makes it easier to embed into certain commerical server farms.
Indeed. It was a question, not a statement of any sort. I was curious about the answer.
I really like the new draft, with the one consideration below.
HTTP Transport
--------------
All requests are encoded as HTTP POST requests to the smart service
URL, "$url/backend.git-http/$service".
All responses are encoded as 200 Ok responses, even if the server
side has "failed" the request. Service specific success/failure
codes are embedded in the content.
I still would like to have an indirection step at the start, in order to keep a single client on a server in the case of skew. I suggest simply do it as HTTP POST $url/backend.git-http, empty body, and return a URL prefix to use for the remainder of the session. That way a server who wants a stateful setup can return a URL which contains a session cookie; others can return a URL containing a target server, and finally others can simply return the requesting URL.
-hpa
From: "H. Peter Anvin" <hpa@zytor.com> Date: 2016-06-15 22:45:13
david@lang.hm wrote:
on the other hand, it would be a good thing if pack files could be cached.
in a peer-peer git environment the cache would not be used very much, but when you have a large number of people tracking a central repository (or even a pseudo-central one like the kernel) you have a lot of people upgrading from one point to the next point.
Worth noting that this also applies to the raw git protocol.
-hpa
on the other hand, it would be a good thing if pack files could be cached.
in a peer-peer git environment the cache would not be used very much, but when you have a large number of people tracking a central repository (or even a pseudo-central one like the kernel) you have a lot of people upgrading from one point to the next point.
Worth noting that this also applies to the raw git protocol.
IIRC the native git server will use existing packs when it can.
it would be interesting to modify git to record what packs it generates and then see how much a big server (like kernel.org) would re-use a pack under different caching strategies.
David Lang
From: "H. Peter Anvin" <hpa@zytor.com> Date: 2016-06-15 22:45:13
david@lang.hm wrote:
On Mon, 25 Aug 2008, H. Peter Anvin wrote:
quoted
david@lang.hm wrote:
quoted
on the other hand, it would be a good thing if pack files could be cached.
in a peer-peer git environment the cache would not be used very much, but when you have a large number of people tracking a central repository (or even a pseudo-central one like the kernel) you have a lot of people upgrading from one point to the next point.
Worth noting that this also applies to the raw git protocol.
IIRC the native git server will use existing packs when it can.
Yes (and the smart http server should, too). However, neither of them can currently generate new packfiles and save them for future use in a separate directory from the repository tree.
-hpa
From: Imran M Yousuf <hidden> Date: 2016-06-15 22:45:13
On Tue, Aug 26, 2008 at 10:25 AM, [off-list ref] wrote:
On Mon, 25 Aug 2008, H. Peter Anvin wrote:
quoted
david@lang.hm wrote:
quoted
on the other hand, it would be a good thing if pack files could be
cached.
in a peer-peer git environment the cache would not be used very much, but
when you have a large number of people tracking a central repository (or
even a pseudo-central one like the kernel) you have a lot of people
upgrading from one point to the next point.
Worth noting that this also applies to the raw git protocol.
IIRC the native git server will use existing packs when it can.
it would be interesting to modify git to record what packs it generates and
then see how much a big server (like kernel.org) would re-use a pack under
different caching strategies.
I fully agree with the caching logic as well. In this regard I was
thinking whether the protocol could be modified a bit to accommodate
it or not. From initial proposal GET was dropped because there will be
caching, which I also agree :), and we need GET in order to achieve
cache - so I would have done something such as - initial request would
be POST and if there is no change and cache can be used I would
redirect it to a equivalen GET URL and if cache is invalid (which the
server can track by pinging the GET URL) serve directly through the
POST method untill either the GET is out of the cache or is updated.
- Imran
David Lang
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
From: Shawn O. Pearce <hidden> Date: 2016-06-15 22:45:13
"H. Peter Anvin" [off-list ref] wrote:
quoted
Detecting Smart Servers
-----------------------
HTTP clients can detect a smart Git-aware server by HEADing
$repo/backend.git-http and looking for a 302 redirect to the
repository's smart service URL:
...
quoted
All subsequent communcation for this transaction is done through
the smart service URL ($ssurl), not the original URL.
I actually suggest embedding the forwarding URL into an ordinary
payload. Instead of a HEAD request here, then do a GET (or, even
better, POST) and get the redirected URL in return.
Why? Because it's common enough to redirect entire trees, and use of
HTTP-layer redirections here is an unnecessary layering violation.
Hmm. I'm actually thinking the exact opposite here. My rationale
for putting the response as a standard HTTP 302/303 style redirect
is to permit hardware load balancers or Apache mod_rewrite rules
to implement simple load balancing with a HTTP redirect.
If we embed the redirect URL into the payload then configuring that
will become a lot more complex. At the minimum you may have to
make up a dummy file for each server (holding the response payload)
then then let mod_rewrite rewrite the request internally to make
Apache serve that file. Ugly.
If you insist on using a HTTP status code, I would claim that 303 is a
better status code.
From: Shawn O. Pearce <hidden> Date: 2016-06-15 22:45:13
"Shawn O. Pearce" [off-list ref] wrote:
"H. Peter Anvin" [off-list ref] wrote:
quoted
I actually suggest embedding the forwarding URL into an ordinary
payload. Instead of a HEAD request here, then do a GET (or, even
better, POST) and get the redirected URL in return.
Hmm. I'm actually thinking the exact opposite here.
Here's the delta from the last draft I emailed. Its basically just
about this redirect stuff.
@@ -43,14 +43,40 @@ All requests/responses use "application/x-git" as the content type. Action specific subtypes are specified by the parameter "service", e.g. "application/x-git; service=upload-pack".+Redirects+---------++If a POST request results in an HTTP 302 or 303 redirect response+clients should retry the request by updating the URL and POSTing+the request to the new location.++If the new request is successful clients should trim off the+trailing "/backend.git/$service" portion of the new loaction+and use the remainder as the base URL for future requests in+the same transaction.++This redirection permits Apache's mod_rewrite (and many other+servers) to implement a form of round-robin load balancing by+redirecting all requests to a generic host to a specific host.+ Detecting Smart Servers ----------------------- HTTP clients can detect a smart Git-aware server by sending a request to service "show-ref".-A Git-aware server will respond with a valid response (see below).-A dumb server should respond with an error message. +A Git-aware server will respond with a valid response. Clients+must check the following properties to prevent being fooled by+misconfigured servers:++ * HTTP status code is 200.+ * Content-Type is "application/x-git; service=show-ref"+ * The body can be parsed without errors. The length of+ each pkt-line must be 4 valid hex digits.++A dumb server will respond with a non-200 HTTP status code.+A misconfigured server may respond with a normal 200 status+code, but an incorrect content type. Service show-ref ----------------
From: "H. Peter Anvin" <hpa@zytor.com> Date: 2016-06-15 22:45:13
Shawn O. Pearce wrote:
Hmm. I'm actually thinking the exact opposite here. My rationale
for putting the response as a standard HTTP 302/303 style redirect
is to permit hardware load balancers or Apache mod_rewrite rules
to implement simple load balancing with a HTTP redirect.
If we embed the redirect URL into the payload then configuring that
will become a lot more complex. At the minimum you may have to
make up a dummy file for each server (holding the response payload)
then then let mod_rewrite rewrite the request internally to make
Apache serve that file. Ugly.
No, you're thinking backwards. What you want is the standard HTTP redirect load balancing to take effect *before* the initial request is serviced. The front-end load balancer will take effect on the initial request, and then redirect the request to a node (via a 302 reply.) The target node then sends a self-referencing URL to keep the service local, if that is desired -- otherwise it doesn't.
Again, the 300-class redirect is treated as a part of the HTTP transport in this case; it doesn't have to be visible to the RPC layer. However, in order to maintain the integrity of an interchange, we do need an additional level of redirection visible to the RPC layer.
If we embed the redirect URL into the payload then configuring that
will become a lot more complex. At the minimum you may have to
make up a dummy file for each server (holding the response payload)
then then let mod_rewrite rewrite the request internally to make
Apache serve that file. Ugly.
A very simple CGI/PHP script will do this, and it's really very very trivial to set up.
Please keep in mind I'm not talking hypotheticals at all. What you have proposed is actually a lot uglier for kernel.org to implement, simply because we try to stay with strict IP-based vhosting
-hpa
From: Nicolas Pitre <hidden> Date: 2016-06-15 22:45:13
On Mon, 25 Aug 2008, david@lang.hm wrote:
and for cloneing (and especially thing like linux-next where you essentially
re-clone daily) letting the pack get cached is probably a very good thing.
I hope that people recloning linux-next daily are very few. This is an
incredible waste of bandwidth, regardless of the protocol used, dumb or
not. A standard fetch with a remote tracking branch (with -f or with a
plus sign on the "fetch" line in your config file) should be all that's
needed to significantly reduce the amount of data needed to transfer.
Nicolas
From: Shawn O. Pearce <hidden> Date: 2016-06-15 22:45:13
Nicolas Pitre [off-list ref] wrote:
On Mon, 25 Aug 2008, david@lang.hm wrote:
quoted
and for cloneing (and especially thing like linux-next where you essentially
re-clone daily) letting the pack get cached is probably a very good thing.
I hope that people recloning linux-next daily are very few. This is an
incredible waste of bandwidth, regardless of the protocol used, dumb or
not. A standard fetch with a remote tracking branch (with -f or with a
plus sign on the "fetch" line in your config file) should be all that's
needed to significantly reduce the amount of data needed to transfer.
Or at least clone with --reference. You get about the same benefit if
your local reference repository is fairly current, say with a stable
upstream like Linus' own tree.
--
Shawn.
From: Shawn O. Pearce <hidden> Date: 2016-06-15 22:45:13
"H. Peter Anvin" [off-list ref] wrote:
Shawn O. Pearce wrote:
quoted
Hmm. I'm actually thinking the exact opposite here. My rationale
for putting the response as a standard HTTP 302/303 style redirect
is to permit hardware load balancers [...]
to implement simple load balancing with a HTTP redirect.
No, you're thinking backwards. What you want is the standard HTTP
redirect load balancing to take effect *before* the initial request is
serviced.
...
Please keep in mind I'm not talking hypotheticals at all. What you have
proposed is actually a lot uglier for kernel.org to implement, simply
because we try to stay with strict IP-based vhosting
@@ -43,14 +43,34 @@ All requests/responses use "application/x-git" as the content type. Action specific subtypes are specified by the parameter "service", e.g. "application/x-git; service=upload-pack".+HTTP Redirects+--------------++If a POST request results in an HTTP 302 or 303 redirect response+clients should retry the request by updating the URL and POSTing+the same request to the new location. Subsequent requests should+still be sent to the original URL.+ Detecting Smart Servers ----------------------- HTTP clients can detect a smart Git-aware server by sending a request to service "show-ref".-A Git-aware server will respond with a valid response (see below).-A dumb server should respond with an error message. +A Git-aware server will respond with a valid response. Clients+must check the following properties to prevent being fooled by+misconfigured servers:++ * HTTP status code is 200.+ * Content-Type is "application/x-git; service=show-ref"+ * The body can be parsed without errors. The length of+ each pkt-line must be 4 valid hex digits.++A dumb server will respond with a non-200 HTTP status code.+A misconfigured server may respond with a normal 200 status+code, but an incorrect content type, or an invalid leading+4 byte sequence for a pkt-line (e.g. "<htm" or "<!DO" are+not valid lengths). Service show-ref ----------------
@@ -62,15 +82,46 @@ Content-Type: application/x-git; service=show-ref The request is an empty body.-The response is a sequence of refs, one per Git packet line.-The final packet line has a length of 0 to indicate the end.+The response is a pkt-line with "refs", followed by zero+or more ref pkt-lines ("$id $name"), and a final pkt-line+with a length of 0:+ S: 0009refs S: 003295dcfa3633004da0049d3d0fa03f80589cbcaf31 HEAD S: 003e95dcfa3633004da0049d3d0fa03f80589cbcaf31 refs/heads/maint S: 003fd049f6c27a2244e12041955e262a404c7faba355 refs/heads/master S: 003b2cb58b79488a98d2721cea644875a8dd0026b115 refs/heads/pu S: 0000+The response may begin with an optional redirect to a new service+URL for the repository:++ S: 0028redirect http://s1.example.com/git/+ S: 0009refs+ S: 003295dcfa3633004da0049d3d0fa03f80589cbcaf31 HEAD+ S: 003fd049f6c27a2244e12041955e262a404c7faba355 refs/heads/master+ S: 0000++or be composed of only a redirect:++ S: 0028redirect http://s1.example.com/git/+ S: 0000++If a redirect is returned the client should update itself+to use the new URL as the location for future requests.+A server may use the redirect to request that the client+"pin" itself to a particular server for the remainder of+the current transaction.++The URL listed in any redirect should be the base URL+without any query args. The client will automatically+append "/backend.git-http/$service" as it makes each+future request.++If no "refs" line was received in the response, but+a "redirect" was received, the client should retry+its request at the new location before giving up.+ Service upload-pack -------------------
This looks really good! The redirect idea just seems cool!
- Imran
-hpa
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
From: Shawn O. Pearce <hidden> Date: 2016-06-15 22:45:14
"H. Peter Anvin" [off-list ref] wrote:
Looks great to me.
So this is what may be the final draft of the HTTP protocol.
I've added stuff about capability selection between the peers for
future expansion support. The upload-pack service has a better
use of it than receive-pack. Otherwise it is what I think you are
agreeing to above. ;-)
I'm hoping to start implementating a prototype of this on Friday.
I may do it in JGit first; the transport infrastructure there is
a lot more modular so experimentation should be quicker. I would
obviously also implement it in C Git, unless someone else comes
along and beats me to it. This project is only a fraction of my
total Git time in any given week. :-|
--8<--
Smart HTTP transfer protocols
=============================
Git supports two HTTP based transfer protocols. A "dumb" protocol
which requires only a standard HTTP server on the server end of the
connection, and a "smart" protocol which requires a Git aware CGI
(or server module). This document describes the "smart" protocol.
As a design feature smart clients can automatically translate and
upgrade "dumb" protocol URLs. This permits all users to have the
same published URL, with the peers automatically choosing to use
the most efficient transport available to them.
HTTP Transport
--------------
All requests are encoded as HTTP POST requests to the smart service
URL, "$url/backend.git-http/$service".
All responses are encoded as 200 Ok responses, even if the server
side has "failed" the request. Service specific success/failure
codes are embedded in the content.
Authentication
--------------
Standard HTTP authentication is used if authentication is required
to access a repository, and must be configured and enforced by the
HTTP server software itself.
Stateless
---------
The protocol, much like its underlying HTTP, is stateless, from the
perspective of the HTTP server side. All state must be retained and
managed by the client. This permits round-robin load-balancing on
the server side, among many other implementation details.
Content Type
------------
All requests/responses use "application/x-git" as the content type.
Action specific subtypes are specified by the parameter "service",
e.g. "application/x-git; service=upload-pack".
HTTP Redirects
--------------
If a POST request results in an HTTP 302 or 303 redirect response
clients should retry the request by updating the URL and POSTing
the same request to the new location. Subsequent requests should
still be sent to the original URL.
Detecting Smart Servers
-----------------------
HTTP clients can detect a smart Git-aware server by sending
a request to service "show-ref".
A Git-aware server will respond with a valid response. Clients
must check the following properties to prevent being fooled by
misconfigured servers:
* HTTP status code is 200.
* Content-Type is "application/x-git; service=show-ref"
* The body can be parsed without errors. The length of
each pkt-line must be 4 valid hex digits.
A dumb server will respond with a non-200 HTTP status code.
A misconfigured server may respond with a normal 200 status
code, but an incorrect content type, or an invalid leading
4 byte sequence for a pkt-line (e.g. "<htm" or "<!DO" are
not valid lengths).
Service show-ref
----------------
Obtains the available refs from the remote repository.
URL: $url/backend.git-http/show-ref
Content-Type: application/x-git; service=show-ref
The request is an empty body.
The response is a pkt-line with "refs", followed by zero
or more ref pkt-lines ("$id $name"), and a final pkt-line
with a length of 0:
S: 0009refs
S: 003295dcfa3633004da0049d3d0fa03f80589cbcaf31 HEAD
S: 003e95dcfa3633004da0049d3d0fa03f80589cbcaf31 refs/heads/maint
S: 003fd049f6c27a2244e12041955e262a404c7faba355 refs/heads/master
S: 003b2cb58b79488a98d2721cea644875a8dd0026b115 refs/heads/pu
S: 0000
The response may begin with an optional redirect to a new service
URL for the repository:
S: 0028redirect http://s1.example.com/git/
S: 0009refs
S: 003295dcfa3633004da0049d3d0fa03f80589cbcaf31 HEAD
S: 003fd049f6c27a2244e12041955e262a404c7faba355 refs/heads/master
S: 0000
or be composed of only a redirect:
S: 0028redirect http://s1.example.com/git/
S: 0000
If a redirect is returned the client should update itself
to use the new URL as the location for future requests.
A server may use the redirect to request that the client
"pin" itself to a particular server for the remainder of
the current transaction.
The URL listed in any redirect should be the base URL
without any query args. The client will automatically
append "/backend.git-http/$service" as it makes each
future request.
If no "refs" line was received in the response, but
a "redirect" was received, the client should retry
its request at the new location before giving up.
Service upload-pack
-------------------
Prepares an estimated minimal pack to transfer new objects to the
client.
URL: $url/backend.git-http/upload-pack
Content-Type: application/x-git; service=upload-pack
The computation to select the minimal pack proceeds as follows
(c = client, s = server):
init step:
(c) Use show-ref to obtain the advertised refs.
(c) Place any object seen in show-ref into set ADVERTISED.
(c) Build a set, WANT, of the objects from ADVERTISED the client
wants to fetch, based on what it saw from show-ref.
(c) Start a queue, C_PENDING, ordered by commit time (popping newest
first). Add all client refs. When a commit is popped from the
queue its parents should be automatically inserted back. Commits
should only enter the queue once.
one compute step:
(c) Send an upload-pack request:
C: 0011capabilities
C: 0024thin-pack include-tag ofs-delta
C: 0009want
C: 0xxx<WANT list>
C: 000bcommon
C: 0xxx<COMMON list>
C: 0009have
C: 0xxx<HAVE list>
C: 0000
The stream is organized into "sections", where each section is
composed of two git pkt-lines. The first pkt-line provides the
name of the section ("capabilities", "want", "have", "common").
The second pkt-line has the binary SHA-1 ids which compose that
section.
The "want" section is required. The other sections ("have",
"common") are optional. A missing "want" section should be
answered with an error.
Sections must appear in the following order, if they appear
at all in the request stream:
* capabilities
* want
* common
* have
Each section may appear multiple times. Client implementions
are encouraged to use as few sections as possible, however the
limit of 64k per pkt-line limits the number of ids to 3,276 per
section entry.
The stream is terminated by a pkt-line flush ("0000").
The HAVE list is created by popping the first 256 commits
from C_PENDING. Less can be supplied if C_PENDING empties.
(s) Parse the upload-pack request:
Verify all objects in WANT are reachable from refs. As
this may require walking backwards through history to
the very beginning on invalid requests the server may
use a reasonable limit of commits (e.g. 1000) walked
beyond any ref tip before giving up.
If no WANT objects are received, send an error:
S: 0019status error no want
If any WANT object is not reachable, send an error:
S: 001estatus error invalid want
Create an empty list, S_COMMON.
If 'common' was sent:
Load all objects into S_COMMON.
If 'have' was sent:
Loop through the objects in the order supplied by the client.
For each object, if the server has the object reachable from
a ref, add it to S_COMMON. If a commit is added to S_COMMON,
do not add any ancestors, even if they also appear in HAVE.
(s) Send the upload-pack response:
If the server has found a closed set of objects to pack, it
replies with the pack and the enabled capabilities. The set
of enabled capabilities is limited to the intersection of
what the client requested and what the server supports.
S: 0010status pack
S: 0011capabilities
S: 0024thin-pack include-tag ofs-delta
S: 000c.PACK...
The returned stream is the side-band-64k protocol supported
by the git-upload-pack service, and the pack is embedded into
stream 1. Progress messages from the server side may appear
in stream 2.
If the server wants more information, it replies with a
status continue response:
S: 0014status continue
S: 000bcommon
S: 0xxx<S_COMMON list>
S: 0000
The stream formatting rules are the same as the request.
The section "common" details the contents of S_COMMON,
that is all objects from HAVE that the server also has.
(c) Parse the upload-pack response:
If the status pkt-line is "status pack:"
Process the pack stream and update the local refs.
If the status pkt-line is "status continue":
Reset COMMON to the items in S_COMMON. The new S_COMMON
should be a superset of the existing COMMON set.
Remove all items in S_COMMON, and all of their ancestors,
from PENDING.
Do another compute step.
Service receive-pack
--------------------
Uploads a pack and updates refs.
URL: $url/backend.git-http/receive-pack
Content-Type: application/x-git; service=receive-pack
The start of the stream is the commands to update the refs and
the remainder of the stream is the pack file itself. See
git-receive-pack and its network protocol in pack-protocol.txt,
as this is essentially the same.
C: 0011capabilities
C: 0005
C: 006395dcfa3633004da0049d3d0fa03f80589cbcaf31 d049f6c27a2244e12041955e262a404c7faba355 refs/heads/maint
C: 0000
C: PACK...
S: 0011capabilities
S: 0005
S: ...<output of receive-pack>...
The capabilities are handled exactly as in the fetch protocol,
however the server may reject a pack and its associated commands
if an invalid capability request is made by the client, or the
client has assumed a pack capability that the server does not
have support for. In the latter case the server must still send
the capabilities key in the response so the client can correct
itself and try again.
--
Shawn.
From: "H. Peter Anvin" <hpa@zytor.com> Date: 2016-06-15 22:45:14
Shawn O. Pearce wrote:
So this is what may be the final draft of the HTTP protocol.
I've added stuff about capability selection between the peers for
future expansion support. The upload-pack service has a better
use of it than receive-pack. Otherwise it is what I think you are
agreeing to above. ;-)
It looks good to me. I *really* like the option of combining a redirect with a refs list in one reply; this will make things substantially easier do deploy on kernel.org, and saves a round trip to boot.
Just an implementation detail for the server, however: for an *empty* repository (one which has no refs at all), the server needs to *not* transmit the redirect, or there will be a loop :) It is unnecessary, anyway, since there is inherently nothing to do.
-hpa
From: Shawn O. Pearce <hidden> Date: 2016-06-15 22:45:14
"H. Peter Anvin" [off-list ref] wrote:
Shawn O. Pearce wrote:
quoted
So this is what may be the final draft of the HTTP protocol.
It looks good to me. I *really* like the option of combining a redirect
with a refs list in one reply; this will make things substantially
easier do deploy on kernel.org, and saves a round trip to boot.
Yea, I had a draft that didn't combine these and I realized how
stupid that was. So I allowed them to appear together if the
server operator wants to do that.
Just an implementation detail for the server, however: for an *empty*
repository (one which has no refs at all), the server needs to *not*
transmit the redirect, or there will be a loop :) It is unnecessary,
anyway, since there is inherently nothing to do.
Actually that's not true. A correct client won't loop.
An empty repository is required to send "refs" section header.
So the client will see the "refs" header and know that the complete
set of refs is following. Only nothing follows, so it knows the
complete set is the empty set.
A redirect with no ref data won't have the "refs" section header.
So the client knows that it cannot conclude anything from that
exchange and must follow the redirect.
An empty repository sending a redirect will send both "redirect"
and "refs", but no refs follow the "refs" section header. So the
client knows that it is empty and it does not need to follow the
redirect it received.
Now if the server is stupid and keeps sending a redirect with no
refs header, yea, the client can loop. So the clients should have
a maximum recursion limit configured into them, just like a good
browser would, so you can't get stuck in an A->B->C->A loop.
--
Shawn.
From: "H. Peter Anvin" <hpa@zytor.com> Date: 2016-06-15 22:45:14
Shawn O. Pearce wrote:
quoted
Just an implementation detail for the server, however: for an *empty* repository (one which has no refs at all), the server needs to *not* transmit the redirect, or there will be a loop :) It is unnecessary, anyway, since there is inherently nothing to do.
Actually that's not true. A correct client won't loop.
An empty repository is required to send "refs" section header.
So the client will see the "refs" header and know that the complete
set of refs is following. Only nothing follows, so it knows the
complete set is the empty set.
A redirect with no ref data won't have the "refs" section header.
So the client knows that it cannot conclude anything from that
exchange and must follow the redirect.
From: Imran M Yousuf <hidden> Date: 2016-06-15 22:45:15
On Thu, Aug 28, 2008 at 10:37 AM, H. Peter Anvin [off-list ref] wrote:
Shawn O. Pearce wrote:
quoted
So this is what may be the final draft of the HTTP protocol.
I've added stuff about capability selection between the peers for
future expansion support. The upload-pack service has a better
use of it than receive-pack. Otherwise it is what I think you are
agreeing to above. ;-)
It looks good to me. I *really* like the option of combining a redirect
with a refs list in one reply; this will make things substantially easier do
deploy on kernel.org, and saves a round trip to boot.
I agree, this is a very cool feature of the protocol...
- Imran
Just an implementation detail for the server, however: for an *empty*
repository (one which has no refs at all), the server needs to *not*
transmit the redirect, or there will be a loop :) It is unnecessary,
anyway, since there is inherently nothing to do.
-hpa
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
--
Imran M Yousuf
Entrepreneur & Software Engineer
Smart IT Engineering
Dhaka, Bangladesh
Email: imran@smartitengineering.com
Blog: http://imyousuf-tech.blogs.smartitengineering.com/
Mobile: +880-1711402557
From: "H. Peter Anvin" <hpa@zytor.com> Date: 2016-06-15 22:56:09
Hi Shawn,
You wrote a really great protocol spec for the smart HTTP protocol back
in the day. It would be really great if it could be checked into the
git repository (updated if need be). Someone mentioned today trying to
reverse-engineer the protocol because of a lack of specs, and I was a
bit surprised to day the least.
-hpa
Hi Shawn,
You wrote a really great protocol spec for the smart HTTP protocol back
in the day. It would be really great if it could be checked into the
git repository (updated if need be). Someone mentioned today trying to
reverse-engineer the protocol because of a lack of specs, and I was a
bit surprised to day the least.
-hpa
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html