123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103 |
- "use strict";
- var makeChannel = require('culvert');
- var bodec = require('bodec');
- var pktLine = require('../lib/pkt-line');
- var wrapHandler = require('../lib/wrap-handler');
- module.exports = function (request) {
- return function httpTransport(gitUrl, username, password) {
- // Send Auth header if username is set
- var auth;
- if (username) {
- auth = "Basic " + btoa(username + ":" + (password || ""));
- }
- return function (serviceName, onError) {
- // Wrap our handler functions to route errors properly.
- onResponse = wrapHandler(onResponse, onError);
- onWrite = wrapHandler(onWrite, onError);
- onResult = wrapHandler(onResult, onError);
- // Create a duplex channel with transform for internal use.
- var serverChannel = makeChannel();//0, "server");
- var clientChannel = makeChannel();//0, "client");
- var socket = {
- put: serverChannel.put,
- drain: serverChannel.drain,
- take: clientChannel.take
- };
- // Send the initial request to start the connection.
- var headers = {};
- if (auth) headers.Authorization = auth;
- request("GET", gitUrl + "/info/refs?service=" + serviceName, headers, onResponse);
- // Prep for later requests
- var bodyParts = [];
- var bodyWrite = pktLine.framer(function (chunk) {
- bodyParts.push(chunk);
- });
- headers["Content-Type"] = "application/x-" + serviceName + "-request";
- socket.take(onWrite);
- var verified = 0;
- var parseResponse = pktLine.deframer(function (line) {
- if (verified === 2) {
- socket.put(line);
- }
- else if (verified === 0) {
- if (line !== "# service=" + serviceName) {
- throw new Error("Illegal service response");
- }
- verified = 1;
- }
- else if (verified === 1) {
- if (line !== null) {
- throw new Error("Expected null after service name");
- }
- verified = 2;
- }
- });
- // Return the other half of the duplex channel for the protocol logic to use.
- return {
- put: clientChannel.put,
- drain: clientChannel.drain,
- take: serverChannel.take
- };
- function onResponse(res) {
- if (res.statusCode !== 200) {
- throw new Error("Invalid response: " + res.statusCode);
- }
- if (res.headers["content-type"] !== "application/x-" + serviceName + "-advertisement") {
- throw new Error("Not a smart http git server");
- }
- parseResponse(res.body);
- }
- function onWrite(item) {
- if (item === undefined) return socket.put();
- bodyWrite(item);
- socket.take(onWrite);
- if (item !== "done\n" || !bodyParts.length) return;
- var body = bodec.join(bodyParts);
- bodyParts.length = 0;
- request("POST", gitUrl + "/" + serviceName, headers, body, onResult);
- }
- function onResult(res) {
- if (res.statusCode !== 200) {
- throw new Error("Invalid result: " + res.statusCode);
- }
- if (res.headers["content-type"] !== "application/x-" + serviceName + "-result") {
- throw new Error("Not a smart http git server");
- }
- parseResponse(res.body);
- }
- };
- };
- };
|