Git HTTP Backend

raw JSON →
1.1.2 verified Thu Apr 23 auth: no javascript maintenance

`git-http-backend` is a Node.js library designed to facilitate serving Git repositories over HTTP, providing a programmatic interface to the underlying Git protocol. It enables developers to construct custom HTTP Git servers, allowing them to either integrate their own `git-receive-pack` and `git-upload-pack` implementations or to delegate these operations to the system's installed Git executables. The package abstracts the complexities of the Git HTTP protocol, primarily by streaming request and response data. As of the provided metadata, the current stable version is 1.1.2. Its release cadence appears to be infrequent, reflecting its role as a focused utility. A key differentiator is its minimalist design, which offers core protocol parsing and streaming capabilities without imposing a complete server framework, thus allowing for flexible integration into existing Node.js HTTP server applications.

error Error: Cannot find module 'git-http-backend'
cause The 'git-http-backend' package has not been installed in your project's `node_modules`.
fix
Run npm install git-http-backend or yarn add git-http-backend in your project directory.
error fatal: repository 'http://localhost:5000/myrepo.git/' not found
cause The requested Git repository path either does not exist on the server's filesystem, or the server's `repos` directory mapping is incorrect.
fix
Verify that the bare Git repository (myrepo.git) exists at the specified dir path on the server. Ensure the req.url parsing correctly extracts the repository name and maps it to a valid physical location.
error git remote: error: unpack failed: unpack-objects abnormal exit
cause This error typically indicates an issue during the `git-receive-pack` process on the server, often due to corrupted data, disk space issues, or incorrect permissions on the repository directory.
fix
Check server logs for more detailed git-receive-pack errors. Verify that the user running the Node.js server has write permissions to the repository directory and that there is sufficient disk space.
error http.createServer(function (req, res) { ... }): service.type is undefined
cause The `service` object's `type` property is crucial for setting the HTTP `Content-Type` header, and if it's `undefined`, it suggests the `git-http-backend` failed to parse the Git service request correctly.
fix
Ensure req.url is correctly structured for Git HTTP requests (e.g., /repo.git/info/refs?service=git-upload-pack) and that the incoming request body (if any) is valid. Debug the backend(req.url, cb) call to inspect the err object.
gotcha This package relies on shelling out to system `git-{receive,upload}-pack` executables. Improper input validation or misconfiguration could lead to command injection vulnerabilities if `service.cmd` or `service.args` are manipulated by malicious clients.
fix Ensure robust input validation and sanitization for all request parameters, especially if `git` command arguments are derived from user input. Consider implementing a whitelist for allowed commands and arguments.
gotcha The library itself does not provide any authentication or authorization mechanisms. Deploying a `git-http-backend` server without implementing custom security layers (e.g., HTTP Basic Auth, token-based auth) will expose all hosted repositories publicly.
fix Implement authentication and authorization middleware in your HTTP server *before* piping requests to `git-http-backend` to secure access to repositories based on user permissions.
gotcha The package is designed for CommonJS (`require`). Attempting to use `import` statements directly in a pure ESM Node.js project will result in a `TypeError: require is not a function` or similar module resolution errors.
fix For ESM projects, use dynamic `import('git-http-backend')` or ensure your build setup correctly handles CommonJS modules. The simplest fix for hybrid projects is to stick to `require()` or use a transpiler.
gotcha The provided example only explicitly handles `gzip` for incoming `Content-Encoding`. Other compression types (e.g., `deflate`, `br`) will not be automatically decompressed, potentially leading to issues with clients using those encodings.
fix Extend the request stream handling to detect and decompress other `Content-Encoding` types using appropriate Node.js `zlib` methods (e.g., `createInflateRaw()` for deflate, `createBrotliDecompress()` for brotli).
npm install git-http-backend
yarn add git-http-backend
pnpm add git-http-backend

This example demonstrates how to set up a basic HTTP server using `git-http-backend` to serve Git repositories, including handling gzipped requests and spawning system Git commands for push and pull operations.

var http = require('http');
var spawn = require('child_process').spawn;
var path = require('path');
var backend = require('git-http-backend');
var zlib = require('zlib');

var server = http.createServer(function (req, res) {
    var repo = req.url.split('/')[1];
    var dir = path.join(__dirname, 'repos', repo);
    // Handle gzipped content for incoming requests
    var reqStream = req.headers['content-encoding'] == 'gzip' ? req.pipe(zlib.createGunzip()) : req;
    
    reqStream.pipe(backend(req.url, function (err, service) {
        if (err) return res.end(err + '\n');
        
        res.setHeader('content-type', service.type);
        console.log(service.action, repo, service.fields);
        
        // Spawn system git command based on service detected
        var ps = spawn(service.cmd, service.args.concat(dir));
        // Pipe the service stream (request data) into git's stdin
        // Pipe git's stdout into the service's response stream
        ps.stdout.pipe(service.createStream()).pipe(ps.stdin);
        
    })).pipe(res);
});
server.listen(5000);

// To set up and use:
// 1. Create a directory for repositories: `mkdir repos`
// 2. Initialize a bare Git repository: `git init repos/myrepo.git --bare -q`
// 3. Run the server: `node server.js &`
// 4. Push to it: `cd my/local/project && git push http://localhost:5000/myrepo.git master`
// 5. Clone from it: `git clone http://localhost:5000/myrepo.git`