Hosting¶
GitServer.Create() returns a builder that follows the conventions of all GenHTTP modules: configure it, add it to
your handler tree and optionally add concerns.
A single repository¶
The repository is served at the path the handler is mounted at. Added to a layout as repo, clients clone it from
https://example.com/repo. The handler only answers the requests sent by git (info/refs, git-upload-pack and
git-receive-pack) and returns nothing for all other requests, so other handlers can serve content at the same path.
Multiple repositories¶
var git = GitServer.Create()
.Repositories(async (request, name) => await _store.FindRepositoryAsync(name));
var app = Layout.Create()
.Add("git", git);
// git clone https://example.com/git/my-project.git
// git clone https://example.com/git/my-project
The function receives the first segment of the path below the handler, without a .git suffix. Return null for
unknown repositories, which results in a "not found" response.
Resolving repositories per request¶
To decide based on the request (e.g. a key routed by another handler, or the authenticated user), pass a function receiving the request:
Return null to respond with "not found". To deny access, throw a ProviderException with the appropriate status
code. The function is invoked for every request, so a client performing a clone causes multiple invocations (one
for the references, one or more for the data).
Authentication¶
Git sends credentials via HTTP basic authentication, so the authentication concerns of GenHTTP can be used:
var git = GitServer.Create()
.Repository(repository)
.Add(BasicAuthentication.Create().Add("jane", "secret"));
// or with a custom check, returning the authenticated user (or null)
var git = GitServer.Create()
.Repository(repository)
.Add(BasicAuthentication.Create((user, password) => CheckAsync(user, password)));
Clients are challenged when they connect without credentials and ask the user or their credential helper for them.
The authenticated user is available to resolvers via request.GetUser<IUser>(). To
grant different permissions to different users (e.g. read-only access for some), resolve the repository per request
and return an instance that only implements IGitRepository for read-only users.
Secrets in URLs
Instead of credentials, a repository can also be addressed by a secret part of its URL (as with a private link).
Keep in mind that git stores the URL in .git/config and that URLs show up in logs and shell histories.
Limits¶
| Method | Default | Description |
|---|---|---|
MaximumPushSize(bytes) |
128 MB | The maximum size of a push. Pushes are processed in memory. |
MaximumFilesPerCommit(n) |
100,000 | The maximum number of files of a pushed commit. |
MaximumRequestSize(bytes) |
16 MB | The maximum size of a fetch request, which lists commits the client wants and has. |
ContentCache(bytes) |
64 MB | How much file content is kept in memory per request to avoid reading files twice. |
Requests exceeding a size limit are answered with HTTP 413, pushed commits with too many files are rejected.
Additionally, the server protects itself against crafted requests: a fetch request may list at most 100,000 commits the client has, pack headers may not claim more data than they contain, and objects the client did not send are only searched for in the newest 10,000 commits of the repository.
Other settings¶
| Method | Default | Description |
|---|---|---|
Agent(agent) |
genhttp-git/x.y.z |
The agent announced to clients, for statistics and debugging only. |
Compression(level) |
Fastest |
How strongly objects sent to clients are compressed. |
Engines and concerns¶
The handler works with all GenHTTP engines and can also be used within an ASP.NET Core application, see
ASP.NET Core. Concerns such as compression or client caching added via Defaults() do
not interfere with git: responses are marked as not cacheable, and request bodies compressed by git are detected
regardless of whether a decompression concern already handled them.
Logging¶
Errors are logged via the logging infrastructure of the server (IServer.Logging). Clients only receive generic
messages for unexpected errors, so check the log if a client reports "internal server error" or "the repository is
inconsistent".